Zeus Analysis – Memory Forensics via Volatility

I am planning to do a blog series on malware analysis using the Zeus sample that I recently received in an email. The idea is not only to share what it does, but to focus mostly on sufficient details (without boring the average reader to death) of how it does what it does, and techniques and tools an analyst can use during the analysis. We will be looking at it through various angles and tools.

It is quite common for malware to have several layers of encoding obfuscations and go through various steps of downloaders. Therefore, often a quick first stab at it is to let it run through a locally deployed automated dynamic analysis sandboxing solution such as Cuckoo or use various freely available services such as malwr. (Caveat: hastily submitting a targetted attack sample to an online service is not a very good idea, as this can alert the attackers that they have been discovered, but this is not we are talking about today). Furthermore, there is a cat and mouse chase going with malware defeating or making it hard to do automatic analysis and reverse engineering, so in many cases it makes sense to just take a look at an infected system via memory forensics and see how malware has established itself on our system, this way we can discover the various different aspects of malware and can work backwards and forewords on pieces that we are interested in further learning about.

In this post we will take a look at what can we learn from an infected system, using Volatility and how can we extract the final piece of decrypted/decoded/unpacked malicious code for further analysis.

So it begins with someone who spells her last name with a lower case letter sending me an email so I can review the export License and invoice:

Kindly open to see export License and payment invoice attached, meanwhile we sent the balance payment yesterday. Please confirm if it has settled in your account or you can call if there is any problem.


Karen parker

But there is a problem I (and most likely you too) don’t get paid to review licenses and invoices. So let’s not worry about the information in the attachment for humans but review what it has for our machines.

We will use Volatality a free available and very powerful tool for memory forensics.

The first step is to acquire memory image, we will use the freely available VirtualBox to run a Windows XP VM, and using the technique described here, get a memory dump of the machine after running the attachment that contained an exe (invoice copy) file. More specifically I used the technique mentioned in section RAM_dump_with_VirtualBox:_via_pgmphystofile

The first thing I would do is use psxview which enumerates processes using various techniques and is likely to detect processes hidden by rootkits as well.

D:downloads>volatility-2.2.standalone.exe –profile=WinXPSP3x86 -f TempXP_SP3_debug_VM_raw_mem_after_zeus.raw psxview

Volatile Systems Volatility Framework 2.2

Offset(P)  Name                    PID pslist psscan thrdproc pspcdid csrss

———- ——————– —— —— —— ——– ——- —–

0x06541da0 svchost.exe            1140 True   True   False    True    True

0x06531b10 wuauclt.exe            1040 True   True   False    True    True

0x065e44d8 svchost.exe             952 True   True   False    True    True

0x0667f818 VBoxService.exe         820 True   True   False    True    True

0x0655eca8 svchost.exe             864 True   True   False    True    True

0x0662fda0 smss.exe                368 True   True   False    True    False

0x06649228 csrss.exe               584 True   True   False    True    False

0x06384da0 alg.exe                1284 True   True   False    True    True

0x066cebb8 winlogon.exe            608 True   True   False    True    True

0x0658eda0 svchost.exe            2004 True   True   False    True    True

0x0657a9a0 lsass.exe               664 True   True   False    True    True

0x062fb020 wmiprvse.exe           2424 True   True   False    True    True

0x067c69c8 System                    4 True   True   False    True    False

0x0658e6f8 VBoxTray.exe           1788 True   True   False    True    True

0x065d4da0 svchost.exe            1100 True   True   False    True    True

0x06581da0 ctfmon.exe             1796 True   True   False    True    True

0x0658a4d8 services.exe            652 True   True   False    True    True

0x066f7da0 jookov.exe             3504 True   True   False    True    False     <– Were you invited to the party?

0x066c9b10 explorer.exe           1532 True   True   False    True    True

0x065de7f0 svchost.exe            1056 True   True   False    True    True

0x0662e728 spoolsv.exe            1652 True   True   False    True    True

0x063c6778 wscntfy.exe            1548 True   True   False    True    True


As we will see below that the process has already exited and is not resident in memory, as an example of using knowledge from memory forensics to identify interesting pieces and investigate further, if we wanted to get more information about this suspicious process we can go back to VM, reverting it to a clean snapshot, infecting again and looking at procmon logs or via logs from automated dynamic analysis solution. Let’s take a look at log from procmon.exe:

4:28:23.2233611 PM invoice copy.exe    3472 WriteFile         C:Documents and SettingsARApplication DataYnigkejookov.exe   SUCCESS Offset: 0, Length: 332,800

4:28:23.2739396 PM invoice copy.exe    3472 Process Create    C:Documents and SettingsARApplication DataYnigkejookov.exe   SUCCESS PID: 3504,

4:28:24.8114842 PM Explorer.EXE        1532 RegSetValue       HKCUSoftwareMicrosoftWindowsCurrentVersionRunJookov         SUCCESS Type: REG_SZ, Length: 132, Data: C:Documents and SettingsARApplication DataYnigkejookov.exe

The process was not resident in memory when the dump was taken:

D:>volatility-2.2.standalone.exe –profile=WinXPSP3x86 -f TempZEUS_invoiceXP_SP3_debug_VM_raw_mem_after_zeus.raw procexedump -v -D . -p 3504 Volatile Systems Volatility Framework 2.2

Process(V) ImageBase  Name                 Result

———- ———- ——————– ——

0x864f7da0 ———- jookov.exe           Error: PEB at 0x7ffdf000 is paged

What we have seen so far is that using the Run registry key the malware sets up a process to be started when Windows start, but the process then exits soon, one possible way that malware is still executing is by injecting code in the trusted processes. Volatility has several plugins that let us discover this and extract the injected code, note that this extracted code is very likely to be neither obfuscated nor encrypted/encoded, as this is what will be running in the context of the trusted processe(s) and is usually injected there after unpacking/decrypting etc.

Volatility’s has a bunch of useful commands for Windows Malware Hunting, you can check them out here. We will look at some of them mostly the ones that gave us interesting information in this case.


Running the apihooks command, we can have an idea of what routines does the Malware hook, and will also give an highlevel idea what the malware is upto.

Taking a look at all the unique functions hooked we see a very interesting list:

Function: activeds.dll!<unknown> at 0x76e1ef81Function: CRYPT32.dll!PFXImportCertStore at 0x77af012fFunction: ntdll.dll!LdrLoadDll at 0x7c91632dFunction: ntdll.dll!NtCreateThread at 0x7c90d1aeFunction: ntdll.dll!ZwCreateThread at 0x7c90d1aeFunction: Secur32.dll!DecryptMessage at 0x77fea6dcFunction: Secur32.dll!DeleteSecurityContext at 0x77fe2d26

Function: Secur32.dll!EncryptMessage at 0x77fea68d

Function: Secur32.dll!SealMessage at 0x77fea68d

Function: Secur32.dll!UnsealMessage at 0x77fea6dc

Function: USER32.dll!GetClipboardData at 0x7e430dba

Function: USER32.dll!TranslateMessage at 0x7e418bf6

Function: WININET.dll!HttpQueryInfoA at 0x3d94879d

Function: WININET.dll!HttpQueryInfoW at 0x3d94bda8

Function: WININET.dll!HttpSendRequestA at 0x3d95eea1

Function: WININET.dll!HttpSendRequestExA at 0x3d9ba6da

Function: WININET.dll!HttpSendRequestExW at 0x3d9ba733

Function: WININET.dll!HttpSendRequestW at 0x3d94face

Function: WININET.dll!InternetCloseHandle at 0x3d949098

Function: WININET.dll!InternetQueryDataAvailable at 0x3d94bf93

Function: WININET.dll!InternetReadFile at 0x3d94655b

Function: WININET.dll!InternetReadFileExA at 0x3d963271

Function: WININET.dll!InternetReadFileExW at 0x3d963239

Function: WININET.dll!InternetWriteFile at 0x3d9a6116

Function: WS2_32.dll!closesocket at 0x71ab3e2b

Function: WS2_32.dll!freeaddrinfo at 0x71ab2b0b

Function: WS2_32.dll!FreeAddrInfoW at 0x71ab2b0b

Function: WS2_32.dll!getaddrinfo at 0x71ab2a6f

Function: WS2_32.dll!GetAddrInfoW at 0x71ab2899

Function: WS2_32.dll!gethostbyname at 0x71ab5355

Function: WS2_32.dll!recv at 0x71ab676f

Function: WS2_32.dll!send at 0x71ab4c27

Function: WS2_32.dll!WSAGetOverlappedResult at 0x71ac0d1b

Function: WS2_32.dll!WSARecv at 0x71ab4cb5

Function: WS2_32.dll!WSASend at 0x71ab68fa

So we see that malware is hooking low level socket communication functions, higher level WININET internet communication routines, crypto routines, along with thread creation and dll load routines.

The processes that were hooked were:

Process: 1040 (wuauclt.exe)  

Process: 1056 (svchost.exe)  

Process: 1532 (explorer.exe) 

Process: 1548 (wscntfy.exe)  

Process: 1788 (VBoxTray.exe) 

Process: 1796 (ctfmon.exe)   

I am assuming it would be hooking other interesting processes like browsers, had they been running at the time dump was taken.

Getting the injected code

Each entry from the output of apihook looks like this

************************************************************************Hook mode: UsermodeHook type: Inline/TrampolineProcess: 1532 (explorer.exe)Victim module: ntdll.dll (0x7c900000 – 0x7c9b2000)Function: ntdll.dll!NtCreateThread at 0x7c90d1aeHook address: 0x303995c

Hooking module: <unknown>Disassembly(0):

0x7c90d1ae e9a9c77286       JMP 0x303995c

0x7c90d1b3 ba0003fe7f       MOV EDX, 0x7ffe0300

0x7c90d1b8 ff12             CALL DWORD [EDX]

0x7c90d1ba c22000           RET 0x20

0x7c90d1bd 90               NOP

0x7c90d1be b836000000       MOV EAX, 0x36

0x7c90d1c3 ba               DB 0xba

0x7c90d1c4 0003             ADD [EBX], AL


0x303995c 55               PUSH EBP

0x303995d 8bec             MOV EBP, ESP

0x303995f 83e4f8           AND ESP, -0x8

0x3039962 83ec24           SUB ESP, 0x24

0x3039965 a1f8170503       MOV EAX, [0x30517f8]

0x303996a 53               PUSH EBX

0x303996b 56               PUSH ESI

0x303996c 57               PUSH EDI

0x303996d 89442410         MOV [ESP+0x10], EAX

0x3039971 e8               DB 0xe8

0x3039972 21               DB 0x21

0x3039973 25               DB 0x25


So back to how do we extract the binary comprising of the injected code, fortunately, volatility has another plugin malfind that scans processes for memory pages containing injected code and dumps it as a binary.

Running malfind on the image we get various entries showing various different binaries injected in a process, let’s take a look at what we see in regards to the ntdll.dll!NtCreateThread being hooked in explorer.exe

We see that malfind detects injected binaries in three different regions in explorer.exe, and it dumps three binaries (if malfind was run with -D option) corresponding to these regions.

Process: explorer.exe Pid: 1532 Address: 0x2b10000  

Process: explorer.exe Pid: 1532 Address: 0x3010000   

Process: explorer.exe Pid: 1532 Address: 0x3d920000 

Based on the apihook output, the hook for CreateThread is at 0x303995c, let’s take a look at the malfind output for 0x3010000

Process: explorer.exe Pid: 1532 Address: 0x3010000Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITEFlags: CommitCharge: 72, MemCommit: 1, PrivateMemory: 1, Protection: 60x03010000  4d 5a 00 00 00 00 00 00 00 00 00 00 00 00 00 00   MZ…………..0x03010010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   …………….0x03010020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   …………….0x03010030  00 00 00 00 00 00 00 00 00 00 00 00 20 01 00 00   …………….0x3010000 4d               DEC EBP

0x3010001 5a               POP EDX

0x3010002 0000             ADD [EAX], AL

0x3010004 0000             ADD [EAX], AL

0x3010006 0000             ADD [EAX], AL

0x3010008 0000             ADD [EAX], AL

So we see that it successfully finds the MZ header as well, that may not be true every time, but we can still work with that, as most of the time the header is corrupted anyways.

At this point we use impscan that scans and shows us which functions are imported, so we can give it a process id, and a base address where we think the injected code starts and it will tell us the about the imported functions:

For what we are looking at the moment if we run it as

impscan -v -b 0x03010000 -p 1532

This gives us output like

IAT        Call       Module               Function———- ———- ——————– ——–0x03011000 0x77df78ab ADVAPI32.dll         IsWellKnownSid0x03011004 0x77ddf10f ADVAPI32.dll         ConvertSidToStringSidW0x03011008 0x77e34ce5 ADVAPI32.dll         InitiateSystemShutdownExW0x0301100c 0x77ddd767 ADVAPI32.dll         RegSetValueExW0x03011010 0x77dd7bd9 ADVAPI32.dll         RegEnumKeyExW

This also, to some extent, gives us an idea of what the malicious code is upto.

impscan also used to generate an IDC script to be run in IDA while analyzing the corresponding binary, it does not do that any more, but we can run a script on impscan’s output and get entries like

MakeName(0x03011000, "ADVAPI32.dll.IsWellKnownSid");
MakeName(0x03011004, "ADVAPI32.dll.ConvertSidToStringSidW");
MakeName(0x03011008, "ADVAPI32.dll.InitiateSystemShutdownExW");
Edit: Michael Hale Ligh (@iMHLv2) pointed out that idc script is still outputted with --output=idc [--output-file=test.idc]

We can then open the binary dumped by malfind in IDA (make sure you select open as a Binary File, and not the default “Portable Executable ..”, as the header is usually corrupted or not available and IDA may get confused. Don’t forget to rebase the binary to correspond to the the address it is loaded in memory. After that you can do

File -> Script Command and run the above mentioned MakeName entries, and start reverse engineering with dynamic analysis of the injected code.

IDA Create Thread Hook

This is it for now. I look forward to continue this series on Zeus analysis and would like to your comments.

My VM image soon fetched some AV that was very concerned and was telling me how my machine was infected, but needed some $$$ to fix it.

Infected with Rogue Anti Virus

I look forward to continuing this series, and welcome your comments and feedback.

Zubair Ashraf

X-Force Security Researcher, IBM Security

Zubair Ashraf is a security researcher and team lead for IBM X-Force Advanced Research. He is very passionate about...