SAMPLE MD5: 50d3cbd314e39b28bcd7938794e18c97
This sample is packed with a packer that drops a shellcode to decompress the
The packer uses a similar technique to “Process Hollowing”. In this case, after dropping the shellcode, the shellcode decodes the payload. Finally, the shellcode unmaps the packer and it maps the payload in the same memory address as the packer was.
The next image shows the different phases of unpacking process.
Image 1: Logic summary of the packer.
I am going to explain in detail the 6 steps described above.
The first step (1) drops the shellcode using Windows messages.
Image 2: Main code of the packer.
The image 2 shows how the class named “needed” is registered. “needed” class has associated the subroutine “sub_4041A6” (The shellcode will be written by this subroutine).
After registering the class, the packer creates a “needed” window.
The packer loops until it does not get more messages, at this moment the shellcode is ready to run (“image 2”, line 24).
“sub_4041A6” subroutine works as state machine. Depends on the received message, it jumps to one state or another. The next messages are the most important for the subroutine:
- Message 0x111: This message manages the state machine, depends on lParam theprogram jumps to one state or another. The packer drops the shellcode after passing for all states.
Image 3 shows how the messages are managed by the window. If the message is different to 0x111 the program pass the message. In addition, if the message is 0x111 with value 0x579 as lParam the window will start to drop the shellcode.
Image 3: Reading 0x111 message.
- Message 0x401: When this message is received, it will start to decode the shellcode. The wParam is the memory address to write from and the lParam is the address to write to.
Image 4: Message 0x401 loop which is responsible for decoding the shellcode.
The loop shown in the image 4, basically do the same as the next pseudo code.
This message is sent until the packer writes the shellcode.
When shellcode is executed, it decrypts itself at the beginning. After this decryption, the shellcode starts to work.
Image 5: Entry point of the shellcode before the decryption.
Image 6: Piece of code of initial decryption just before calling to the decrypted shellcode.
Imagen 7: Entry point of the shellcode after the decryption.
The shellcode allocates memory with VirtualAlloc function and starts to drop binary data which looks to be compressed.
Image 8: Uncompress process.
After uncompressing data, we can find the payload.
Image 9: uncompressed, payload.
Now we are at the third (3) step, the shellcode will unmap the packer and will map the decrypted payload in the same address as the packer was (4).
Image 10: Unmap/map code.
Finally, the shellcode fixes up the import addresses of the payload and it passes the control to the payload.
Image 11: Fixing up the imports of the payload.
Image 12: Jump to OEP.
The first command for starting the unpacking (in the subroutine associated with the "needed" registered class) is when the lParam is 0x38.
The firs state of the "needed" class is to get the system time. Once it has the current month (using GetSystemTime) it moves to lParam, the current month value (1 = January, 2 = February ... 11 = November, 12 = December) plus 0x27 and sends the message.
So, If it is not November It won't unpack =(