Showing posts with label unpacking. Show all posts
Showing posts with label unpacking. Show all posts

Monday, November 30, 2015

Guest Post: Martin Korman (VolatilityBot - An Automated Malicious Code Dumper)

This is a guest post from Martin Korman, author of VolatilityBot.

Lately, I've found myself manually unpacking different versions of the same malware in order to perform static analysis with IDA and BinDiff. Therefore, I've decided to write a small system that will automate the entire process – the VolatilityBot.

How does VolatilityBot work?
  1. It executes the malware on a VM.
  2. It waits for a pre-defined period of time.
  3. It suspends the VM.
  4. It compares the snapshot to a golden image of the VM, finds new processes, injected code, loaded DLLs or Kernel Modules, dumps them from the memory and fixes the PE file in order to make static analysis easier.

All metadata is saved to a SQLite DB. Dumps are saved to a configured storage path on disk. All PE files pass a short static analysis and reports are stored as well. VolatilityBot can theoretically manage an unlimited quantity of virtual machines, depending on the performance of your host machine. 

Some core capabilities of this automation tool were designed to make it as scalable as possible and easy to work with over time:

  • The Bot-Excavator's Manager can handle an unlimited number of machines at once, all depending on the performance of the researcher's equipment.
  • Automatic "Golden Image" generation is provided in order to ease the process of creating all "Golden Image" data. Just create your configuration file, and execute the script.
  • To simplify scalability, any database supported by SQLalchemy can be set or replaced as needed. The default Bot-Excavator's backend saves data to an SQLite database.
  • Memory dumps and data from all configured post processing modules are saved to a predefined storage directory.
  • Add tags to each execution of the script for quick visual reference to information you may need later.
  • Add dynamic tags to post-processing modules. For example, for malware that loads a kernel mode driver, tag it with "loads_kmd".Volatility Bot-Excavator's modular structure makes it easy to add additional modules and post-processors that may be deemed necessary with time. 

Let's dive deeper into the architecture of VolatilityBot. The Bot-Excavator is made of four (4) major components:


1. The Manager. This is the core of the Bot-Excavator tool. The Manager executes the automatic extraction as well as the post-processing modules. This module also controls the associated machines' activity to streamline the workflow.


2. Machines Module. This is an abstract design of a research machine; it contains five functions: Revert, Start, Suspend, Clean-up and Get memory path. Each machine has a minimal python agent running, that listens and waits for a malware sample. When the sample is sent, it executes it by double clicking the sample, using an AutoIt script. 


The agent is really minimal in order to not affect the behavior of the malware in the machine. The agent does not perform any API hooking and does not control the machine in any form besides executing the malware. The machines are controlled and monitored by the manager component, which knows not to send more analyses to a machine if its busy or if it encountered any errors analyzing the previous sample.


3. Code Extractors. This component consists of a number of modules grouped together for the purpose of extracting all the different malicious code components from memory. These are separate for code injections, new processes, etc. This component is modular and allows researchers to write new code for other extractors they may need.


These are the existing modules for this component:

  • injected_code – uses the Volatility "malfind" plugin in order to find suspect memory areas, after dumping them it tries to determine if the section contains a valid PE or valid shell code. If it found a valid PE, it fixes PE the header. Either way it will extract strings and execute YARA on the section dumped from memory.
  • module_scan - Uses the Volatility "modscan" plugin to load kernel modules. It detects and dumps newly loaded kernel modules.
  • create_process_dump - Uses the Volatility "procdump" and "pslist" plugins to dump new processes created by malware. Executes YARA, and extracts malware strings.
  • create_process_dump_as - Uses the Volatility "procdump" plugin to dump address space. Executes YARA, and extracts malware strings.
  • hooks – Extract API hooks done by malware (User-mode and Kernel-mode)
4. Post-Processing Modules. The post-processing modules kick in after the extraction is complete. They are then tasked with automated actions like fixing the PE, or availing the resulting elements to static analysis, YARA scans, strings and IP address logging etc.


This module type can help with:

  • Executing the configured YARA rules on post-extraction input as defined by the researcher.
  • Extracting strings from the input defined. Other modules can be layered on top in order to extract IP addresses, URLs, etc.
  • Producing a report for static analysis with basic PE analysis of the input file.

Because the malware samples are executed in a virtual machine, in order to avoid VM detection, a few tricks were used:

  • Registry keys cleanup (all VMware stuff I don't think there is a need to describe, as there's a lot of information on the internet regarding this issue).
  • A macro that moves the mouse and executes the malware.
  • Of course, no VMware tools on the machine.

Documentation and installation instructions are available here:
https://bitbucket.org/martink90/volatilitybot_public/downloads/Documentation_Nov_2015.pdf






For any questions, feel free to reach me via twitter (@MartinKorman), or open an issue in the project's Bit Bucket. 

Wednesday, January 23, 2013

HowTo: Extract "Hidden" API-Hooking BHO DLLs

A Twitter user recently asked a question to the @volatility account: "can you please tell me how to extract SilentBanker [from memory]"? We like to encourage people to work through problems on their own, so our initial advice was short and sweet: SilentBanker is a BHO so find the DLL and extract it with dlldump. The follow up question from the Twitter user was one that likely many other people have had in the past (regarding SilentBanker or any other malware with similar characteristics), so we turned the reply into a blog post. In particular, the user could find the BHO by querying the registry, but it did not appear to be loaded in any process.

So, how do you find the DLL in order to dump it?

Identifying the BHO DLL

Let's re-trace the user's steps and see how the task might be completed. Given the knowledge that its a BHO, you might start by getting the CLSID with printkey:

$ python vol.py -f silentbanker.vmem printkey -K 'Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects'
Volatile Systems Volatility Framework 2.3_alpha
Legend: (S) = Stable   (V) = Volatile

----------------------------
Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\software
Key name: Browser Helper Objects (S)
Last updated: 2010-08-15 18:54:02 

Subkeys:
  (S) {00009E9F-DDD7-AA59-AA7D-AA4B7D6BE000}

Then you would resolve the full path to the BHO DLL by querying the CLSID's InprocServer32 value, like this:

$ python vol.py -f silentbanker.vmem printkey -K 'Classes\CLSID\{00009E9F-DDD7-AA59-AA7D-AA4B7D6BE000}\InprocServer32'
Volatile Systems Volatility Framework 2.3_alpha
Legend: (S) = Stable   (V) = Volatile

----------------------------
Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\software
Key name: InprocServer32 (S)
Last updated: 2010-08-15 18:54:02 

Subkeys:

Values:
REG_SZ                        : (S) C:\WINDOWS\system32\mscorews.dll
REG_SZ        ThreadingModel  : (S) Apartment

DLLs and File Object Handles

And this is where our friend got stuck. Using dlllist, it does not appear that mscorews.dll is loaded in any process:

$ python vol.py -f silentbanker.vmem dlllist | grep mscorews
Volatile Systems Volatility Framework 2.3_alpha

Furthermore, as the user noted, filescan locates a FILE_OBJECT that represents mscorews.dll, but there are 0 open handles to the object. 

$ python vol.py -f silentbanker.vmem filescan | grep mscorews
Volatile Systems Volatility Framework 2.3_alpha
Offset(P)    #Ptr   #Hnd Access Name
---------- ------ ------ ------ ----
[snip]
0x04b5b4b8      1      0 R--r-d \Device\HarddiskVolume1\WINDOWS\system32\mscorews.dll
[snip]

First you must understand that when a process loads a DLL, a handle to the DLL is opened (creating a FILE_OBJECT), the file's contents are read and mapped into process memory, and then the file handle is closed. So if there are 0 open handles to a FILE_OBJECT, that does not indicate that the DLL was not, or is not, loaded in a process. Don't believe me? Well, kernel32.dll is loaded in *every* process - that is a fact - but both of the FILE_OBJECTs that still reside in physical memory show 0 handles:

$ python vol.py -f silentbanker.vmem filescan | grep kernel32
Volatile Systems Volatility Framework 2.3_alpha
0x0111ad28      1      0 R--rwd \Device\HarddiskVolume1\WINDOWS\system32\kernel32.dll
0x05e39748      1      0 R--rwd \Device\HarddiskVolume1\WINDOWS\system32\kernel32.dll

Alright, back to the task of finding this DLL. If we're looking for a BHO, our best bet is to look Windows Explorer (explorer.exe) or Internet Explorer (IEXPLORE.EXE). Other processes don't load BHOs, so no need to look elsewhere. Also, intuition tells us that there's a good reason the malware would manifest as a BHO DLL - to inspect, alter, or log the behavior of the target process. Based on that - I immediately think API hooks.

Leveraging API Hooks as a Code Map

The apihooks plugin will not only tell you what functions are hooked, but give you disassembly of the code, which is critical for finding out where the "hidden" DLL exists. In the output below, you'll notice there are about 10 hooked APIs, all of which take an initial hop into a different segment of memory. For example the first API, kernel32!ExitProcess is redirected to 0xe50000. The second entry, user32!DispatchMessageA is redirected to 0x10e0000. At first glance this may appear like a Poison Ivy style fragmented code injection, but its not. Each of the smaller initial hops contain a small sequence of instructions to redirect execution to the main body of SilentBanker's code. 

$ python vol.py -f silentbanker.vmem -p 1884 apihooks --quick
Volatile Systems Volatility Framework 2.3_alpha
************************************************************************
Hook mode: Usermode
Hook type: Inline/Trampoline
Process: 1884 (IEXPLORE.EXE)
Victim module: kernel32.dll (0x7c800000 - 0x7c8f4000)
Function: kernel32.dll!ExitProcess at 0x7c81caa2
Hook address: 0xe50000
Hooking module: 

Disassembly(0):
0x7c81caa2 e959356384       JMP 0xe50000
0x7c81caa7 6aff             PUSH -0x1
0x7c81caa9 68b0f3e877       PUSH DWORD 0x77e8f3b0
0x7c81caae ff7508           PUSH DWORD [EBP+0x8]
0x7c81cab1 e846ffffff       CALL 0x7c81c9fc
0x7c81cab6 e9               DB 0xe9
0x7c81cab7 29cf             SUB EDI, ECX
0x7c81cab9 01               DB 0x1

Disassembly(1):
0xe50000 58               POP EAX
0xe50001 680500e600       PUSH DWORD 0xe60005
0xe50006 6800000000       PUSH DWORD 0x0
0xe5000b 680000807c       PUSH DWORD 0x7c800000
0xe50010 6828180310       PUSH DWORD 0x10031828
0xe50015 50               PUSH EAX
0xe50016 688e9b0210       PUSH DWORD 0x10029b8e
0xe5001b c3               RET
0xe5001c 0000             ADD [EAX], AL
0xe5001e 0000             ADD [EAX], AL

************************************************************************
Hook mode: Usermode
Hook type: Inline/Trampoline
Process: 1884 (IEXPLORE.EXE)
Victim module: USER32.dll (0x77d40000 - 0x77dd0000)
Function: USER32.dll!DispatchMessageA at 0x77d4bcbd
Hook address: 0x10e0000
Hooking module: 

Disassembly(0):
0x77d4bcbd e93e433989       JMP 0x10e0000
0x77d4bcc2 6a01             PUSH 0x1
0x77d4bcc4 ff7508           PUSH DWORD [EBP+0x8]
0x77d4bcc7 e8fdcbffff       CALL 0x77d488c9
0x77d4bccc 5d               POP EBP
0x77d4bccd c20400           RET 0x4
0x77d4bcd0 8b4508           MOV EAX, [EBP+0x8]
0x77d4bcd3 e9               DB 0xe9
0x77d4bcd4 47               INC EDI

Disassembly(1):
0x10e0000 58               POP EAX
0x10e0001 6805000f01       PUSH DWORD 0x10f0005
0x10e0006 6800000000       PUSH DWORD 0x0
0x10e000b 680000807c       PUSH DWORD 0x7c800000
0x10e0010 6828180310       PUSH DWORD 0x10031828
0x10e0015 50               PUSH EAX
0x10e0016 68619f0210       PUSH DWORD 0x10029f61
0x10e001b c3               RET
0x10e001c 0000             ADD [EAX], AL
0x10e001e 0000             ADD [EAX], AL

************************************************************************
Hook mode: Usermode
Hook type: Inline/Trampoline
Process: 1884 (IEXPLORE.EXE)
Victim module: USER32.dll (0x77d40000 - 0x77dd0000)
Function: USER32.dll!DispatchMessageW at 0x77d489d9
Hook address: 0x1100000
Hooking module: 

Disassembly(0):
0x77d489d9 e922763b89       JMP 0x1100000
0x77d489de 6a00             PUSH 0x0
0x77d489e0 ff7508           PUSH DWORD [EBP+0x8]
0x77d489e3 e8e1feffff       CALL 0x77d488c9
0x77d489e8 5d               POP EBP
0x77d489e9 c20400           RET 0x4
0x77d489ec 90               NOP
0x77d489ed 90               NOP
0x77d489ee 90               NOP
0x77d489ef 90               NOP
0x77d489f0 90               NOP

Disassembly(1):
0x1100000 58               POP EAX
0x1100001 6805001101       PUSH DWORD 0x1110005
0x1100006 6800000000       PUSH DWORD 0x0
0x110000b 680000807c       PUSH DWORD 0x7c800000
0x1100010 6828180310       PUSH DWORD 0x10031828
0x1100015 50               PUSH EAX
0x1100016 68619f0210       PUSH DWORD 0x10029f61
0x110001b c3               RET
0x110001c 0000             ADD [EAX], AL
0x110001e 0000             ADD [EAX], AL

************************************************************************
Hook mode: Usermode
Hook type: Inline/Trampoline
Process: 1884 (IEXPLORE.EXE)
Victim module: USER32.dll (0x77d40000 - 0x77dd0000)
Function: USER32.dll!GetClipboardData at 0x77d6fcb2
Hook address: 0x10c0000
Hooking module: 

Disassembly(0):
0x77d6fcb2 e949033589       JMP 0x10c0000
0x77d6fcb7 83ec2c           SUB ESP, 0x2c
0x77d6fcba 56               PUSH ESI
0x77d6fcbb 57               PUSH EDI
0x77d6fcbc 8d45d4           LEA EAX, [EBP+0xffffffd4]
0x77d6fcbf 50               PUSH EAX
0x77d6fcc0 ff7508           PUSH DWORD [EBP+0x8]
0x77d6fcc3 e8e8000000       CALL 0x77d6fdb0
0x77d6fcc8 8bf0             MOV ESI, EAX

Disassembly(1):
0x10c0000 58               POP EAX
0x10c0001 6805000d01       PUSH DWORD 0x10d0005
0x10c0006 6800000000       PUSH DWORD 0x0
0x10c000b 680000807c       PUSH DWORD 0x7c800000
0x10c0010 6828180310       PUSH DWORD 0x10031828
0x10c0015 50               PUSH EAX
0x10c0016 68bc9f0210       PUSH DWORD 0x10029fbc
0x10c001b c3               RET
0x10c001c 0000             ADD [EAX], AL
0x10c001e 0000             ADD [EAX], AL

************************************************************************
Hook mode: Usermode
Hook type: Inline/Trampoline
Process: 1884 (IEXPLORE.EXE)
Victim module: ADVAPI32.dll (0x77dd0000 - 0x77e6b000)
Function: ADVAPI32.dll!CryptDeriveKey at 0x77dea685
Hook address: 0xeb0000
Hooking module: 

Disassembly(0):
0x77dea685 e976590c89       JMP 0xeb0000
0x77dea68a de77e8           FIDIV WORD [EDI+0xffffffe8]
0x77dea68d 88c2             MOV DL, AL
0x77dea68f fe               DB 0xfe
0x77dea690 ff33             PUSH DWORD [EBX]
0x77dea692 f6               DB 0xf6
0x77dea693 8975d8           MOV [EBP+0xffffffd8], ESI
0x77dea696 8975e4           MOV [EBP+0xffffffe4], ESI
0x77dea699 8975d0           MOV [EBP+0xffffffd0], ESI
0x77dea69c 89               DB 0x89

Disassembly(1):
0xeb0000 58               POP EAX
0xeb0001 680500ec00       PUSH DWORD 0xec0005
0xeb0006 6800000000       PUSH DWORD 0x0
0xeb000b 680000807c       PUSH DWORD 0x7c800000
0xeb0010 6828180310       PUSH DWORD 0x10031828
0xeb0015 50               PUSH EAX
0xeb0016 687fa00210       PUSH DWORD 0x1002a07f
0xeb001b c3               RET
0xeb001c 0000             ADD [EAX], AL
0xeb001e 0000             ADD [EAX], AL

************************************************************************
Hook mode: Usermode
Hook type: Inline/Trampoline
Process: 1884 (IEXPLORE.EXE)
Victim module: ADVAPI32.dll (0x77dd0000 - 0x77e6b000)
Function: ADVAPI32.dll!CryptGenKey at 0x77e114b1
Hook address: 0xef0000
Hooking module: 

Disassembly(0):
0x77e114b1 e94aeb0d89       JMP 0xef0000
0x77e114b6 e177             LOOPZ 0x77e1152f
0x77e114b8 e85c54fcff       CALL 0x77dd6919
0x77e114bd 33f6             XOR ESI, ESI
0x77e114bf 8975d8           MOV [EBP+0xffffffd8], ESI
0x77e114c2 8975e4           MOV [EBP+0xffffffe4], ESI
0x77e114c5 8975dc           MOV [EBP+0xffffffdc], ESI
0x77e114c8 89               DB 0x89

Disassembly(1):
0xef0000 58               POP EAX
0xef0001 680500f000       PUSH DWORD 0xf00005
0xef0006 6800000000       PUSH DWORD 0x0
0xef000b 680000807c       PUSH DWORD 0x7c800000
0xef0010 6828180310       PUSH DWORD 0x10031828
0xef0015 50               PUSH EAX
0xef0016 6862a10210       PUSH DWORD 0x1002a162
0xef001b c3               RET
0xef001c 0000             ADD [EAX], AL
0xef001e 0000             ADD [EAX], AL

************************************************************************
Hook mode: Usermode
Hook type: Inline/Trampoline
Process: 1884 (IEXPLORE.EXE)
Victim module: ADVAPI32.dll (0x77dd0000 - 0x77e6b000)
Function: ADVAPI32.dll!CryptImportKey at 0x77dea879
Hook address: 0xed0000
Hooking module: 

Disassembly(0):
0x77dea879 e982570e89       JMP 0xed0000
0x77dea87e de77e8           FIDIV WORD [EDI+0xffffffe8]
0x77dea881 94               XCHG ESP, EAX
0x77dea882 c0feff           SAR DH, 0xff
0x77dea885 33f6             XOR ESI, ESI
0x77dea887 8975d4           MOV [EBP+0xffffffd4], ESI
0x77dea88a 33db             XOR EBX, EBX
0x77dea88c 895de4           MOV [EBP+0xffffffe4], EBX
0x77dea88f 89               DB 0x89
0x77dea890 75               DB 0x75

Disassembly(1):
0xed0000 58               POP EAX
0xed0001 680500ee00       PUSH DWORD 0xee0005
0xed0006 6800000000       PUSH DWORD 0x0
0xed000b 680000807c       PUSH DWORD 0x7c800000
0xed0010 6828180310       PUSH DWORD 0x10031828
0xed0015 50               PUSH EAX
0xed0016 68f2a00210       PUSH DWORD 0x1002a0f2
0xed001b c3               RET
0xed001c 0000             ADD [EAX], AL
0xed001e 0000             ADD [EAX], AL

************************************************************************
Hook mode: Usermode
Hook type: Inline/Trampoline
Process: 1884 (IEXPLORE.EXE)
Victim module: ws2_32.dll (0x71ab0000 - 0x71ac7000)
Function: ws2_32.dll!connect at 0x71ab406a
Hook address: 0xe90000
Hooking module: 

Disassembly(0):
0x71ab406a e991bf3d8f       JMP 0xe90000
0x71ab406f 83ec18           SUB ESP, 0x18
0x71ab4072 57               PUSH EDI
0x71ab4073 8d45e8           LEA EAX, [EBP+0xffffffe8]
0x71ab4076 50               PUSH EAX
0x71ab4077 8d45ec           LEA EAX, [EBP+0xffffffec]
0x71ab407a 50               PUSH EAX
0x71ab407b ff152840ac71     CALL DWORD [0x71ac4028]
0x71ab4081 33               DB 0x33

Disassembly(1):
0xe90000 58               POP EAX
0xe90001 680500ea00       PUSH DWORD 0xea0005
0xe90006 6800000000       PUSH DWORD 0x0
0xe9000b 680000807c       PUSH DWORD 0x7c800000
0xe90010 6828180310       PUSH DWORD 0x10031828
0xe90015 50               PUSH EAX
0xe90016 6818a00210       PUSH DWORD 0x1002a018
0xe9001b c3               RET
0xe9001c 0000             ADD [EAX], AL
0xe9001e 0000             ADD [EAX], AL

************************************************************************
Hook mode: Usermode
Hook type: Inline/Trampoline
Process: 1884 (IEXPLORE.EXE)
Victim module: ws2_32.dll (0x71ab0000 - 0x71ac7000)
Function: ws2_32.dll!send at 0x71ab428a
Hook address: 0xe70000
Hooking module: 

Disassembly(0):
0x71ab428a e971bd3b8f       JMP 0xe70000
0x71ab428f 83ec10           SUB ESP, 0x10
0x71ab4292 56               PUSH ESI
0x71ab4293 57               PUSH EDI
0x71ab4294 33ff             XOR EDI, EDI
0x71ab4296 813d2840ac714894ab71 CMP DWORD [0x71ac4028], 0x71ab9448
0x71ab42a0 0f               DB 0xf
0x71ab42a1 84               DB 0x84

Disassembly(1):
0xe70000 58               POP EAX
0xe70001 680500e800       PUSH DWORD 0xe80005
0xe70006 6800000000       PUSH DWORD 0x0
0xe7000b 680000807c       PUSH DWORD 0x7c800000
0xe70010 6828180310       PUSH DWORD 0x10031828
0xe70015 50               PUSH EAX
0xe70016 68b9990210       PUSH DWORD 0x100299b9
0xe7001b c3               RET
0xe7001c 0000             ADD [EAX], AL
0xe7001e 0000             ADD [EAX], AL

Can you tell what address range to dump now? For ExitProcess, there's a PUSH DWORD 0x10029b8e followed by a RET. For DispatchMessageA, there's a PUSH DWORD 0x10029f61 followed by a RET. For other APIs, they go to 0x10029fbc, 0x1002a07f, and 0x1002a162, etc. So you can bet, regardless of the initial hop addresses, all hooked APIs end up in the range 0x1002????. 

Let's check out that address in volshell:

$ python vol.py -f silentbanker.vmem volshell
Volatile Systems Volatility Framework 2.3_alpha
(pid = Current context: process System, pid=4, ppid=0 DTB=0x319000
Welcome to volshell! 
To get help, type 'hh()'
>>> cc(pid = 1884)
Current context: process IEXPLORE.EXE, pid=1884, ppid=1724 DTB=0x6cc02a0
>>> db(0x10020000)
0x10020000  4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00   MZ..............
0x10020010  b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00   ........@.......
0x10020020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x10020030  00 00 00 00 00 00 00 00 00 00 00 00 d8 00 00 00   ................
0x10020040  0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68   ........!..L.!Th
0x10020050  69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f   is.program.canno
0x10020060  74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20   t.be.run.in.DOS.
0x10020070  6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00   mode....$.......

There's a PE header at the base address that we selected based on the API hooks output. We don't see mscorews.dll in the dlllist output or in the vadinfo mapped files, because after the DLL initially loads, it copies itself to a virtually allocated region (i.e. VirtualAlloc), then unloads. The entry in the PEB for the DLL is wiped out, as is the file mapping, but the code stays running. Typical code injection artifact that malfind will also detect appropriately: 

$ python vol.py -f silentbanker.vmem -p 1884 malfind
Volatile Systems Volatility Framework 2.3_alpha
[snip]
Process: IEXPLORE.EXE Pid: 1884 Address: 0x10020000
Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITE
Flags: CommitCharge: 22, MemCommit: 1, PrivateMemory: 1, Protection: 6

0x10020000  4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00   MZ..............
0x10020010  b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00   ........@.......
0x10020020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x10020030  00 00 00 00 00 00 00 00 00 00 00 00 d8 00 00 00   ................

Extracting the DLL

At the end of the day, you can now effortlessly extract the hidden DLL from Internet Explorer with the dlldump plugin:

$ mkdir sb
$ python vol.py -f silentbanker.vmem -p 1884 dlldump --base 0x10020000 -D sb/
Volatile Systems Volatility Framework 2.3_alpha
Process(V) Name                 Module Base Module Name          Result
---------- -------------------- ----------- -------------------- ------
0x80f1b020 IEXPLORE.EXE         0x010020000 UNKNOWN              OK: module.1884.107e020.10020000.dll

As a sanity check: 

$ strings sb/module.1884.107e020.10020000.dll
[snip
iexplore.exe
explorer.exe
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-Disposition: form-data; name="%s"; filename="C:\%s"
Content-Type: application/x-www-form-urlencoded
http://%s
%d%d.exe
/acct/logout.asp
dotscfg.xml
fosinfo.xml
/acct/confirm.asp
&BAction=Confirm
USD_PER_OUNCE
&USD_PER_OUNCE=
PAYER_ACCOUNT
&PAYER_ACCOUNT=
PAYMENT_METAL_ID
&PAYMENT_METAL_ID=
Currency_Symbol
&Currency_Symbol=
Memo
&Memo=
WORTH_OF
&WORTH_OF=
PAY_IN
Amount
Payee_Account
/acct/verify.asp
BAction=Preview
past=&
&WORTH_OF=Gold&Memo=&
9999
&PAY_IN=
&Amount=
Payee_Account=
" VALUE: "
" PASS: "
" LOG: "
POP3 User Name
HTTPMail Password2
HTTPMail User Name
Software\Microsoft\Internet Account Manager\Accounts

Conclusion

Your takeaways for this short how-to is that 1) just because the FILE_OBJECT handle count is zero does not mean a file isn't loaded in a process 2) sometimes a DLL will quickly create a copy of itself and then unload, leaving no trace in the PEB 3) you can use indirect methods to locate hidden DLLs, such as API hook trampoline addresses and injected code artifacts. 

Wednesday, December 12, 2012

Unpacking Dexter POS "Memory Dump Parsing" Malware

I'm a big fan of Dexter. As I recently mentioned during an impromptu discussion with our first group of memory analysis training attendees, if there are only a few minutes left in an episode and he hasn't killed anyone yet, I start getting nervous. So when I heard there's malware named dexter that has also been "parsing memory dumps" of specific processes on POS (Point of Sale) systems, I was excited to take a look. How exactly does this memory dump parsing occur? Is it scanning for .vmem files on an infected VM host? Maybe walking directories of network shares to find collections of past memory dumps taken by forensic teams? Perhaps acquiring a crash dump or mini-dump of the POS system itself? Turns out its none of the above, and the memory dump parsing is just a ReadProcessMemory loop, but figuring that out was nonetheless a textbook example of how to use Volatility in a reverse-engineering malware scenario.

Getting started in the typical way, you can see dexter is packed. There are PE sections named .conas, .ts10, .ts20, .ts30, .ts40, and .ts50; suspiciously named exports like RenameHerbal, RenameFortation, and LoadMemberData; only two imported APIs - GetKeyboardState and GetSystemWindowsDirectoryW; and roughly 10% of the file is recognized by IDA as executable code (the rest is compressed/packed data).


If you needed further proof, you could check the strings:

$ strings -a ~/Desktop/dexter.exe 
!This program cannot be run in DOS mode.
IRich,
.text
`.conas
.const
@.data
.ts050
@.ts040
@.ts030
@.ts020
@.ts010
iopiio
worG
uNqkObyOqdrSDunixUVSmOFucsNpJUJKkmpmqlUW
FvlLutksfHVJWIzigOJfTfFRxxUmwtdRKhmgjhdiXlSq
TZJ_QaVg_vGB
OWMu_wWH_EHz
SOU_GTUQ
PSOsqo_Jk
GetKeyboardState
USER32.dll
GetSystemWindowsDirectoryW
KERNEL32.dll
C:\Debugger.fgh
,vr1
rnyCsipvZnUURpjurWxiRqgauylOKfl3J
owz{
tjpudajfQwdBCBGAtjpcrTlenAyHMz
nuymGmpBownDvVIErgffsrBxQskLJu
zn|c
p}mOPSJqtFxbQlmrSPiThjdwfHxndtrP
ModuleReplace.exe
LoadMemberData

Nothing too interesting there. If we're going to understand how this malware parses memory dumps, we'll need to unpack it first. There's the manual option of finding OEP, dumping a sample with OllyDbg or LordPE, and fixing imports with ImpREC (or something similar), but I try to save that more time consuming and technical approach for when its really needed. In the case of dexter, and a majority of malware these days, all you need to do is run it and let it unpack itself. Being lazy never felt so good!

After copying the malware to a VM, it was executed and resulted in the creation of two new Internet Explorer processes. The code has to persist on the system in some way, so if the process (dexter.exe) doesn't stay running itself, you can bet it dissolves (i.e. injects) into another process. A reasonable first guess of the targets would be the two new IE instances: pids 1480 and 820. 


Now back in Volatility, working with the suspended VMs memory file, let's list processes just to orient ourselves with this new perspective: 

$ ./vol.py pslist
Volatile Systems Volatility Framework 2.3_alpha
Offset(V)  Name                PID   PPID   Thds     Hnds  Start                                
---------- ---------------- ------ ------ ------ --------  -------------------- 
0x81bcc830 System                4      0     59      190                                             
0x81b27020 smss.exe            380      4      3       21  2012-12-03 05:35:49                      
0x81a39660 csrss.exe           604    380     11      407  2012-12-03 05:35:51                      
0x818fbd78 winlogon.exe        640    380     18      506  2012-12-03 05:35:53                      
0x818e62a0 services.exe        684    640     15      287  2012-12-03 05:35:53                      
0x81889150 lsass.exe           696    640     20      353  2012-12-03 05:35:53                      
0x81afd458 vmacthlp.exe        848    684      1       24  2012-12-03 05:35:54                      
<snip>                    
0x81783020 ProcessHacker.e    2532    424      3       79  2012-12-12 01:49:12                      
0x81b27558 IEXPLORE.EXE       1480    968      7      115  2012-12-12 01:49:21                      
0x81710da0 IEXPLORE.EXE        820   1480      2       30  2012-12-12 01:49:21  

The next thing I did since code injection was suspected is run malfind on the two IE pids. It located two memory segments - one in each IE process, same base address in both (0x150000), same protection (PAGE_EXECUTE_READWRITE), and according to the hexdump there's an MZ header at the base of the region. 

$ ./vol.py malfind -p 1480,820
Volatile Systems Volatility Framework 2.3_alpha

Process: IEXPLORE.EXE Pid: 1480 Address: 0x150000
Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITE
Flags: CommitCharge: 11, MemCommit: 1, PrivateMemory: 1, Protection: 6

0x00150000  4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00   MZ..............
0x00150010  b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00   ........@.......
0x00150020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00150030  00 00 00 00 00 00 00 00 00 00 00 00 c0 00 00 00   ................

Process: IEXPLORE.EXE Pid: 820 Address: 0x150000
Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITE
Flags: CommitCharge: 11, MemCommit: 1, PrivateMemory: 1, Protection: 6

0x00150000  4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00   MZ..............
0x00150010  b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00   ........@.......
0x00150020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00150030  00 00 00 00 00 00 00 00 00 00 00 00 c0 00 00 00   ................

Now that we've quite effortlessly identified where the unpacked code is hiding, let's dump it out of memory. We'll use the dlldump plugin for this. Although the PE at 0x15000 isn't necessarily a DLL, the dlldump plugin allows the extracting/rebuilding of any PE in process memory if you supply the --base address (which we know). 

$ mkdir dexter 
$ ./vol.py dlldump -p 1480,820 --base=0x150000 -D dexter/
Volatile Systems Volatility Framework 2.3_alpha
Process(V) Name          Module Base Name    Result
---------- ------------- ----------- ------- ------
0x81b27558 IEXPLORE.EXE  0x000150000 UNKNOWN OK: module.1480.1b27558.150000.dll
0x81710da0 IEXPLORE.EXE  0x000150000 UNKNOWN OK: module.820.1710da0.150000.dll

For a quick understanding of how effective this approach can be in unpacking malware, take a look at the strings now:

$ strings -a dexter/module.1480.1b27558.150000.dll 
!This program cannot be run in DOS mode.
.text
.data
.rsrc
wuauclt.exe
alg.exe
spoolsv.exe
lsass.exe
winlogon.exe
csrss.exe
smss.exe
System
explorer.exe
iexplore.exe
svchost.exe
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
SeDebugPrivilege
NTDLL.DLL
NtQueryInformationProcess
/portal1/gateway.php
11e2540739d7fbea1ab8f9aa7a107648.com
7186343a80c6fa32811804d23765cda4.com
e7dce8e4671f8f03a040d08bb08ec07a.com
e7bc2d0fceee1bdfd691a80c783173b4.com
815ad1c058df1b7ba9c0998e2aa8a7b4.com
67b3dba8bc6778101892eb77249db32e.com
fabcaa97871555b68aa095335975e613.com
Windows 7
Windows Server R2
Windows Server 2008
Windows Vista
Windows Server 2003 R2
Windows Home Server
Windows Server 2003
Windows XP Professional x64
Windows XP
Windows 2000
32 Bit
64 Bit
http://%s%s
Content-Type:application/x-www-form-urlencoded
POST
Mozilla/4.0(compatible; MSIE 7.0b; Windows NT 6.0)
LowRiskFileTypes
Software\Microsoft\Windows\CurrentVersion\Policies\Associations
rpcrt4.dll
gdi32.dll
wininet.dll
urlmon.dll
shell32.dll
advapi32.dll
user32.dll
IsWow64Process
WindowsResilienceServiceMutex
Software\Resilience Software
Software\Microsoft\Windows\CurrentVersion\Run
.DEFAULT\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
UpdateMutex:
response=
page=
&ump=
&opt=
&unm=
&cnm=
&view=
&spec=
&query=
&val=
&var=
DetectShutdownClass
download-
update-
checkin:
scanin:
uninstall

The strings output shows a list of process names, which makes sense - the Seculert Blog mentioned that it enumerates processes. You also see it references SeDebugPrivilege, likely for the ability to call OpenProcess and read/write the memory of other processes. The ABCDEF[....] is a base64 alphabet, so you can expect it to encode some or all of the data it POSTs to gateway.php on one of the randomly named .com domains. It would create the WindowsResilienceServiceMutex and make a run key in the Software\Resilience Software registry key. 

To solve our real question - how does this malware parse memory dumps - we need to open the unpacked file in IDA. Its import table is already fixed up, so aside from switching the ImageBase value in the PE header so RVAs are interpreted correctly by IDA, we're done unpacking before we even really started. A quick look through the unpacked file's IAT shows it calls ReadProcessMemory, and cross-referencing that leads to one function, shown below:


What you see here is the "memory dump parsing" function. It iterates once for each active process on the system, calling OpenProcess() to obtain a handle, then using VirtualQueryEx() to determine which memory ranges are accessible to the process, and reading them into a local buffer with ReadProcessMemory(). The data is then passed off to two scanning sub-functions which do the real work of deciding which data to steal from the buffer. 

In summary, though I'm slightly disappointed that the memory dump parsing function is just a ReadProcessMemory() loop, at least I didn't waste much time getting there. Unpacking the malware by leveraging Volatility was as easy as 1-2-3. Lastly, since some of our students in the Windows Memory Forensics training requested videos of common ways we use Volatility, here's an initial example in quicktime format showing the steps described in this blog: http://www.mnin.org/dexter.mov.zip