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:
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.
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
$ 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.
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