Blog
Previous Posts
September 2006| 09/29/2006 | Malicious Website / Malicious Code of the Week » |
| 09/24/2006 | Web Attacker with VML being setup. » |
| 09/24/2006 | Keep an eye on NEWS stories. » |
| 09/22/2006 | MOTW: VML Payload Analysis » |
| 09/22/2006 | VML Candid Camera » |
| 09/20/2006 | Proof-of-Concept (POC) for I.E. zero-day posted. » |
| 09/19/2006 | New Internet Explorer Zero-Day being utilized. » |
| 09/16/2006 | MOTW: Downloader Analysis » |
| 09/08/2006 | MOTW: zCodec Delivers » |
| 09/01/2006 | MOTW: VMProtect Analysis » |
+ August 2006
+ July 2006
+ June 2006
+ May 2006
+ April 2006
General Description:
This malware is a simple Trojan downloader.Today's analysis will not focus on the actual payload, but on how the file is being protected against Reverse Engineering. The file has been protected by a PE protector called : VM Protect (Virtual Machine Protect). This protection converts Assembly instructions to pseudo code. There is a Virtual Machine embedded in the binary that will interpret this newly created code. Disassemblers are then useless because they don't support the Virtual CPU instructions. VMProtect uses a rather complex Virtual Machine, and analyzing it would take a long time. The VM are most likely different in each protected binaries, which makes the analysis useless on any other protected binary. Rather, I choose a different approach to analyze the code since the Imports were not scrambled. You will find an ollydebugger script that will sets breakpoints on every API functions that are imported by the binary. Simply parsing the Import Address Table. Then it is very easy to trace the application flow and guess what is going on in this binary.
Technical Details:
If we look at our file with a PE Editor, we notice section named ".vmp". This is a good hint that our file is VMProtected. Using IDA Pro to disassemble it, we see that our application starts with Assembly code, and it doesn't look like clean assembly. It is obviously obfuscated on purpose. Also important information, the ImageBase of our executable is: 0x13140000
Here is the disassembly of the Entry Point:
Anyone a bit familiar with Assembly will notice that this code isn't clean. As I said in the introduction, I am going to use another technique in order to follow the code flow and understand the logic behind this sample. Having a look at the Import Table, we see that it imports a few interesting API functions. They already give us a good amount of information on what the application might be doing:
CreateRemoteThread, WriteProcessMemory etc.. We don't know which process might be injected, nor if a dll is injected, or if it uses delta based assembly, or just any other techniques to inject code inside a remote process. In order to find out, I made an ollydbg script that will browse the Import Address Table and put breakpoints on every imported API function. The IAT starts at 13142000:
//////////////////////////////////////////////////// var IATstart var IATslots mov IATstart, 13142000 // IAT start address mov IATslots, 15 // how many apis to handle. breakpoint_loop: cmp [IATstart],0 // don't set breakpoint at nulls between IID. je skip_breakpoint bp [IATstart] skip_breakpoint: add IATstart, 4 dec IATslots cmp IATslots, 0 jne breakpoint_loop /////////////////////////////////////////////////////
Now, we just need to run the application in OllyDBG and when we are on the entry point, we run this little script. it will put the breakpoints for us.
We could have added a few more breakpoints on GetProcAddress and LoadLibraryA as well. (A malware could emulate both API functions though, so make sure to always debug malicious applications in a Virtual Machine, or even better, on a spare machine.)
By Pressing F9 and looking how the application stops on our breakpoints, we get this information:
0012FFBC 13145D45 /CALL to GetModuleHandleA 0012FFC0 00000000 \pModule = NULL 0012FFC4 7C816D4F RETURN to kernel32.7C816D4F
The application does a few GetModuleHandleA, nothing of interest.
0012FFB8 13145DB7 /CALL to FindWindowA 0012FFBC 13141152 |Class = "shell_traywnd" 0012FFC0 00000000 \Title = NULL 0012FFC4 7C816D4F RETURN to kernel32.7C816D4F 0012FFC8 7C920738 ntdll.7C920738
Then it does a FindWindow on the class "Shell_traywnd", which belongs to the explorer.exe application.
It gives us a good hint: This file might inject explorer.exe
0012FFB8 13145F29 /CALL to GetWindowThreadProcessId 0012FFBC 00050054 |hWnd = 00050054 (class='Shell_TrayWnd') 0012FFC0 13141350 \pProcessID = show.13141350 0012FFC4 7C816D4F RETURN to kernel32.7C816D4F
It then gets some process information using GetWindowThreadProcessID.
It uses the handle found before with FindWindowA
0012FFB4 1314610B /CALL to OpenProcess 0012FFB8 001F0FFF |Access = PROCESS_ALL_ACCESS 0012FFBC 00000000 |Inheritable = FALSE 0012FFC0 000001CC \ProcessId = 1CC
It Opens the Process with PROCESS_ALL_ACCESS.
After that, you will find a VirtualAllocEx allocating memory at address: 13140000
0012FFAC 13145E23 call to VirtualAllocEx 0012FFB0 00000048 0012FFB4 13140000 show.13140000 // Address of allocation. 0012FFB8 00008000 0012FFBC 00003000 0012FFC0 00000040
Notes:
It is important to notice that our application tries to allocate memory in explorer.exe using its own imagebase as a parameter of VirtualAllocEx.
Our application has a non standard imagebase and this is made on purpose. The idea behind this imagebase is that, the injector can copy itself directly in the remote process if it can allocate some memory at the same memory address. What does that mean? It simply mean that the injected code won't need to use delta based code, no relocations will be needed. The imports are already resolved into the injector IAT, thus when they are injected in the remote process, the imports will still be correct. Eventually, after the allocation we have a WriteProcessMemory which will write 8000h bytes in explorer.exe starting from 13140000.
0012FFAC 13145EB6 /CALL to WriteProcessMemory 0012FFB0 00000048 |hProcess = 00000048 (window) 0012FFB4 13140000 |Address = 13140000 0012FFB8 13140000 |Buffer = show.13140000 0012FFBC 00008000 |BytesToWrite = 8000 (32768.) ; writes 8000 bytes 0012FFC0 13141354 \pBytesWritten = show.13141354 0012FFC4 7C816D4F RETURN to kernel32.7C816D4F
Finally, we have a call to CreateRemoteThread to execute the injected Code.
CreateRemoteThread at address 13141168.
0012FFA4 13145D39 show.13145D39
0012FFA8 00000048
0012FFAC 00000000
0012FFB0 00000000
0012FFB4 13141168 show.13141168 // Start address of the remote
thread==> the interesting code.
0012FFB8 13140000 show.13140000
0012FFBC 00000000
0012FFC0 13141358 show.13141358
Having a look at this memory location, we see:
We can see that the payload is very simple. The injected code starts by deleting the application that did the injection in order to remove any evidence.
After that, it will try to download another executable from a website, and will place it inside the Windows Directory. This newly created Application is then executed.
Outro:
I hope this little article gave the readers some ideas on how you can analyze applications using some complex obfuscation techniques. This was an easy example, but this kind of technique can be adapted and applied on different situations.
Researcher: Nicolas Brulez, Websense Security Labs
Post a Comment:







