Obfuscation
During your reverse-engineering journey you will find obfuscation. It is security through obscurity and is used to prevent reverse-engineering.
There are many obfuscators both FOSS and commercial a few examples are:
https://zelix.com/ https://skidfuscator.dev/
I won't recommend any of them even though I recommended zelix in the previous iteration of the manual, a decent bit of stuff has changed since then and I don't feel like recommending any of them.
Your best bet is to closely examine them yourself and choose which you think is the best, the manual will teach you how to do just that by explaining certain obfuscation techniques.
Obfuscation techniques
Obfuscators use obfuscation techniques, some are good and some not so much.
String encryption
In preventing the reverse-engineer from being able to understand what the code does, string encryption plays a big part.
It simply works by the obfuscator loading an encrypted string that has been encrypted during the time of obfuscation and calling a method to decrypt it at runtime or in some cases decrypting it on the spot.
Most FOSS obfuscators use some form of the XOR operation, the characters of a string are iterated through and each of them get XOR performed over them using an encryption key, the key is usually a random integer.
This isn't a good way to perform encryption as XOR simply is not secure.
Other obfuscators which are most commonly commercial use some form of polymorphic string encryption or an implementation of an existing encryption standard like AES.
Defeating XOR
In order to defeat XOR string encryption we must find the key used for decryption at runtime, this is usually found as an argument to the obfuscator's decryption method or as a stack element, then we simply run XOR over the encrypted string in the exact same way it was encrypted.
The reason for this is because when you run XOR over a previously encrypted character using the same key it causes it to be decrypted.
Defeating custom implementations
This will highly vary on the obfuscator but usually you can hook the implementation and pull out decrypted strings and any other stuff you may need or just virtualize the call to decryption.
Defeating polymorphic encryption
Polymorphic encryption refers to the encryption of data using multiple operations and keys, for example you will see shift and XOR operations mixed together and a bunch of other things, this is a bit harder to decrypt so I suggest just virtualizing the calls or running the decryption method separately.
Control flow flattening
Control flow flattening is incredibly common and works by routing jumps through a jump table called the dispatcher.
The dispatcher is commonly a switch that matches a local variable to see where it should jump to.
It is a very long topic to explain and there are plenty of sources online so until I can overcome my laziness this will stay like that.
Last updated