It is no secret to anyone that from compiled assemblies (exe and dll) for the .NET platform, code in high-level languages (C #, VB.net) can be easily restored. This means not only that if the program has a licensing system, it can be easily removed; but also that your source code can be copied, for example, by dishonest competitors. To protect themselves from such threats, most commercial software developers use various kinds of obfuscators.
Why and from whom we defend?
Obviously, obfuscation as one of the stages of protection is relevant only for commercial software.
To protect the program, if it uses the registration system by serial number or activation, it is required from “crackers”, who either write for a lack of money (if the program is expensive) or because of their love for art. Finding out where the necessary conditional transition is located, or checking the serial number, is much harder if you have at best a “node” from the IL code than if you see an easily understood C # code. This, of course, is not a panacea, but adds the n-th number of minutes required for hacking. (If n is large enough, then only very persistent individuals will try to break;)
It is also necessary to protect against one of the varieties of industrial espionage. It's simple: just remove the metadata and confuse the rest of the program so much so that it will be cheaper for a competitor to write a program from scratch than to disassemble yours.
Usually,
.NET Reflector is used to view assembly metadata. It has a simple and intuitive interface, as well as the ability to extend the functionality of plug-ins.
Beginners can find screenshots and examples of use on the site of the reflector.
')
There are also several commercial viewers of assemblies and decompilers, maybe I will list them later (the trial versions parse only half of the build, and the “happy owners” of the licensed versions report not very big differences from the reflector).
Obfuscators and packers
.NET applications try to protect with two main methods: directly by
obfuscating the IL code (when the output is a nearly valid * .net assembly, and it can be performed on unmodified MS.NET or
mono ). And the
packaging is a modification of the assembly so that the output is a winapi application containing the unpacking module and the packed IL code.
* - assembly may contain invalid IL instructions, which however will not be executed. And the build as a whole looks “normal” and can be run on any supported runtime.With obfuscation, everything seems to be clear: we submit the assembly to the .net input, we get the assembly to the output of the .net, everything works approximately the same. No unnecessary “hidden” data, everything is in place, only confused and renamed to something useless.
In the case of the packer, some problems await us:
- Our build will now be performed only under Windows (or neatly tuned mono + wine)
- The packer, which sends the original assembly to the mscoree input, is removed in 1 minute, and does not make sense for protection. Packers that intercept the internal functions of mscoree are very dependent on the version of the framework and cause false positive reactions in some antiviruses. Interception of internal functions in general is a delicate and ungrateful business.
- Packers are native-programs, and do not allow your application to be compiled in x86-64 code, where it is available (and in some cases it gives a big performance boost)
- For normal execution, the .net environment in any case requires access to the original IL bytecode. And even preJITted assemblies should contain it. And that means getting this bytecode is also real.
- And, lastly, quote: "if it runs it can be unpacked"
A variety of “protectors” (
protectors ) usually combine both approaches and will be considered in both parts of this review.
Reverser tools
The first and most basic tool is a
reflector . Usually everyone pumps plugins to him to his own taste. I will only recommend one:
reflexil , it allows you to change the bytecode of methods, the properties of the assembly, and contains a convenient removal utility strong-name. With this plugin it is very convenient to make cracks;)
If the assembly has undergone obfuscation, then viewing it in the reflector is not very convenient, so before changing it (or pulling out the code), it must be “deobfuscated”, for this a variety of ready-made deobfuscators are used (of which you can find
a lot on the Internet).
It is also useful to have your own deobfuscator, which is always easy to “finish” to the needs of a particular task.
If we deal with packers, we will need various tools for native reverse engineering, such as a debugger (WinDbg, OllyDbg), a dumper (PE tools), a PE-file editor (for example, CFF Explorer). As well as .net-unpacking-specific tools:
Generic .NET Unpacker ,
.net dumper (KDD) ,
.Net Assembly Rebuilder . We will get acquainted with them in the second part of the review.
Everything, on this my verbiage ends, the next post will contain more details (even with pictures);)
Continuation →The approximate content of the following posts:
- 1. Obfuscators.
- 1.1. Techniques
- 1.2. Overview Obfuscators
- 1.3. Deobfuscation techniques
- 1.4. Deobfuscators
- 2. Packers.
- 3. Used sources, and what else to read on the topic