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. 

No comments:

Post a Comment