Tiny R2 Emulation

Synopsis

Today's article reviews how to use Radare2 to make the malware deobfuscate itself. Radare2 or R2 simplifies the process through archaic VIM like commands. One caveat though, R2 emulates slowly. It can't brute force anything of significance quickly; but, when used correctly, R2's emulation reduces analysis time.

Sample

Understanding what the malware does is important before diving into any emulation. This Tinyloader sample, found on VirusShare, serves as today's specimen. If interested, a number of online articles cover Tinyloader in more detail.

Sample Hash: 4a3dba1098daf8ed2c437943d814c507859ab0866060adf2a7025f4afea147c8

Tinyloader utilizes an obfuscated payload while also being simple to reverse. This makes it an ideal walk-through candidate!

The entry point's function performs the following:

  1. VirtualAlloc allocates memory at address 0x40101e.
  2. The instructions between 0x40104b-0x40106a copy the obfuscated payload to the allocated memory segment.
  3. A brute force loop finds the XOR key. It performs the comparison check at 0x401072.
  4. 0x401070 - 0x401092 contains the payload deobfuscation instructions.
    1. One loop performs both the XOR key brute forcing and the deobfuscation. Jump instructions control the execution flow between the two.
  5. The execution flow jumps to the deofuscated instructions at line 0x401096.

TinyloaderEntryPointFigure 1: Tinyloader Entry Point

Tinyloader's code base (figure 1) is very succinct.

R2 Emulation

Start by devising an emulation strategy for the malware specimen. Tinyloader's short instruction set results in most instructions getting emulated. Where possible, strive to keep things simple by avoiding instructions that call external functions.

Tinyloader's assembly code breaks down into the following sections:

  1. Staging the obfuscated payload
  2. Brute forcing the key
  3. Deobfuscating the payload

The order of 1 and 2 do not matter provided both occur before 3.

During the research phase of this article, it quickly became apparent that a simple loop adversely affects the speed of R2's emulation framework. Emulation frameworks differ from one to the next and ESIL[1], the emulation framework used by Radare2, is slower than a tortoise when brute forcing XOR keys that are the length of a dword. It was nowhere close to the key's actual value 6 hours into emulation.

Therefore, the updated procedures are:

  1. Brute forcing the key (not emulated)
  2. Staging the obfuscated payload
  3. Deobfuscating the payload

Brute Force XOR Key

Using Python to brute force the XOR key takes under a minute. The dword to XOR is located at 0x403000 (see Figure 1). This XORed dword matches 0x90909090 (at 0x401072) when the correct key is found.

Construct a simple python script using this information:

>>> for x in range(0xffffffff):
...   if 0x978710a1 ^ x == 0x90909090:
...     print(hex(x))
...     break
... 
0x7178031

Code Snippet 1: Brute Forcing XOR Key
Now on to the emulation!

Emulation

Splitting the emulation into two parts allows the XOR key to be added between the two parts.

Part 1 - Staging the Obfuscated Payload

Follow these 5 steps to setup and run emulation.

1 - Pre-emulation Setup
e asm.bits=32
e asm.arch=x86
e asm.emu.write=true
e io.cache=true

Code Snippet 2: Pre-emulation Setup Commands

Breaking this down line by line:

  1. e asm.bits=32 : Set the assembly to 32 bits; should be the default[2]
  2. e asm.arch=x86 : Set the architecture to x86; again, should be the default[3]
  3. e asm.emu.write=true : Allow memory writes[4] as the emulation modifies content
  4. e io.cache=true : Allow ESIL to write to the cache[5] versus to the file on disk.
2 - Initialize Emulation Engine
aei
aeim

Code Snippet 3: Initialize Emulation Engine Commands

  1. aei : Initializes the emulation engine state[6]
  2. aeim Initializes ESIL's VM Stack[7]

So simple!

3 - Configure Memory
aeim 0x800000 0x28000

Code Snippet 4: Configure Memory Commands

Initializes memory at location 0x800000 of length 0x28000. The emulation engine will copy the obfuscated code to this allocated memory.

4 - Configure Registers
s 0x40104b
aeip
aer eax=0x800000

Code Snippet 5: Configure Registers Commands

  1. s 0x40104b : "Seek" the emulation starting point. Seek is short for "move to". Choose this location as it is right after some external APIs calls, yet retains the necessary assembly instructions for successful emulation.
  2. aeip : Sets instruction pointer to the current location.
  3. aer eax=0x800000 : Sets eax to point to the allocated memory defined in step 3.
    • aer : Prints out the current register values. Use aer to confirm changes.
    • Note the first instruction emulated adds 0x14000 to 0x800000. This is important because the obfuscated code is copied to starting location of 0x814000.
5 - Run Emulation
aecu 0x401070

Code Snippet 6: Run Command

Finally, emulate code until 0x401070


Again, but with Screenshots!

Configure everything as defined above.

Image Description

Figure 2: Emulation Config - Excludes the actual emulation step.


Notice EIP is now pointing to 0x40104b:
TinyloaderEntryPoint_Emu_Setup_EIPFigure 3: EIP Starting point


aecu 0x401070 emulates until the XOR instruction.

TinyloaderEntryPoint_Emu_Mid_EmuFigure 4: EIP and registers after executing: aecu 0x401070


Jump over to the location stored in eax to confirm the memory copy.
TinyloaderEntryPoint_Emu_Mid_Emu_MemoryFigure 5: Memory - Contents Obfuscated

Part Two - Deobfuscating the Payload

This step is simple, modify the value of ecx to 0x7178031 (the XOR key) and run until the call instruction.

aer ecx=0x7178031
aecu 0x401096

Code Snippet 7: Deobfuscation emulation commands

Image DescriptionFigure 6: Set ecx to the XOR key value


Execute: aecu 0x401096

TinyloaderEntryPoint_Emu_Final_CallFigure 7: EIP now point to the call instruction.


Switch back over to 0x814000 to see the deobfuscated code. Not all of the assembly instructions in Figure 8 are actually assembly instructions. Data (strings) is mixed with the code, so some of the bytes need to be flagged as data instead.

At this point, deobfuscation is complete! Further analysis is left as an exercise for the reader ;-)

TinyloaderEntryPoint_Emu_Final_Emu_MemoryFigure 8: Deofuscated Bytes

Conclusion

This tutorial shows how simple R2's emulate framework is even with the obtuse syntax. Radare2's emulation feature can unpack the embedded payload but be careful when emulating a brute force loop.


  1. https://radare.gitbooks.io/radare2book/content/disassembling/esil.html ↩︎

  2. http://blog.superponible.com/2017/04/15/emulating-assembly-in-radare2/ ↩︎

  3. http://blog.superponible.com/2017/04/15/emulating-assembly-in-radare2/ ↩︎

  4. http://blog.superponible.com/2017/04/15/emulating-assembly-in-radare2/ ↩︎

  5. http://blog.superponible.com/2017/04/15/emulating-assembly-in-radare2/ ↩︎

  6. http://radare.today/posts/emulating-simple-bootloader/ ↩︎

  7. http://blog.superponible.com/2017/04/15/emulating-assembly-in-radare2/ ↩︎

comments powered by Disqus