Reversing : The Hacker's Guide to Reverse Engineering

(ff) #1

because the analyzer must determine how memory modifications performed
through one pointer would affect the data accessed using other pointers that
point to the same memory location. In this case, the idea is to create several
pointers that point to the array of indexes and have to write to several loca-
tions within at several stages. It would be borderline impossible for an auto-
mated deobfuscator to predict in advance the state of the array, and without
knowing the exact contents of the array it would not be possible to properly
analyze the code.
In a brief performance comparison I conducted, I measured a huge runtime
difference between the original function and the function from Listing 10.4:
The obfuscated function from Listing 10.4 was about 3.8 times slower than the
original unobfuscated function in Listing 10.2. Scattering 11 copies of the
OBFUSCATEmacro increased this number to about 12, which means that the
heavily obfuscated version runs about 12 times slower than its unobfuscated
counterpart! Whether this kind of extreme obfuscation is worth it depends on
how concerned you are about your program being reversed, and how con-
cerned you are with the runtime performance of the particular function being
obfuscated. Remember that there’s usually no reason to obfuscate the entire
program, only the parts that are particularly sensitive or important. In this par-
ticular situation, I think I would stick to the array-based approach from Listing
10.4—the OBFUSCATEmacros wouldn’t be worth the huge performance
penalty they incur.


Inlining and Outlining


Inlining is a well-known compiler optimization technique where functions are
duplicated to any place in the program that calls them. Instead of having all
callers call into a single copy of the function, the compiler replaces every call
into the function with an actual in-place copy of it. This improves runtime
performance because the overhead of calling a function is completely elimi-
nated, at the cost of significantly bloating the size of the program (because
functions are duplicated). In the context of obfuscating transformations, inlin-
ing is a powerful tool because it eliminates the internal abstractions created by
the software developer. Reversers have no information on which parts of a cer-
tain function are actually just inlined functions that might be called from
numerous places throughout the program.
One interesting enhancement suggested in [Collberg3] is to combine inlin-
ing with outliningin order to create a highly potent transformation. Outlining
means that you take a certain code sequence that belongs in one function and
create a new function that contains just that sequence. In other words it is the
exact opposite of inlining. As an obfuscation tool, outlining becomes effective
when you take a random piece of code and create a dedicated function for it.
When done repetitively, such a process can really add to the confusion factor
experienced by a human reverser.


Antireversing Techniques 353
Free download pdf