In this white paper, we will examine one of the modern anti-debugging methods that is based on software nanomites technology. It’s also an effecient method of the process antidumping.
This approach was first introduced in the Armadillo protector for Windows applications.
Software Designer of Driver Development Team
The Armadillo Protector
Armadillo (also known as SoftwarePassport) is a commercial protector with a rich development history. It was first released on January 15, 1999. It was developed by Silicon Realms company with Chad Nelson as the leading code developer.
One of the methods used by Armadillo is nanomite technology.
The Description of the Software Nanomites Implementation in Armadillo
Armadillo uses the protection by parent process. In Windows OS, only one ring-3 debugger can be attached to a debugged process at a time. This was used in Armadillo. The protection creates a child process and attaches to it with debugging. When a protected program is started in a debugger, it is possible to debug only the parent process. This technique is called Debug Blocker.
Armadillo Nanomites Technology
The developer of the application, which is protected by Armadillo, marks some code segments in the program sources. The compiler leaves these marks untouched after a compilation. It allows the protector to locate the code that requires protection. After that, the code is cut out from the program for packing. During unpacking, the cut out code segments are obfuscated and written into the allocated memory with jumps to them left in their place.
The marks from the program are used to identify the procedures that must be “processed”. The processing is creating the table of conditional and unconditional jumps. These jumps are replaced with 0xCC byte before packing (the int3 assembler command), and other jump bytes are replaced with trash. The obstruction to restoring the table is its “completeness”: before packing, all 0xCC bytes are also included in the table with non-existent jumps assigned to them. For example, there is a push 0CCh instruction, but the address of the 0CCh byte is present in the table as well, and on attempt to restore this table element, the code will be completely corrupted.
While executing the code, debugging exceptions constantly occur at nanomites (int3 is basically a breakpoint). However the parent process doesn’t restore the original bytes at all. It examines three tables: the table of flags, the table of sizes, and the table of offsets. The analysis of flags defines where the control must be transferred: a size value (no jump) or a size value + an offset value (a jump is needed).
This method is the most powerful weapon of the protector as there is no means of fighting nanomites that would be 100% reliable.
Fighting Software Nanomites
There are three main ways of fighting nanomites.
The first of them is repeated attaching of a debugging process, or enabling VEH followed by the inclusion of the table of nanomites to the debugger code. Basically the protection debugger is replaced with the cracker’s debugger. Researching such program isn’t the most pleasant work as trash bytes and the absence of jumps break the work of almost any analyzer.
The second way is starting the program under an unpacker or under a debugger embedded in an unpacked program. While the program is running, hacker must try to use as many program features as possible and try out different combinations of program options. This way, hacker can gradually collect the information on “real” nanomites and restore them. As it is unlikely that all nanomites will be restored this way, this method is combined with the first one.
The third way, which is the most difficult to implement, is an analyzer. An analyzer must "execute” the code and go through all its branches, and when it encounters nanomites, it must restore them according to the table. The complication here is the processing of switch-tables, table calls (class method calls and high-level language constructor calls look like call ds:[edx+410h] at a low level, for example), and API functions with CALLBACK parameters.
The Difficulties of Reversing a Product Protected by Nanomite Technology
- Debug Blocker approach like the one in Armadillo. We cannot attach with a debugger to a process which is under the ring3 debugging. The only option is a ring 0 debugging, and this isn’t very convenient. The detaching of the parent process is possible only after restoring all nanomites. The result of an attempt to attach with a debugger to a process protected by nanomites:
- Due to the absence of jumps in the software, the application transforms into a solid piece of code in disassemblers (e.g. IDA Pro), and this prevents any analysis. The code looks as follows:
The Disadvantages of Using Software Nanomites
- The major disadvantage is performance. Each time a process encounters a nanomite, a context is switched and the control is transferred to the parent process. This procedure is very slow, that’s why it is best to use nanomites in the key code segments that are not critical for performance.
- This mechanism may conflict with other anti-debugging methods.
Corrections of the make files of the protected project are required for the implementation of this mechanism, and this is not always convenient.
Apriorit has applied the Nanomite technology to protect Linux applications. Learn more about Apriorit Linux Code Protection!