Here’s a sample I got some days ago via Facebook (md5: 6853d7ce162adb707ddfa6529b82b4af). Only few antivirus are able to recognize it right now.
To obtain the exe you have to simply click on a link which is show inside a chat request from a friend of you (the infected friend). The message I got is:
“Foto :D http://apps.facebook.com/peoplephotos/photo.php?=id_number”
where “foto” is the italian translation of “photo”, and id_number is your Facebook id (I removed mine).
The link is not working anymore on Facebook but I think they have some more available links to use… anyway, the interesting part of the malware is the use of a technique called Dynamic forking. It’s an old technique used sometimes inside packers and stuff like that, but as far as I have seen (and according to some friends) it’s a rarity to see it inside a malware. There’s an article explaining everything about the method right here: http://www.security.org.sg/code/loadexe.html (it’s dated April 2004!).
Is it really so interesting? Yes indeed, mainly because it’s not so easy to catch and debug the second exe on the fly. Not to mention you can’t dump it in an easy way. Is it impossible to study the exe? Not really… there’s always a simple way to do such things.
The “dynamic forking” method is all inside a call starting at 0x4013A0 address:
...
4013CE push CREATE_SUSPENDED
...
4013D3 push edx ; CommandLine = "PATH OF THE MALWARE\facebook-pic000163927.exe"
...
4013DB call _CreateProcessA ; it runs itself
...
401414 push ecx
401415 push edx
401416 mov _GetThreadContext, eax
40141B call eax
...
401432 push 4 ; number of bytes to read
...
401440 mov _ReadProcessMemory, eax
401445 call eax ; read BaseAddress from CONTEXT structure, it's 0x400000
...
401459 push edx ; BaseAddress: 0x400000
40145A push ecx ; process handle
40145B mov _ZwUnmapViewOfSection, eax
401460 call eax ; unmap!
It follows the article step by step, the last call is the most important one because it’s used to unmap the entire view of the section that contains BaseAddress. After that, the next part of the procedure is used to fill part of the unmapped section:
401462 mov esi, [ebp+decompressedBuffer] ; take care of ESI value!!!
401465 mov edi, [esi+3Ch]
401468 mov edx, [edi+esi+54h] ; SizeOfHeaders
40146C add edi, esi ; edi -> "PE"
40146E mov [ebp+decompressedBuffer], edx
...
40148A mov _VirtualAllocEx, eax
...
40149A push ecx ; size: 0x2FC000
40149B mov ecx, [ebp+var_1C]
40149E push edx ; 0x400000
40149F push ecx ; hprocess
4014A0 call eax ; VirtualAllocEx
...
4014D2 push 0
4014D4 push edx ; 0x400: number of bytes to write
4014D5 mov edx, [ebp+var_1C]
4014D8 push esi ; decompressedBuffer
4014D9 push ecx ; 0x400000
4014DA push edx
4014DB mov _WriteProcessMemory, eax
4014E0 call eax ; replace the header of the *new* process
... ; replace the rest of the *new* process's code
It allocs the necessary space for the *new* process (0x2FC000 represent the SizeOfImage of the real malware), and it replaces the old process code with the new one which is taken from a buffer pointed by ESI (look at 0x401462). This buffer is really important, I’ll tell you later why. Now, the final part of the procedure:
40158D mov [ebp+var_280], eax ; change oep of the file from 0x4017D3 to 0x40C4FF
...
4015A4 push ecx
4015A5 push edx
4015A6 mov _SetThreadContext, eax
4015AB call eax ; SetThreadContext
...
4015BE mov _ResumeThread, eax
4015C3 call eax ; ResumeThread
Pretty simple, it changes the entry point and it runs the process from the new location.
At this point I’m not able to debug the new process with a debugger like Ollydbg, I’m not even able to dump the new process… and the question is: how can I solve the problem? The dynamic forking is a powerfull method but there’s a big flaw in it, you always know how to dump the real malware: in this case decompressedBuffer is the answer! The buffer contains all the new code, and you only have to understand where the hell it was stored:
401383 push ecx ; finaluncompressedsize
401384 push ebp ; compressedbuffersize
401385 push edx ; compressedbuffer
401386 push edi ; uncompressedbuffersize
401387 push esi ; uncompressed buffer
401388 push COMPRESSION_FORMAT_LZNT1
40138A mov RtlDecompressBuffer, eax
40138F call eax
The malware uses lznt1 compression algo to reveal the real code. When the decompression ends you only have to dump 0x11200 bytes starting from UncompressedBuffer address and voilà! Now you can easily check the real malware!
Well, something unusual is always better than the usual boring thing…