开发者

C: Obfuscating an integer

开发者 https://www.devze.com 2022-12-19 23:05 出处:网络
If I have an integer like this in several places in my code... int my_secret = 42; ... is it possible to make it more difficult to find that integer in the compiled program? I\'ve seen this开发者_运

If I have an integer like this in several places in my code...

int my_secret = 42;

... is it possible to make it more difficult to find that integer in the compiled program? I've seen this开发者_运维百科 done with strings, for example by shifting each letter by x characters and then un-shifting them at runtime, but I doubt this technique would work well with numbers.


This never works. Secret keys should never, ever be in code. Creating them at runtime works. Obfuscation is surely tempting providence.


You can do this by splitting this value between two variables. For instance like this:

volatile int my_secret_1 = 20;
volatile int my_secret_2 = 22;

and then use my_secret_1 + my_secret_2 instead of my_secret.

The volatile keyword is needed because most of (if not all) the c compilers would optimize it otherwise. In any way it is better to see what assembler code is produced by a compiler.


You could calculate it at runtime via some function the compiler can't optimize such using the square of the number and then taking the square root via a math library function.

Of course the problem is that none of this type of stuff will stop a determined person.

It could also be argued that you really don't need to bother. Obfuscating a string makes a lot of sense because there are tons of easy to use tools that will dump strings from an exe. Your 42 however will just be encoded as a binary number. The whole exe is just a long sequence of binary numbers and there isn't a simple tool to search for the 42. You would have to disassemble the exe and understand the assembly. Anyone who is going to go through that much trouble is likely to figure out the number no matter what you do.

So the short answer is don't bother it's obfuscated enough for casual use.


The initial question in Hassan's comment is the critical one. It depends on what you're keeping secret, and why, as to how much work is -worth it-. Generally speaking, hiding something from someone who is using the program which (at some point) puts those values together is impossible to do forever. You can make it harder for an attacker, however.

The question then becomes how much work you want to go to in order to make it harder for that attacker. You can then do anything from code obfuscation (not very secure, but may deter a very casual attacker and is relatively easy to do, especially since the original source can be commented with what's going on) to full on encryption and some of the "black box" type methods that have been used for copy protection (though even those are ultimately breakable) to, if this is critical enough, providing this as something to the effect of a web service where the code is not going to the end user. Even that isn't always failsafe.

So, how secret do you want your secret, and how much work are you willing to put into trying to keep it that way?


I've heard of people using self-modifying code for obfuscation purposes. As others have said, someone determined enough can still crack it, but it makes life tougher on a would-be attacker if they can't even see the final code disassembled or set breakpoints in it. (Setting a breakpoint amounts to replacing a byte of memory with an INT 3 instruction; if that memory gets modified as part of a self-modifying code operation, the breakpoint will disappear, possibly corrupting the instructions there and leading to even more fun.)

It's still possible to single-step through the code in a debugger. To partially counteract that, you can test IsDebuggerPresent() occasionally and lead the attacker on a wild goose chase if so. Of course this too can be counter-counteracted, e.g. by DLL shimming or even creating a low-level device driver if necessary.


There is no way to completely hide such secrets from determined attackers, but there are ways to raise the bar (which might sometimes serve as both a deterrent, and a temporary measure.)

The simplest way for doing this is by applying one-time-pads like XOR.

int pad = 322;
int secret = 360;
int value = pad ^ secret; // This is 42

You can add combinations of such one-time-pads, along with obfuscated cryptographic functions to make it harder for an attacker to find the value.

Note that although this makes it harder for attackers to derive the key by looking at the compiled code, they can still attach a debugger to a running process and pull the computed key right out of memory. In fact, there are debuggers (such as IDA pro) that make stuff like this almost trivial.

You also have to worry about the OS paging your key to disk after it has been computed, which can be extracted quite trivially. (Using something like mlock() to lock pages to memory can help you with this.)

Anyhow, this is a very tricky problem, one that many software authors are battling with to implement unintrusive (e.g., no validating keys over the network) licensing schemes.


How to use the ones complement

int secret = ~42;
printf("%0X %0x" , secret , ~secret );

prints

FFFFFFD5 42

EDIT: Or using a macro

#define OBFUSCATE(X) (~(X)^0xdeadbeef)

int secret = OBFUSCATE( 42 );
printf("%0X %d" , secret ,OBFUSCATE( secret ));

2152413A 42


Hide representing its value in another number base. See example at base conversion and base 64


You can try antispy C/C++ Obfuscation Library for all platforms they offer a way to hide value types during compile time.


There really is no way to hide just an integer in the program, as someone could just step through a debugger to determine its final value.

Your best bet is to use some auto-obfuscator to obfuscate the whole routine/program.

0

精彩评论

暂无评论...
验证码 换一张
取 消