Topic created on: October 24, 2012 11:42 CDT by legola .
Hi guy,
i have a question for experienced malware reverser.
I'm newbie of reversing and i'm in trouble with an executable written in VB6 and obfuscated.
I have seen some RunPE malware samples that don't use the "CreateProcessA/W" functions for spawning the suspended child process, they call the "CreateProcessInternalA/W" functions instead. Similarly for the "WriteProcessMemory", they use the ntdll "ZwWriteVirtualMemory" function.
This is why if you place your breakpoint on CreateProcessW, it will never get hit.
One very common thing between RunPE malware is that they all call the "ZwResumeThread" function at the final step. Try to place the BP there.
I wrote something about that a while ago. You can find it here:
http://waleedassar.blogspot.com/2012/03/visual-basic-malware-part-1.html
|
Hi, thank thank you for your reply.
|
I quickly analyzed it and found that it is a typical RunPE piece of malware.
Using my OllyVB OllyDbg plugin to find the DllFunctionCall calls, i found that it has only 5 calls (RegCreateKeyExA, RegSetValueExA, GetProcAddress, LoadLibraryA, and RtlMoveMemory). Amony them, only GetProcAddress and LoadLibraryA are of interest.
I placed BPs on LoadLibraryA and GetProcAddress to know which functions are being used.
Among the functions i found are:
1) GetModuleFileNameW and CreateProcessW.
The two functions are used by the process to spawn a copy of itself in a suspended state. Similar to this in C.
wchar_t path[MAX_PATH]={0};
GetModuleFileNameW(0,path,MAX_PATH*2);
PROCESS_INFORMATION PI;
STARTUPINFO SI={sizeof(SI)};
CreateProcessW(0,path,0,0,FALSE,CREATE_SUSPENDED,0,0,&SI,&PI);
At this point, we have another process in suspended state.
2) NtUnmapViewOfSection, VirtualAllocEx, and WriteProcessMemory.
NtUnmapViewOfSection(PI.hProcess,0x400000); //0x400000 is the ImageBase of the new spawned process.
pNew=VirtualAllocEx(PI.hProcess,0x400000,0x10000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); //Remember this.
WriteProcessMemory(PI.hProcess,0x400000,pNewImageHeader,0x400,0);
WriteProcessMemory(PI.hProcess,0x401000,pFirstSection,0x1800,0);
WriteProcessMemory(PI.hProcess,0x403000,pSecondSection,0x800,0);
WriteProcessMemory(PI.hProcess,0x404000,pThirdSection,0x200,0);
WriteProcessMemory(PI.hProcess,0x40F000,pFourthSection,0xC00,0);
This unmaps the original image off the new process address space. VirtualAllocEx is then called to allocate memory into the new process in place of the unmapped image. WriteProcessMemory is then used to copy the decrypted code to the new process.
3) GetThreadContext, SetThreadContext, and ResumeThread
CONTEXT CTX={CONTEXT_FULL};
GetThreadContext(&CTX);
CTX.EAX=NewEntryPointInRemoteProcess; //At offset 0xB0 from the start of the CONTEXT structure
SetThreadContext(&CTX); //sets the new entry point
ResumeThread(PI.hThread);
This retrieves the CONTEXT of the new suspended thread, sets a new entry point via changing value of EAX in the CONTEXT structure, flushes the CONTEXT structure back to the new process.
Once we are at the breakpoint on ResumeThread, we have a fully functioning process that is ready to harm.
Now, all you have to do is dump it using any memory dumping tool. Personally, i prefer VSD (Virtual Section Dumper)
Given the parameters passed to VirtualAllocEx, we can use VSD to dump the new image starting from 0x400000 with size 0x10000.
Now, we have the dumped file on disk say dump.exe, what is left is to fix that dump file as follows:
1) Fix the section table. Merge all sections into one big section.
2) Fix the EntryPoint.--> (Value of Eax of the CONTEXT structure passed to SetThreadContext) minus 0x400000
Done.
OllyVB can be found at:
http://code.google.com/p/myollyplugins/downloads/detail?name=OllyVB.dll
VSD can be found at:
http://code.google.com/p/virtualsectiondumper/
|
Very very useful. Thank you .
ps: i already use OllyVB :)
|
Note: Registration is required to post to the forums.
|