Introduction
As developers, we should normally strive to write code that is as clear and easy-to-read as possible. This makes it easier for ourselves and other developers to more easily understand that code, which then makes it easier to make changes and with less chance of errors.
But there are actually a few cases where you might want to make your code a little less clear. For example, let's say you write a shareware program that requires a registration key to fully activate the program. A hacker might step through your code to understand how it works so that they might be able to activate the software without purchasing a registration key. In this case, your software might actually benefit by making it harder for the hacker to understand what your program does.
Swapping Variables
The scenario above is one example where you might want to make debugging your code a little bit more difficult by making the purpose of the software instructions a little less obvious. In this article, we will look at ways to obfuscate (make more difficult to understand) code for swapping the values of two variables. Although you might not really need a swap, a swap can be used instead of direct assignments to make the purpose of your code less clear.
Listing 1 shows a traditional way to swap two variables. It uses a temporary variable to hold the initial value of x, assigns the value of y to x, and finally it assigns the value in the temporary variable to y. Upon completion, x now holds that value that was in y and y now holds the value that was in x.
Listing 1: Swapping Two Variables the Traditional Way
int temp = x;
x = y;
y = temp;
A hacker debugging your software will readily be able to see that this code is swapping the value of two variables. Listing 2 shows another way to swap two variables. It uses addition and subtraction to make the swap less obvious.
This version starts by adding y to x. It then assigns the value of x, less the value of y, to y. And finally, it subtracts the new value of y from x. Again, the result is that x now holds that value that was in y, and y now holds the value that was in x.
Listing 2: Using Addition and Subtraction to Swap Two Variables
x += y;
y = (x - y); // y gets value of x
x -= y; // x gets value of y
A hacker is likely to find the code above significantly less obvious with regard to what it does. But we can do better. Listing 3 uses the XOR swap algorithm to swap two variables.
An XOR operation outputs a 0 where the two input bits are the same, and outputs a 1 where the two input bits are different. The XOR swap algorithm is very unintuitive, and can be used to create a swap routine that is even more obfuscated.
Listing 3: Using XOR to Swap Two Variables
x ^= y;
y ^= x;
x ^= y;
It's also worth noting that the swap code in Listings 2 and 3 do not require any additional variables, while the code in Listing 1 does. Under normal circumstances this is not a consideration, and we are more concerned here with how easily a hacker can understand what the code does. However, there may be rare circumstances where not requiring an additional variable does provide an advantage.
Using Obfuscated Swaps in Your Code
When trying to make your code more obfuscated to hackers trying to debug it, it would be nice if you could do it in a way that your original code is still clear and easy to understand by you. With regards to the swap routines, a good way to do that is to put the swapping code in an inline method. This way, the obfuscated code doesn't appear directly within the code that uses it, but making it inline means the swapping code will be inserted directly into the code that uses. This should give you the best of both worlds.
Listing 4 tests the swap routines above. It places the swap routines in inline methods, making the original source code easier to understand.
Listing 4: Testing the Swap Code using Inline Methods
#include "stdafx.h"
#include <stdio.h>
inline void TraditionalSwap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
inline void ObfuscatedSwap(int& x, int& y)
{
x += y;
y = (x - y);
x -= y;
}
inline void ObfuscatedSwap2(int& x, int& y)
{
x ^= y;
y ^= x;
x ^= y;
}
int _tmain(int argc, _TCHAR* argv[])
{
int x = 123, y = 456;
_tprintf(_T("Initial Values: x = %d, y = %d\n"), x, y);
TraditionalSwap(x, y);
_tprintf(_T("After TraditionalSwap(): x = %d, y = %d\n"), x, y);
ObfuscatedSwap(x, y);
_tprintf(_T("After ObfuscatedSwap(): x = %d, y = %d\n"), x, y);
ObfuscatedSwap2(x, y);
_tprintf(_T("After ObfuscatedSwap2(): x = %d, y = %d\n"), x, y);
getchar();
}
And here is the output from the code above.
Initial Values: x = 123, y = 456
After TraditionalSwap(): x = 456, y = 123
After ObfuscatedSwap(): x = 123, y = 456
After ObfuscatedSwap2(): x = 456, y = 123
Conclusion
It is worth pointing out that a good optimzing compiler might optimize away your obfuscated code. For that reason, it might be worth wrapping your swap methods in a pragma that prevents optimization of that particular code, or even using inline assembler.
Of course, using XOR swapping won't make your application impenetrable to hackers. However, it can be included as one of many techniques to make it more difficult for a hacker to figure out what your code is doing, thereby requiring more effort to thwart possible security measures that are part of your application.
End-User License
Use of this article and any related source code or other files is governed
by the terms and conditions of
.
Author Information
Jonathan Wood
I'm a software/website developer working out of the greater Salt Lake City area in Utah. I've developed many websites including Black Belt Coder, Insider Articles, and others.