為了尋找kernel32.dll的地址,可以直接輸出,也可以通過TEB,PEB等查找。
?
尋找TEB:
dt _TEB
nt!_TEB
+0x000 NtTib : _NT_TIB
+0x01c EnvironmentPointer : Ptr32 Void
+0x020 ClientId : _CLIENT_ID
+0x028 ActiveRpcHandle : Ptr32 Void
+0x02c ThreadLocalStoragePointer : Ptr32 Void
+0x030 ProcessEnvironmentBlock : Ptr32 _PEB
+0x034 LastErrorValue : Uint4B
0x30處就是PEB
?
dt _PEB
nt!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
+0x002 BeingDebugged : UChar
+0x003 BitField : UChar
+0x003 ImageUsesLargePages : Pos 0, 1 Bit
+0x003 IsProtectedProcess : Pos 1, 1 Bit
+0x003 IsLegacyProcess : Pos 2, 1 Bit
+0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit
+0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit
+0x003 SpareBits : Pos 5, 3 Bits
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA
+0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
0x0C處是 LDR
?
dt _PEB_LDR_DATA
nt!_PEB_LDR_DATA
+0x000 Length : Uint4B
+0x004 Initialized : UChar
+0x008 SsHandle : Ptr32 Void
+0x00c InLoadOrderModuleList : _LIST_ENTRY
+0x014 InMemoryOrderModuleList : _LIST_ENTRY
+0x01c InInitializationOrderModuleList : _LIST_ENTRY
+0x024 EntryInProgress : Ptr32 Void
+0x028 ShutdownInProgress : UChar
+0x02c ShutdownThreadId : Ptr32 Void
InMemoryOrderModuleList 是嵌套在一個更大的結構體 _LDR_DATA_TABLE_ENTRY 里面
dt _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x008 InMemoryOrderLinks : _LIST_ENTRY ? ? ? //就是InMemoryOrderModuleList
+0x010 InInitializationOrderLinks : _LIST_ENTRY
+0x018 DllBase : Ptr32 Void
第二參數就是我們要找的而_LIST_ENTRY表示結構體中的單個元素,InMemoryOrderLinks位于結構體首地址偏移8字節處
其Flink和Blink并不指向臨近結構的第一個字節,相反它們引用了臨近結構的地址。每個結構的地址
正好是第一個成員的地址Flink。
所以為了得到相鄰結構的地址,需要從Flink中減去8字節的偏移。
下面是兩種得到kernel32.dll地址的方法
VOID Sub_1(); int main() {Sub_1();HMODULE v1 = NULL; v1 = LoadLibrary(L"kernel32.dll"); //加載DLL printf("0x%08p\r\n", v1);return 0; }VOID Sub_1() { int address = 0; __asm { xor ebx, ebx; mov ebx, fs:[0x30]; mov ebx, [ebx + 0x0c]; mov ebx, [ebx + 0x14]; mov ebx, [ebx]; mov ebx, [ebx]; mov ebx, [ebx + 0x10]; mov address, ebx; } printf("0x%08p\r\n", address); }
?
我的測試結果是 0x76C00000
在用戶模式下,TEB的創建方式總是相同的,與該地址對應的段選擇器自動放置在FS段寄存器中,TEB的偏移地址總是0.
TEB的地址可以被表示為 FS:00000000H.
?