相關知識:Windows Knowledge, PE Format, Windbg command, x86 knowledge
先定義一下問題:如何使用Windbg or KD,藉由Windows的運作法則以及PE的格式,找出一個Process載入的Kernel32.dll的位置。更進一步的推導出Kernel32.dll所export的function。
就拿記事本為例子吧!打開Windbg,"File->Attach To Process",挑選notepad.exe。
接著看存放在fs:[30]的PEB data。
1: 0:001> dd fs:[30] L1
2: 0038:00000030 7ffde000
3: 0:001> dt _PEB 7ffde000
4: ntdll!_PEB
5: +0x000 InheritedAddressSpace : 0 ''
6: +0x001 ReadImageFileExecOptions : 0 ''
7: +0x002 BeingDebugged : 0x1 ''
8: +0x003 SpareBool : 0 ''
9: +0x004 Mutant : 0xffffffff
10: +0x008 ImageBaseAddress : 0x01000000
11: +0x00c Ldr : 0x001a1e90 _PEB_LDR_DATA
12: +0x010 ProcessParameters : 0x00020000 _RTL_USER_PROCESS_PARAMETERS
13: ......(略)
PEB的資訊很多,這裡就只列出部分內容。為什麼要找到PEB呢?因為PEB裡面的Ldr欄位存放了一個list,這個list記載了該Process所載入的module資訊,藉此我們就可以找到Kernel32.dll
1: 0:001> dt _PEB_LDR_DATA 0x001a1e90
2: ntdll!_PEB_LDR_DATA
3: +0x000 Length : 0x28
4: +0x004 Initialized : 0x1 ''
5: +0x008 SsHandle : (null)
6: +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x1a1ec0 - 0x1a3030 ]
7: +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x1a1ec8 - 0x1a3038 ]
8: +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x1a1f28 - 0x1a3040 ]
9: +0x024 EntryInProgress : (null)
InLoadOrderModuleList就是上面提到的List,我們來依著LIST_ENTRY裡的第一個欄位FLink尋訪一下這個list:
1: 0:001> dt ntdll!_LDR_DATA_TABLE_ENTRY 0x1a1ec0
2: +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x1a1f18 - 0x1a1e9c ]
3: +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x1a1f20 - 0x1a1ea4 ]
4: +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
5: +0x018 DllBase : 0x01000000
6: +0x01c EntryPoint : 0x0100739d
7: +0x020 SizeOfImage : 0x14000
8: +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\notepad.exe"
9: +0x02c BaseDllName : _UNICODE_STRING "notepad.exe"
10: +0x034 Flags : 0x5000
11: +0x038 LoadCount : 0xffff
12: +0x03a TlsIndex : 0
13: +0x03c HashLinks : _LIST_ENTRY [ 0x1a1f54 - 0x7c97b2c8 ]
14: +0x03c SectionPointer : 0x001a1f54
15: +0x040 CheckSum : 0x7c97b2c8
16: +0x044 TimeDateStamp : 0x48025287
17: +0x044 LoadedImports : 0x48025287
18: +0x048 EntryPointActivationContext : (null)
19: +0x04c PatchInformation : (null)
List的開頭存放的是notepad.exe本身,我們繼續往下找:
1: 0:001> dt ntdll!_LDR_DATA_TABLE_ENTRY 0x1a1f18
2: +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x1a1fc0 - 0x1a1ec0 ]
3: +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x1a1fc8 - 0x1a1ec8 ]
4: +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x1a1fd0 - 0x1a1eac ]
5: +0x018 DllBase : 0x7c900000
6: +0x01c EntryPoint : 0x7c912c28
7: +0x020 SizeOfImage : 0xaf000
8: +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\ntdll.dll"
9: +0x02c BaseDllName : _UNICODE_STRING "ntdll.dll"
10: +0x034 Flags : 0x80084004
11: +0x038 LoadCount : 0xffff
12: +0x03a TlsIndex : 0
13: +0x03c HashLinks : _LIST_ENTRY [ 0x7c97b2c8 - 0x1a1efc ]
14: +0x03c SectionPointer : 0x7c97b2c8
15: +0x040 CheckSum : 0x1a1efc
16: +0x044 TimeDateStamp : 0x4802a12c
17: +0x044 LoadedImports : 0x4802a12c
18: +0x048 EntryPointActivationContext : (null)
19: +0x04c PatchInformation : (null)
20: 0:001> dt ntdll!_LDR_DATA_TABLE_ENTRY 0x1a1fc0
21: +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x1a2068 - 0x1a1f18 ]
22: +0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x1a2070 - 0x1a1f20 ]
23: +0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x1a2260 - 0x1a1f28 ]
24: +0x018 DllBase : 0x7c800000
25: +0x01c EntryPoint : 0x7c80b63e
26: +0x020 SizeOfImage : 0xf6000
27: +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\kernel32.dll"
28: +0x02c BaseDllName : _UNICODE_STRING "kernel32.dll"
29: +0x034 Flags : 0x80084004
30: +0x038 LoadCount : 0xffff
31: +0x03a TlsIndex : 0
32: +0x03c HashLinks : _LIST_ENTRY [ 0x7c97b2b0 - 0x7c97b2b0 ]
33: +0x03c SectionPointer : 0x7c97b2b0
34: +0x040 CheckSum : 0x7c97b2b0
35: +0x044 TimeDateStamp : 0x4802a12c
36: +0x044 LoadedImports : 0x4802a12c
37: +0x048 EntryPointActivationContext : (null)
38: +0x04c PatchInformation : (null)
賓果!,kernel32.dll的base address是0x7c800000。可不可以請Windbg幫我們自動地解析出list上面module的資訊?可以的,請使用!list這個指令,其格式是:
!list -t FLink的欄位 -x "要執行的指令" -a "給指令的參數" -e 起始Flink的位置
下面這個例子是自動去秀出每個module的FullDllName:
1: 0:001> !list -t ntdll!_LDR_DATA_TABLE_ENTRY.InLoadOrderLinks.Flink -x "dt" -a "+0x24 _UNICODE_STRING" -e 0x1a1ec0
2: dt 0x1a1ec0 +0x24 _UNICODE_STRING
3: ntdll!_UNICODE_STRING
4: "C:\WINDOWS\system32\notepad.exe"
5: +0x000 Length : 0x3e
6: +0x002 MaximumLength : 0x40
7: +0x004 Buffer : 0x00020728 "C:\WINDOWS\system32\notepad.exe"
8:
9: dt 0x1a1f18 +0x24 _UNICODE_STRING
10: ntdll!_UNICODE_STRING
11: "C:\WINDOWS\system32\ntdll.dll"
12: +0x000 Length : 0x3a
13: +0x002 MaximumLength : 0x208
14: +0x004 Buffer : 0x7c97d028 "C:\WINDOWS\system32\ntdll.dll"
15:
16: dt 0x1a1fc0 +0x24 _UNICODE_STRING
17: ntdll!_UNICODE_STRING
18: "C:\WINDOWS\system32\kernel32.dll"
19: +0x000 Length : 0x40
20: +0x002 MaximumLength : 0x42
21: +0x004 Buffer : 0x001a1f70 "C:\WINDOWS\system32\kernel32.dll"
22:
23: dt 0x1a2068 +0x24 _UNICODE_STRING
24: ntdll!_UNICODE_STRING
25: "C:\WINDOWS\system32\comdlg32.dll"
26: +0x000 Length : 0x40
27: +0x002 MaximumLength : 0x42
28: +0x004 Buffer : 0x001a2018 "C:\WINDOWS\system32\comdlg32.dll"
29:
30: dt 0x1a2110 +0x24 _UNICODE_STRING
31: ntdll!_UNICODE_STRING
32: "C:\WINDOWS\system32\ADVAPI32.dll"
33: +0x000 Length : 0x40
34: +0x002 MaximumLength : 0x42
35: +0x004 Buffer : 0x001a20c0 "C:\WINDOWS\system32\ADVAPI32.dll"
36: ......(略)
上面囉嗦了一串,其實我們大可以使用!peb這個指令,可以輕易的得出kernel32.dll的起始位置,但是辛苦的果實比較甜美,不是嗎
1: 0:001> !peb
2: PEB at 7ffde000
3: InheritedAddressSpace: No
4: ReadImageFileExecOptions: No
5: BeingDebugged: Yes
6: ImageBaseAddress: 01000000
7: Ldr 001a1e90
8: Ldr.Initialized: Yes
9: Ldr.InInitializationOrderModuleList: 001a1f28 . 001a3040
10: Ldr.InLoadOrderModuleList: 001a1ec0 . 001a3030
11: Ldr.InMemoryOrderModuleList: 001a1ec8 . 001a3038
12: Base TimeStamp Module
13: 1000000 48025287 Apr 14 02:35:51 2008 C:\WINDOWS\system32\notepad.exe
14: 7c900000 4802a12c Apr 14 08:11:24 2008 C:\WINDOWS\system32\ntdll.dll
15: 7c800000 4802a12c Apr 14 08:11:24 2008 C:\WINDOWS\system32\kernel32.dll
16: 763b0000 4802a0c9 Apr 14 08:09:45 2008 C:\WINDOWS\system32\comdlg32.dll
17: ......(略)
找到起始位置之後,就要來計算kernel32.dll有那些可以使用的function摟。上次我們介紹了幫助解析PE檔頭的!dh,這次改用比較苦工的方式,先以+0x3C、+0x78這兩個offset找到Export table的RVA(或者也可以用!dh得知),然後再以+0x20的offset得到function name table 的RVA :
1: 0:001> dd 7c800000+0x3c L1
2: 7c80003c 000000f0
3: 0:001> dd 7c800000+000000f0+0x78 L1
4: 7c800168 0000262c
5: 0:001> dd 7c800000+0000262c+0x20 L1
6: 7c80264c 00003538
7: 0:001> dd 7c800000+00003538
8: 7c803538 00004b9b 00004baa 00004bb3 00004bbc
9: 7c803548 00004bcd 00004bde 00004bfd 00004c1c
10: 7c803558 00004c29 00004c45 00004c52 00004c6c
11: 7c803568 00004c7c 00004c95 00004ca3 00004cae
12: 7c803578 00004cb9 00004cc5 00004cdd 00004cf7
13: 7c803588 00004d18 00004d2f 00004d47 00004d5e
14: 7c803598 00004d7c 00004d96 00004daa 00004dc3
15: 7c8035a8 00004de2 00004de7 00004dfc 00004e11
16: 0:001> da 7c800000+00004b9b
17: 7c804b9b "ActivateActCtx"
18: 0:001> da 7c800000+00004baa
19: 7c804baa "AddAtomA"
20: 0:001> da 7c800000+00004bb3
21: 7c804bb3 "AddAtomW"
22: 0:001> da 7c800000+00004bbc
23: 7c804bbc "AddConsoleAliasA"
至於function的address呢?可以用類似的方式得知,相關offset請參考PE 格式。本篇內容可以由程式來實作,是一個相當經典的技巧,網路上可以找到一海票範例。ShellCode尤其喜愛使用
(待續)
No comments:
Post a Comment