Eazfuscator.NET performs several code and metadata optimizations during obfuscation.
Merging of string literal duplicates is a complementary optimization method to string encryption obfuscation technique. Formally, this optimization ensures that all encrypted string values are unique in one .NET assembly. Such kind of optimization also widely known as string pooling.
Example 3.11. Hypothetical string table before encryption
String Values |
---|
Abracadabra |
Siam |
Foo |
Abracadabra |
Foo |
Bar |
Example 3.12. Hypothetical string table after encryption with duplicates merging
Original String Values | Encrypted String Values |
---|---|
Abracadabra | }S£tP)€_9€[] |
Siam | @!€NayfI* |
Foo | !>@"buY] |
Bar | E)€a£J |
Sealed class is a specially marked class which can not be inherited. .NET runtime uses a knowledge about such classes to perform an optimization on virtual method calls, such optimization has considerable impact on overall application performance. Therefore Eazfuscator.NET analyzes the classes of .NET assembly and marks all not inheritable ones as sealed when it is possible. However, this optimization does not enhance obfuscation; information about class inheritance can be used by a hacker as an additional information to infer the program operation. But in this case the risk is lower than performance benefits.
Example 3.13. Source code retrieved with decompiler before sealing of terminal classes
class Shape { … } class Circle : Shape { … }
Example 3.14. Source code retrieved with decompiler after sealing of terminal classes
class Shape { … } sealed class Circle : Shape { … }
String compression is an automatic size optimization which results in smaller assemblies. Large strings are compressed during obfuscation. The compressed strings are uncompressed on demand during the run time. The decompression algorithm is incredibly fast, so there is no performance penalty observed — the actual decompression speed comes very close to the speed of a simple memory copy.
String compression is a part of string encryption technique and is on by default.
Eazfuscator.NET applies code optimizations to deliver the best performance to your applications. .NET compilers such as C#, VB.NET and JIT already do a pretty decent job in this area. But what they all do not do is high-level optimizations.
High-level optimization is a fresh trend in optimization technology and Eazfuscator.NET establishes itself as the first tool to deliver this technology to the wide .NET user base. The best way to briefly describe high-level optimization is to start thinking as developer thinks: we all know that there are some methods and code patterns which are faster than others. What Eazfuscator.NET does is this: it finds the slow code and swaps it with faster one. Eazfuscator.NET uses a preciously brewed knowledge base of common and efficient code patterns that you can meet in every .NET application.
At first glance, high-level optimization is very similar to a well-known peephole optimization approach. But the main difference is that the classical peephole optimization works only on a small window of target machine instructions, while high-level optimization works at the application-wide level and considers control and data flows as well as the sacred knowledge about specific frameworks such as LINQ, MEF and others.
Let's take a look at example.
Example 3.15. The slow code
[Flags] enum RunOptions { None = 0x00, PrepareDatabase = 0x01, SkipPlugins = 0x02 } class Engine { public void Run(RunOptions options) { if (options.HasFlag(RunOptions.PrepareDatabase)) InitializeDatabase(); … } … }
The code above uses Enum.HasFlag
method to check whether PrepareDatabase
flag is set.
Being sweet in syntax, the code has astonishingly bad performance due to boxing operations that are invisilbly generated by C# compiler.
Example 3.16. The fast code. Produced by Eazfuscator.NET after optimizing the slow code
public void Run(RunOptions options) { if ((options & RunOptions.PrepareDatabase) == RunOptions.PrepareDatabase) InitializeDatabase(); … }
As you can see, Eazfuscator.NET emitted functionally equivalent code. The result of optimization is 500x speed improvement of condition evaluation over original slow code.
The optimizer is on by default and works behind the scenes during obfuscation.