Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site











SourceForge.net Logo

Code Obfuscation

 

As you can easily understand, the encryption method proposed earlier has 2 flaws :

 

The decrypting code/key is visible and traceable

 

You must obtain the key before the decryption phase

 

The first point is not so important: even if that's true that user can step the decryptor and get the real code, he must do it for every function you did protect, record the code, repatch the executable in many places (they can be hundreds, if needed), disable the decryption parts, and so on.... an huge work, often not worth the time spent. And, of course, if your app is so valuable you can resort to a commercial tool !

 

Second point is somehow more sensitive : if the cracker gets the key, he can write a tool that automatically decrypts and patch your application in short time, even if it contains hundred of protected functions. Is not so easy, but can be done in a reasonable time.

A perfect solution for that doesn't exist... of course. But, we can make cracker's live a bit more difficult if we encrypt somehow also sensitive parts of code with a random key.

This is done by another couple of macros :

 

void MyObfuscatedFunction(void)

{

    OBFUSCATE_START_FUNC;

 

    <here my function code>

 

    OBFUSCATE_END_FUNC;

 

}

 

You can notice that the GetCypher parameter is gone. The macro generates automatically a Snow2 Cypher object and a random, 16 byte long key, different for each obfuscated function. The key is stored into the executable and automatically used to decrypt the code on the fly when needed and to reencrypt it at function exit.

The code will run anyways, it won't check any key, so what's the purpose ?

Is simply to defeat  disassemblers and to make function tracing quite hard.

The disassembler would see just garbage bytes, as the function is stored in encrypted form. If you try to trace it step by step with a debugger, the function will be unencrypted just when needed, and re-encrypted on exit, which confuses many debuggers (TheIde GDB frontend is *very* confused about it :-) )

You'd normally use Obfuscation when obtaining your key used to decrypt the Protected parts, mostly on code startup and on some sensitive parts which needs to be executed before the key is available.

 

A note : the code MUST reach the end macro in order to re-obfuscate itself. That means that you can't put any return statement inside the obfuscation block. If you do, your app will crash if the obfuscated function is executed twice. So :

 

    OBFUSCATE_START_FUNC;

    <some code here>

    return;

    OBFUSCATE_END_FUNC;

 

Is WRONG and will make your app crash on second function invocation; the right approach is :

 

    OBFUSCATE_START_FUNC;

    <some code here>

    OBFUSCATE_END_FUNC;

    return;

 

The non-MT limitation of obfuscation should be removed, as the whole block is enclosed into a Mutex object.

As the block is decoded AND re-encoded on each execution, don't use this kind of protection for time-sensitive code sections, as they would be slowed down quite a lot.

Do you want to contribute?