Select Page


In my talk at the University of Florida (video link here) i pointed out how important correct error handling in Emulation/Virtualization is. Today we got new ZBot samples and they are using exactly that to avoid generic emulation / unpacking. I had 5 min time to take a couple of Screenshots and to add some comments to it. So here is a closer look to the tartup-code of these ZBots.

They call the API function “SwitchDesktop” from User32.DLL with wrong Desktophandle on purpose. The Desktophandle is always wrong – see the code at “results in invalid handle”.

Usually this API functions sets it’s return code ( Non-Zero for Success ) in register EAX. So they move this result to the stack and since EAX is 4 bytes (unsigned long) you see there a sub of the stackpointer with 4. Alone that code passage is highly obfuscated code and you won’t see that with normal compilers, because there’s no need to push EAX on the stack if you pop it afterwards without any changes in between.

So, they pop EBX (read: the value in EAX is now in EBX) and compare that with Zero. Remember: This function should return Zero, because it got an invalid handle on purpose. Basically this API must return as “Sorry can’t do that, i don’t know that handle – ERROR”. Most emulation systems using so called “Dummy-API’s”. There they just return always true or always false.

Our Behavior-based Virtualization (MX-V) knows such tricks and decrypts the executable and finds interesting stuff inside the file. For example a mutex that gets created after decryption and right before process enumeration (all done in unicode) that hints that the authors of this malware do know about AVIRA Antivirus. But look for yourself:

[VVS] User32:SwitchDesktop – Desktophandle: 7C910208 ERROR: Unknown Handle!
[VVS] Kernel32:GetPrivateProfileIntA – AppName: KeyName: FileName: ”
[VVS] Kernel32:VirtualAlloc – rtx=130000, va=0, sz=1334F, at=3000, p=40
[VVS] Kernel32:VirtualProtect – lpAddress = 00400000, flNewProtect = 00000040 OK
[VVS] Kernel32:IsBadReadPtr Entry – READ ACCESS!
[VVS] Kernel32:IsBadReadPtr Entry – READ ACCESS!
…decompressing here (very simple encrypted)…
[VVS] Kernel32:IsBadReadPtr Entry – READ ACCESS!
[VVS] Kernel32:GetUserDefaultUILanguage – is: English, USA
[VVS] advapi32:OpenProcessToken Entry – OK
[VVS] [ApiDef]: LookupPrivilegeValueW
[VVS] Advapi32:AdjustTokenPrivileges – OK
[VVS] close_emu_handle: 00420000
[VVS] [ApiDef]: GetUserNameW – OK
[VVS] Kernel32:GetCommandLineA – OK
[VVS] Kernel32:CreateMutexW – creates mutex named ‘_AVIRA_21099‘ OK
[VVS] Kernel32:CreateToolhelp32Snapshot – OK, flags: 2, procId: 0
[VVS] [ApiDef]: Process32FirstW NumParams:2 STD_CALL
…process enumeration and continue…

Michael St. Neitzel