Zeus Gameover v3

July 24, 2014

The Dell SonicWALL Threats Research Team has analyzed binaries that are part of a potential revival of the recently taken down Zeus Gameover botnet. SonicWALL's Anti-Spam service detected and blocked the campaign initially reported by Malcovery Security and Brian Krebs. SonicWALL researchers were able to remove the protection scheme used to hide the malware, which masquerades at first glance as an inconspicuous MFC application using a PDF icon, but once ran infects the end-users workstation and begins calling out to command-and-control servers. The Domain Generation Algorithm (DGA) used in this latest iteration appears to differ from previous versions, and the Peer-to-Peer (P2P) component that was previously used does not appear to be included.

Infection Cycle and Indicators of Compromise

A host infected with this latest variant or spin-off of Zeus displays, at a functional level, no major new functionality. Infected hosts were, during this campaign, presented with a spam email with a binary attachment that had a PDF icon. If the attachment is downloaded and ran by an end user, it presents the typical Zeus behavior. A randomly named directory is created in %TEMP% then a randomly named copy of the binary is dropped in the new directory. E.G.

"C:Documents and SettingsaLocal SettingsTempZaofgadeg.exe"

Then a batch file is created, also in %TEMP% to delete the initially downloaded artifact:

 @echo off :raejpugyl del /F /Q /A RSHAIL "C:Documents And Settingsafile.exe" >nul if exist "C:Documents And Settingsafile.exe" goto raejpugyl 

To maintain persistence, a registry run-key is created, pointing at the binary in %TEMP%

 SetValueKey "HKCUSoftwareMicrosoftWindowsCurrentVersionRunGadeg" "C:Documents and SettingsaLocal SettingsTempZaofgadeg.exe" 

From here, we observe the file doing what we expect of Zeus, injecting pieces of itself into running processes and attempting to steal the end-user's banking information. One thing we observed in this version that was not present in other recent versions of Gameover is anti virtual machine and sandbox detection, as detailed below in the unpacking details.

Manually Unpacking

To manually unpack the sample, we'll first need to bypass checks for vboxservice.exe and vmtoolsd.exe, assuming you're analyzing in a VM. If not, this step can obviously be skipped. It should be noted that the code below was data initially that was modified then copied to a newly allocated region of memory which we're debugging, so if you're looking for these strings or code locations in the original binary statically, they will not exist. In the snippet below, we observe two strings being created, then a sequence of Windows API calls to enumerate processes, then iterate through that list and compare running process names to the ones VirtualBox and VMWare use for their tools.

 debug039:01492610 mov     byte ptr [ebp-44h], 'V' debug039:01492614 mov     byte ptr [ebp-43h], 'B' debug039:01492618 mov     byte ptr [ebp-42h], 'o' debug039:0149261C mov     byte ptr [ebp-41h], 'x' debug039:01492620 mov     byte ptr [ebp-40h], 'S' debug039:01492624 mov     byte ptr [ebp-3Fh], 'e' debug039:01492628 mov     byte ptr [ebp-3Eh], 'r' debug039:0149262C mov     byte ptr [ebp-3Dh], 'v' debug039:01492630 mov     byte ptr [ebp-3Ch], 'i' de
bug039:01492634 mov     byte ptr [ebp-3Bh], 'c' debug039:01492638 mov     byte ptr [ebp-3Ah], 'e' debug039:0149263C mov     byte ptr [ebp-39h], '.' debug039:01492640 mov     byte ptr [ebp-38h], 'e' debug039:01492644 mov     byte ptr [ebp-37h], 'x' debug039:01492648 mov     byte ptr [ebp-36h], 'e' debug039:0149264C mov     [ebp-35h], bl debug039:0149264F mov     byte ptr [ebp-2Ch], 'v' debug039:01492653 mov     byte ptr [ebp-2Bh], 'm' debug039:01492657 mov     byte ptr [ebp-2Ah], 't' debug039:0149265B mov     byte ptr [ebp-29h], 'o' debug039:0149265F mov     byte ptr [ebp-28h], 'o' debug039:01492663 mov     byte ptr [ebp-27h], 'l' debug039:01492667 mov     byte ptr [ebp-26h], 's' debug039:0149266B mov     byte ptr [ebp-25h], 'd' debug039:0149266F mov     byte ptr [ebp-24h], '.' debug039:01492673 mov     byte ptr [ebp-23h], 'e' debug039:01492677 mov     byte ptr [ebp-22h], 'x' debug039:0149267B mov     byte ptr [ebp-21h], 'e' debug039:0149267F mov     [ebp-20h], bl debug039:01492682 call    dword ptr [ebp-4A4h]            ; kernel32_CreateToolhelp32Snapshot ... debug039:014926D3 call    esi                             ; kernel32_GetModuleHandleA debug039:014926D5 push    eax debug039:014926D6 call    dword ptr [ebp-4D4h]            ; kernel32_GetModuleFileNameA ... debug039:014926E6 call    dword ptr [ebp-4D0h]            ; kernel32_Process32First debug039:014926EC test    eax, eax debug039:014926EE jz      short loc_1492732 debug039:014926F0 debug039:014926F0 loc_14926F0:                            ; CODE XREF: debug039:0149272Ej ... debug039:014926FA call    dword ptr [ebp-0B0h]            ; kernel32_Process32Next debug039:01492700 test    eax, eax debug039:01492702 jz      short loc_1492732 debug039:01492704 lea     eax, [ebp-79Ch]                 ; current proc debug039:0149270A push    eax debug039:0149270B lea     eax, [ebp-44h]                  ; looking for debug039:0149270E push    eax debug039:0149270F call    doChrCmp debug039:01492714 pop     ecx debug039:01492715 test    eax, eax debug039:01492717 pop     ecx debug039:01492718 jnz     short loc_1492730 debug039:0149271A lea     eax, [ebp-79Ch]                 ; current proc debug039:01492720 push    eax debug039:01492721 lea     eax, [ebp-2Ch]                  ; looking for debug039:01492724 push    eax debug039:01492725 call    doChrCmp debug039:0149272A pop     ecx debug039:0149272B test    eax, eax debug039:0149272D pop     ecx debug039:0149272E jz      short loc_14926F0 

To bypass this, we can simply go to the strings location in memory:

 0011E6A8  56 42 6F 78 53 65 72 76  69 63 65 2E 65 78 65 00  VBoxService.exe. 0011E6B8  F3 00 00 00 FA 00 00 00  76 6D 74 6F 6F 6C 73 64  =...·...vmtoolsd 0011E6C8  2E 65 78 65 00 DD 54 01  BB 7A DD 77 6B 65 72 6E  .exe.¦T.+z¦wkern 

And in IDA, F2 to modify the memory and change a letter of each string, as seen below:

 0011E6A8  55 42 6F 78 53 65 72 76  69 63 65 2E 65 78 65 00  UBoxService.exe. 0011E6B8  F3 00 00 00 FA 00 00 00  75 6D 74 6F 6F 6C 73 64  =...·...umtoolsd 0011E6C8  2E 65 78 65 00 DD 54 01  BB 7A DD 77 6B 65 72 6E  .exe.¦T.+z¦wkern 

The next anti-analysis code we see is looking for a module related to Sandboxie, where CreateToolhelp32Snapshot > Module32First > Module32Next is called to look for sbiedll.dll. The technique to bypass this is the same as for VMWare/Vbox. If any of the above are found, the malware will call the following to terminate:

 debug039:0149367E push    0 debug039:01493680 xor     eax, eax debug039:01493682 call    eax debug039:01493684 retn 

Next we trace further along into the crypter's stub, we see it call CreateProcessW using itself as an argument, then several sections of memory are unmapped using NtUnmapViewOfSection, then it calls VirtualAllocEx. At this point, we have a new child process, and data begins to be written to sections of that child process.

 debug039:01492255 call    [ebp+kernel32_CreateProcessW] ... debug039:01492277 call    dword ptr [ebp-kernel32_GetThreadContext] ... debug039:0149228D call    [ebp+ntdll_NtReadVirtualMemory] debug039:01492293 push    [ebp+var_1C] debug039:01492296 push    [ebp+var_30] debug039:01492299 call    [ebp+NtUnmapViewOfSection] debug039:0149229C push    [ebp+var_1C] debug039:0149229F push    [ebp+var_30] debug039:014922A2 call    [ebp+NtUnmapViewOfSection] debug039:014922A5 push    [ebp+var_1C] debug039:014922A8 push    [ebp+var_30] debug039:014922AB call    [ebp+NtUnmapViewOfSection] debug039:014922AE push    dword ptr [edi+34h] debug039:014922B1 push    [ebp+var_30] debug039:014922B4 call    [ebp+NtUnmapViewOfSection] debug039:014922B7 push    dword ptr [edi+34h] debug039:014922BA push    [ebp+var_30] debug039:014922BD call    [ebp+NtUnmapViewOfSection] debug039:014922C0 push    40h debug039:014922C2 push    3000h debug039:014922C7 push    dword ptr [edi+50h] debug039:014922CA push    dword ptr [edi+34h] debug039:014922CD push    [ebp+var_30] debug039:014922D0 call    [ebp+kernel32_VirtualAllocEx] 

To get further along where the unpacked binary is ready for us to dump, we're looking for CreateProcess > VirtualAlloc > multiple calls to WriteProcessMem
ory then SetThreadContext and finally a call to ResumeThread, like below.

 debug039:01492354 call    [ebp+kernel32_WriteProcessMemory] debug039:0149235A mov     eax, [edi+28h] debug039:0149235D add     eax, [ebp+var_5C]             ; make note of eax here, its OEP debug039:01492360 mov     [ebp+var_1204], eax           ; eax == 00432EA1 debug039:01492366 mov     [ebp+var_120C], eax debug039:0149236C lea     eax, [ebp+var_12BC] debug039:01492372 push    eax debug039:01492373 push    [ebp+var_2C] debug039:01492376 call    [ebp+SetThreadContext] debug039:0149237C push    [ebp+var_2C] debug039:0149237F call    [ebp+kernel32_ResumeThread] 

If we break at 0x01492360, and note the value in EAX, next we need to set a BP on the call to ResumeThread. Break here, but don't execute yet. If we open the process in 010 Editor. the bottom pane has a "Process" tab that shows heap, flags etc. At 0x400000 we observe some memory that starts with an "MZ". Getting warmer. We noted the EP above, so if we drop the probable base address of 0x400000 and add0x32EA1 to the start of the section that has an "MZ" we arrive at a local address of 0x35EA1. Still using 010, if we overwrite 0x558B with0xEBFE here and save:


We can then step over the resume thread and run the parent process. It will exit, and the child process will be running suspended in an infinite loop at the OEP and we can attach here to continue debugging and also dump the unpacked executable. In it's unpacked state at OEP we see a much more familiar entry point, and much more analyzed code than before:


There will still be some strings still encoded, however we see references to the banking software processes Zeus is known to look for to steal information like:

 .text:00408944 00000006 unicode us                 .text:0040894C 00000012 unicode bancline           .text:00408960 00000012 unicode fidelity           .text:00408974 00000012 unicode micrsolv           .text:00408988 00000010 unicode bankman            .text:00408998 0000000E unicode vantiv             .text:004089A8 0000000E unicode episys             .text:004089B8 00000016 unicode jack henry         .text:004089D0 00000014 unicode cruisenet          .text:004089E4 00000014 unicode gplusmain          .text:004089F8 00000026 unicode launchpadshell.exe .text:00408A20 0000001A unicode dirclt32.exe       .text:00408A3C 00000012 unicode wtng.exe           .text:00408A50 0000001A unicode prologue.exe       .text:00408A6C 00000016 unicode silverlake         .text:00408A84 00000014 unicode pcsws.exe          .text:00408A98 00000016 unicode v48d0250s1         .text:00408AB0 0000001A unicode fdmaster.exe       .text:00408ACC 00000010 unicode fastdoc            


GAV Signature "Zbot.A_51" was created to block the binaries associated with spam attachments or other distribution methods. Thus far Dell SonicWALL NGFW Threat Prevention services (GAV/IPS) and email security solutions have been blocking this attack. SonicWALL researchers will also continue tracking, analyzing and reporting on this new campaign as it develops.

Related Articles and References: