Let’s feed the same DotFuscated code from Listing 12.7 into another decom-
piler, Decompiler.Net and see how it reacts to the DotFuscator’s control flow
obfuscation.
public void a ()
{
for (d theD = this.a; (theD != null); theD = theD.b)
{
theD.a ();
}
}
No problems here—Decompiler.Net does a good job and the obfuscated
control flow structure of this routine seems to have no impact on its output.
The fact is that control flow obfuscations have a certain cat-and-mouse nature
to them where decompiler writers can always go back and add special heuris-
tics that can properly deal with the various distorted control flow structures
encountered in obfuscated methods. It is important to keep this in mind and to
not overestimate the impact these techniques have on the overall readability of
the program. It is almost always going to be possible to correctly decompile
control flow obfuscated code—after all the code always has to retain its origi-
nal meaning in order for the program to execute properly.
If you go back to the subject of symbol renaming, notice how confusing this
simple alphabetical symbol naming scheme can be. Your amethod belongs to
class b, and there are two references to a: one this.areference and another
theD.amethod call. One is a field in class b, and the other is a method in class
d. This is an excellent example of where symbol renaming can have quite an
annoying effect for reversers.
While I’m dealing with symbol renaming, DotFuscator has another option
that can cause additional annoyance to attackers trying to reverse obfuscated
assemblies. It can rename symbols using invalid characters that cannot be
properly displayed. This means that (depending on the tool that’s used for
viewing the code) it might not even be possible to distinguish one symbol name
from the other and that in some cases these characters might prevent certain
tools from opening the assembly. The following code snippet is our AddItem
method obfuscated using DotFuscator with the Unprintable Symbol Names
feature enabled. The following code was produced using Decompiler.Net:
public void ᜤ (ᜃ A_0)
{
A_0.áœ_ = this.ᜤ;
if (this.ᜤ != null)
{
this.ᜤ.ᜤ = A_0;
}
this.ᜤ = A_0;
}
450 Chapter 12