Hi folks, today I would post on Anti-Static Analysis Techniques.
The primary purpose of Anti-Static Analysis Technique is to prevent an analyst from understanding the nature of a program without actually running the program. There are many different types of Anti-Static Analysis Techniques such as: Disassembly Desynchronization, Dynamically Computed Target Address, Opcode Obfuscation, Imported Function Obfuscation and Target Attacks on Analysis Tools.
Today I am going to give you a short overview on the first and probably the oldest techniques called disassembly desynchronization. This technique consists in executing a function call (as well as a jump) into the middle of another function code. In this way the decompiler, taking the first 5-bytes as instruction set, decodes wrong instructions confusing the revers engineer. So lets say to have a call near ptr 00000003 located in 00000001. Supposing the real function starts at 00000004 and calling 00000003 we are desynchronizing the assembly instruction set because the disassembler starts to decode instruction set from the wrong offset. In fact after the “call” the decompiler will decode one byte wrong instruction set propagating the error around the code. The following image shows you how this techniques is possible by modifying the calling addressing (loc_X+1 and loc_Y+2).
One of the most famous implementation of this techniques is Shiva. What shiva does is to map the executable in the following way:
The Shiva runtime block is the decryption point where it performs (in order): Anti-Static Reverse Engineer checks, allocating memory heaps, cloning dynamic monitor process and decrypting encrypted blocks (in the figure Block 3). Shiva Block 2 is optional, it is a password protected AES where the key is obfuscated into the encrypted code (it uses Tiny Encryption Algorithm with 128 bit of key). The encryption phase happens as previously described (loc_x+1, loc_y+2) by adding offsets to jumps, functions call or more generally speaking by misaligning the binary decoding process. The decryption phase works (of course) oppositely, by setting the right offsets.
Shiva divides encrypted blocks in two sets: (i) data set, aligned to natural ends of variable length, and (ii) code set partitioned about 1K in size. It keeps unused memory space filled up with 0xCC (INT3, basically jump to empty location memory), in response Shiva decrypts and maps the needed memory page.
There are many different ways to detect this kind of obfuscation and many different tools like for example IDA-Plugins or external program running emulation techniques. IDA emulation record list contains enough information to rebuild the right code blocks, once rebuilt the right (decrypted) code blocks, it becomes possible to generate ELF headers and segments to construct a separated and unwrapped binary. Beside IDA pro, another interesting tool called stripshiva; a command line tools containing a x86 emulator which performs the decoding steps as IDA does.
As shown in the previous figure, stripshiva runs the starting block and the overall program, in the meanwhile a “kind of ” monitor engine records each stripped (or decoded) block. Once the program ends running stripshiva builds an ELF containing the decoded and ordered blocks: you are ready to go by analyzing the stripshiva outcome !
Obviously there are many different ways in both sides: Disassembly Desynchronization and Disassembly Synchronization. Goal of this post is not to explain how each of it works (for these purposes there are books and research papers, that actually are very good in this field) but to give a light flavor on the topic introducing the reader into Disassembly Desynchronization topic.