抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

TEB

TEB(Thread Environment Block), 线程环境变量块, TEB中包含了线程的堆栈指针、TLS(线程本地存储)指针、异常处理链表指针、用户模式分页表指针等信息。TEB中fs寄存器通常被设置为fs:[0](32位), 指向当前线程的的TEB结构体。其他线程可以通过访问自己的TEB结构体来获取自己的状态和信息。

PEB

PEB(Process Environment Block), 进程环境变量块, PEB中包含了进程的代码、数据段指针、进程的环境变量、进程启动参数信息以及加载的dll信息等。PEB结构体中的fs段寄存器通常被设置为0x30(32位), 指向当前进程的PEB结构体。

TEB的查找方式

32 bit 64 bit
fs gs

32位TEB/PEB查找

TEB

1
2
3
4
5
6
7
8
9
0:000> dt _TEB
ntdll!_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 // <== 指向PEB
...

PEB

包含进程信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
0:000> dt _PEB
ntdll!_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 IsImageDynamicallyRelocated : Pos 2, 1 Bit
+0x003 SkipPatchingUser32Forwarders : Pos 3, 1 Bit
+0x003 IsPackagedProcess : Pos 4, 1 Bit
+0x003 IsAppContainer : Pos 5, 1 Bit
+0x003 IsProtectedProcessLight : Pos 6, 1 Bit
+0x003 IsLongPathAwareProcess : Pos 7, 1 Bit
+0x004 Mutant : Ptr32 Void
+0x008 ImageBaseAddress : Ptr32 Void
+0x00c Ldr : Ptr32 _PEB_LDR_DATA // <=== 指向PEB_LDR_DATA
...

PEB_LDR_DATA

包含有关为进程加载的模块的信息

PEB_LDR_DATA结构定义

1
2
3
4
5
typedef struct _PEB_LDR_DATA {
BYTE Reserved1[8]; // 保留供操作系统内部使用
PVOID Reserved2[3]; // 保留供操作系统内部使用
LIST_ENTRY InMemoryOrderModuleList; // 包含进程的已加载模块的双向链表, 链表中的每个项都是指向LDR_DATA_TABLE_ENTRY结构的指针
} PEB_LDR_DATA, *PPEB_LDR_DATA;

LIST_ENTRY 结构体定义

1
2
3
4
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

_LIST_ENTRY: 这个双向链表指向进程装载的模块, 结构中每个指针, 指向了一个LDR_DATA_TABLE_ENTRY的结构;

LDR_DATA_TABLE_ENTRY 结构定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
WORD LoadCount;
WORD TlsIndex;
union
{
LIST_ENTRY HashLinks;
struct
{
PVOID SectionPointer;
ULONG CheckSum;
};
};
union
{
ULONG TimeDateStamp;
PVOID LoadedImports;
};
_ACTIVATION_CONTEXT * EntryPointActivationContext;
PVOID PatchInformation;
LIST_ENTRY ForwarderLinks;
LIST_ENTRY ServiceTagLinks;
LIST_ENTRY StaticLinks;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

查询PEB_LDR_DATA

在遍历InMemoryOrderModuleList时, 地址需要-0x08

1
2
3
4
5
6
7
8
9
10
11
0:000> dt _PEB_LDR_DATA
ntdll!_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

查询LDR_DATA_TABLE_ENTRY

InLoadOrderLinks 为示例

获取主模块(程序自身)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
0:000> dt -r1 0x014b41d8 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x14b40c0 - 0x77eceb2c ]
+0x000 Flink : 0x014b40c0 _LIST_ENTRY [ 0x14b45d0 - 0x14b41d8 ]
+0x004 Blink : 0x77eceb2c _LIST_ENTRY [ 0x14b41d8 - 0x14b4810 ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x14b40c8 - 0x77eceb34 ]
+0x000 Flink : 0x014b40c8 _LIST_ENTRY [ 0x14b45d8 - 0x14b41e0 ]
+0x004 Blink : 0x77eceb34 _LIST_ENTRY [ 0x14b41e0 - 0x14b4818 ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x000 Flink : (null)
+0x004 Blink : (null)
+0x018 DllBase : 0x00d80000 Void // Dll基址
+0x01c EntryPoint : 0x00dce118 Void
+0x020 SizeOfImage : 0x126000
+0x024 FullDllName : _UNICODE_STRING "D:\\xxx\\EnumModule.exe" // 第一个模块为程序自身
+0x000 Length : 0xb2
+0x002 MaximumLength : 0xb4
+0x004 Buffer : 0x014b27dc "D:\\xxx\\EnumModule.exe"
+0x02c BaseDllName : _UNICODE_STRING "EnumModule.exe"
+0x000 Length : 0x1c
+0x002 MaximumLength : 0x1e
+0x004 Buffer : 0x014b2872 "EnumModule.exe"
+0x034 FlagGroup : [4] "???"

略...
获取NtDll
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
0:000> dt -r1 0x14b40c0 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x14b45d0 - 0x14b41d8 ]
+0x000 Flink : 0x014b45d0 _LIST_ENTRY [ 0x14b49c0 - 0x14b40c0 ]
+0x004 Blink : 0x014b41d8 _LIST_ENTRY [ 0x14b40c0 - 0x77eceb2c ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x14b45d8 - 0x14b41e0 ]
+0x000 Flink : 0x014b45d8 _LIST_ENTRY [ 0x14b49c8 - 0x14b40c8 ]
+0x004 Blink : 0x014b41e0 _LIST_ENTRY [ 0x14b40c8 - 0x77eceb34 ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x14b49d0 - 0x77eceb3c ]
+0x000 Flink : 0x014b49d0 _LIST_ENTRY [ 0x14b45e0 - 0x14b40d0 ]
+0x004 Blink : 0x77eceb3c _LIST_ENTRY [ 0x14b40d0 - 0x14b4820 ]
+0x018 DllBase : 0x77da0000 Void // <=== 指向ntdll.dll的基址
+0x01c EntryPoint : (null)
+0x020 SizeOfImage : 0x1b2000
+0x024 FullDllName : _UNICODE_STRING "C:\\WINDOWS\\SYSTEM32\\ntdll.dll"
+0x000 Length : 0x3a
+0x002 MaximumLength : 0x3c
+0x004 Buffer : 0x014b3fa0 "C:\\WINDOWS\\SYSTEM32\\ntdll.dll"
+0x02c BaseDllName : _UNICODE_STRING "ntdll.dll"
+0x000 Length : 0x12
+0x002 MaximumLength : 0x14
+0x004 Buffer : 0x77dab4f8 "ntdll.dll"
+0x034 FlagGroup : [4] "???"

略...
获取Kernel32
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
0:000> dt -r1 0x014b45d0 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x14b49c0 - 0x14b40c0 ]
+0x000 Flink : 0x014b49c0 _LIST_ENTRY [ 0x14b4810 - 0x14b45d0 ]
+0x004 Blink : 0x014b40c0 _LIST_ENTRY [ 0x14b45d0 - 0x14b41d8 ]
+0x008 InMemoryOrderLinks : _LIST_ENTRY [ 0x14b49c8 - 0x14b40c8 ]
+0x000 Flink : 0x014b49c8 _LIST_ENTRY [ 0x14b4818 - 0x14b45d8 ]
+0x004 Blink : 0x014b40c8 _LIST_ENTRY [ 0x14b45d8 - 0x14b41e0 ]
+0x010 InInitializationOrderLinks : _LIST_ENTRY [ 0x14b4820 - 0x14b49d0 ]
+0x000 Flink : 0x014b4820 _LIST_ENTRY [ 0x77eceb3c - 0x14b45e0 ]
+0x004 Blink : 0x014b49d0 _LIST_ENTRY [ 0x14b45e0 - 0x14b40d0 ]
+0x018 DllBase : 0x76310000 Void // <=== 指向KERNEL32.DLL的基址
+0x01c EntryPoint : 0x763277c0 Void
+0x020 SizeOfImage : 0xf0000
+0x024 FullDllName : _UNICODE_STRING "C:\\WINDOWS\\System32\\KERNEL32.DLL"
+0x000 Length : 0x40
+0x002 MaximumLength : 0x42
+0x004 Buffer : 0x014b46e8 "C:\\WINDOWS\\System32\\KERNEL32.DLL"
+0x02c BaseDllName : _UNICODE_STRING "KERNEL32.DLL"
+0x000 Length : 0x18
+0x002 MaximumLength : 0x1a
+0x004 Buffer : 0x014b4710 "KERNEL32.DLL"
+0x034 FlagGroup : [4] "???"

略...

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Get_LDR_Data_Table.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Windows.h>

// InLoadOrderModuleList
VOID GetInLoadOrderModuleList(DWORD* PEB)
{
PDWORD Ldr = NULL;
DWORD* InLoad = NULL;
DWORD* Kernel32 = NULL;
DWORD* p = NULL;
DWORD* BaseAddress = NULL;
DWORD* BaseDllName = NULL;
DWORD* FullDllName = NULL;
Ldr = *(PDWORD*)((unsigned char*)PEB + 0x0c);
// printf("得到LDR指针:%x\r\n", Ldr);
InLoad = *(DWORD**)((unsigned char*)Ldr + 0x0c);
// printf("得到InLoadOrderModuleList结构指针:%x\r\n", InLoad);
// Kernel32 = *(DWORD**)((unsigned char*)InLoad + 0x18);
// printf("得到Kernel32基址:%x\r\n", Kernel32);
p = InLoad;
p = *((DWORD**)p);
while (InLoad != p)
{
BaseAddress = *((DWORD**)((unsigned char*)p + 0x18)); // DllBase
BaseDllName = *((DWORD**)((unsigned char*)p + 0x30)); // BaseDllName
FullDllName = *((DWORD**)((unsigned char*)p + 0x28)); // FullDllName
if (BaseAddress ==0)
{
break;
}
printf("镜像基址:0x%-20x 模块名称:%S\r\n ---> 模块路径:%S\n", BaseAddress, (unsigned char*)BaseDllName, (unsigned char*)FullDllName);
p = *((DWORD**)p);
}
}

// InMemoryOrderModuleList
VOID GetInMemoryOrderModuleList(DWORD* PEB)
{
DWORD* Ldr = NULL;
DWORD* InMemory = NULL;
DWORD* Kernel32 = NULL;
DWORD* p = NULL;
DWORD* BaseAddress = NULL;
DWORD* BaseDllName = NULL;
DWORD* FullDllName = NULL;
Ldr = *(DWORD**)((unsigned char*)PEB + 0x0c);
//printf("得到LDR结构指针:%x\r\n", Ldr);
InMemory = *(DWORD**)((unsigned char*)Ldr + 0x14);
//printf("得到InMemoryOrderModuleList结构指针:%x\r\n", InMemory);
//Kernel32 = *(DWORD**)((unsigned char*)InMemory + 0x10);
// printf("得到Kernel32基址:%x\r\n", Kernel32);
p = InMemory;
p = *((DWORD**)p);
while (InMemory != p)
{
BaseAddress = *((DWORD**)((unsigned char*)p + 0x10));
BaseDllName = *((DWORD**)((unsigned char*)p + 0x28));
FullDllName = *((DWORD**)((unsigned char*)p + 0x20));
if (BaseAddress == 0)
{
break;
}
printf("镜像基址:0x%-20x 模块名称:%S\r\n ---> 模块路径:%S\n", BaseAddress, (const char*)BaseDllName, (const char*)FullDllName);
p = *((DWORD**)p);
}
}

int main()
{
DWORD* PEB = NULL;
__asm
{
mov eax, fs:[0x30]
mov PEB, eax
}
printf("得到PEB指针:0x%08x\r\n", PEB);
printf("--------------------------------------------------------------------\r\n");
GetInLoadOrderModuleList(PEB);
printf("--------------------------------------------------------------------\r\n");
GetInMemoryOrderModuleList(PEB);
printf("--------------------------------------------------------------------\r\n");

_TEB* pTeb = NtCurrentTeb();
PDWORD pPeb = (PDWORD) * (PDWORD)((DWORD)pTeb + 0x30);
PDWORD pLdr = (PDWORD) * (PDWORD)((DWORD)pPeb + 0x0c);
PDWORD pInLoadOrderLinks = (PDWORD) * (PDWORD)((DWORD)pLdr + 0x0c);
PDWORD pModExe = (PDWORD)*pInLoadOrderLinks;
PDWORD pModNtDll = (PDWORD)*pModExe;
PDWORD pModKernel32 = (PDWORD)*pModNtDll;
printf("镜像基址:0x%-20x 模块名称:%S\r\n ---> 模块路径:%S\n", pModKernel32[6], (const char*)pModKernel32[12], (const char*)pModKernel32[10]);
}

64位TEB/PEB查找

windbg查找

在遍历InMemoryOrderModuleList链表时, 地址需-0x10;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
0:000> !peb
PEB at 000000d737450000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: Yes
ImageBaseAddress: 00007ff723010000
NtGlobalFlag: 70
NtGlobalFlag2: 0
Ldr 00007ffc29996440
Ldr.Initialized: Yes
Ldr.InInitializationOrderModuleList: 00000275005e4450 . 00000275005e4d20
Ldr.InLoadOrderModuleList: 00000275005e4620 . 00000275005edae0
Ldr.InMemoryOrderModuleList: 00000275005e4630 . 00000275005edaf0
Base TimeStamp Module
7ff723010000 666289ca Jun 07 12:17:14 2024 D:\Tencent\WeChat\WeChat.exe
7ffc29810000 67ca8829 Mar 07 13:46:17 2025 C:\WINDOWS\SYSTEM32\ntdll.dll
7ffc286f0000 36466623 Nov 09 11:48:51 1998 C:\WINDOWS\System32\KERNEL32.DLL
7ffc270e0000 44653e19 May 13 10:02:01 2006 C:\WINDOWS\System32\KERNELBASE.dll
7ffc27630000 3b26444f Jun 13 00:33:19 2001 C:\WINDOWS\System32\USER32.dll
7ffc26e70000 331718eb Mar 01 01:42:03 1997 C:\WINDOWS\System32\win32u.dll
7ffc286c0000 533dc7aa Apr 04 04:42:18 2014 C:\WINDOWS\System32\GDI32.dll
7ffc26f20000 05ca1d5d Jan 29 13:04:29 1973 C:\WINDOWS\System32\gdi32full.dll
7ffc27040000 8e0806c9 Jul 06 02:04:57 2045 C:\WINDOWS\System32\msvcp_win.dll
7ffc26b40000 10c46e71 Dec 01 05:19:45 1978 C:\WINDOWS\System32\ucrtbase.dll
7ffc29410000 dac79f47 Apr 25 03:38:47 2086 C:\WINDOWS\System32\ADVAPI32.dll
7ffc28be0000 657b2709 Dec 15 00:02:17 2023 C:\WINDOWS\System32\msvcrt.dll
7ffc28580000 47af1f27 Feb 10 23:58:31 2008 C:\WINDOWS\System32\sechost.dll
7ffc26c60000 5a31de46 Dec 14 10:13:26 2017 C:\WINDOWS\System32\bcrypt.dll
7ffc29130000 1caf5f33 Apr 02 10:00:19 1985 C:\WINDOWS\System32\RPCRT4.dll
7ffc27a10000 8ec472d1 Nov 26 00:12:01 2045 C:\WINDOWS\System32\SHELL32.dll
7ffc283c0000 99614267 Jul 18 18:13:59 2051 C:\WINDOWS\System32\ole32.dll
7ffc287d0000 eadd58d3 Nov 12 12:32:19 2094 C:\WINDOWS\System32\combase.dll
7ffc294d0000 672b2c78 Nov 06 16:44:40 2024 C:\WINDOWS\System32\SHLWAPI.dll
7ffc06d90000 1aaf409d Mar 09 23:09:17 1984 C:\WINDOWS\WinSxS\amd64_microsoft.windows.gdiplus_6595b64144ccf1df_1.1.22621.3672_none_57feacb6ce14a323\gdiplus.dll

略...

0:000> dt -r1 0x00000275005e4630-0x10 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x00000275`005e4430 - 0x00007ffc`29996450 ]
+0x000 Flink : 0x00000275`005e4430 _LIST_ENTRY [ 0x00000275`005e4d00 - 0x00000275`005e4620 ]
+0x008 Blink : 0x00007ffc`29996450 _LIST_ENTRY [ 0x00000275`005e4620 - 0x00000275`005edae0 ]
+0x010 InMemoryOrderLinks : _LIST_ENTRY [ 0x00000275`005e4440 - 0x00007ffc`29996460 ]
+0x000 Flink : 0x00000275`005e4440 _LIST_ENTRY [ 0x00000275`005e4d10 - 0x00000275`005e4630 ]
+0x008 Blink : 0x00007ffc`29996460 _LIST_ENTRY [ 0x00000275`005e4630 - 0x00000275`005edaf0 ]
+0x020 InInitializationOrderLinks : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ]
+0x000 Flink : (null)
+0x008 Blink : (null)
+0x030 DllBase : 0x00007ff7`23010000 Void // <=== 指向程序本身
+0x038 EntryPoint : 0x00007ff7`2301c148 Void
+0x040 SizeOfImage : 0xa5000
+0x048 FullDllName : _UNICODE_STRING "D:\\Tencent\\WeChat\\WeChat.exe"
+0x000 Length : 0x38
+0x002 MaximumLength : 0x3a
+0x008 Buffer : 0x00000275`005e41c0 "D:\\Tencent\\WeChat\\WeChat.exe"
+0x058 BaseDllName : _UNICODE_STRING "WeChat.exe"
+0x000 Length : 0x14
+0x002 MaximumLength : 0x16
+0x008 Buffer : 0x00000275`005e41e4 "WeChat.exe"
+0x068 FlagGroup : [4] "???"

略...

0:000> dt -r1 0x00000275`005e4440-0x10 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x00000275`005e4d00 - 0x00000275`005e4620 ]
+0x000 Flink : 0x00000275`005e4d00 _LIST_ENTRY [ 0x00000275`005e5440 - 0x00000275`005e4430 ]
+0x008 Blink : 0x00000275`005e4620 _LIST_ENTRY [ 0x00000275`005e4430 - 0x00007ffc`29996450 ]
+0x010 InMemoryOrderLinks : _LIST_ENTRY [ 0x00000275`005e4d10 - 0x00000275`005e4630 ]
+0x000 Flink : 0x00000275`005e4d10 _LIST_ENTRY [ 0x00000275`005e5450 - 0x00000275`005e4440 ]
+0x008 Blink : 0x00000275`005e4630 _LIST_ENTRY [ 0x00000275`005e4440 - 0x00007ffc`29996460 ]
+0x020 InInitializationOrderLinks : _LIST_ENTRY [ 0x00000275`005e5460 - 0x00007ffc`29996470 ]
+0x000 Flink : 0x00000275`005e5460 _LIST_ENTRY [ 0x00000275`005e4d20 - 0x00000275`005e4450 ]
+0x008 Blink : 0x00007ffc`29996470 _LIST_ENTRY [ 0x00000275`005e4450 - 0x00000275`005e4d20 ]
+0x030 DllBase : 0x00007ffc`29810000 Void // <=== 指向ntdll.dll基址
+0x038 EntryPoint : (null)
+0x040 SizeOfImage : 0x217000
+0x048 FullDllName : _UNICODE_STRING "C:\\WINDOWS\\SYSTEM32\\ntdll.dll"
+0x000 Length : 0x3a
+0x002 MaximumLength : 0x3c
+0x008 Buffer : 0x00000275`005e42c0 "C:\\WINDOWS\\SYSTEM32\\ntdll.dll"
+0x058 BaseDllName : _UNICODE_STRING "ntdll.dll"
+0x000 Length : 0x12
+0x002 MaximumLength : 0x14
+0x008 Buffer : 0x00007ffc`2994e5d0 "ntdll.dll"
+0x068 FlagGroup : [4] "???"

略...

0:000> dt -r1 0x00000275`005e4d10-0x10 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x00000275`005e5440 - 0x00000275`005e4430 ]
+0x000 Flink : 0x00000275`005e5440 _LIST_ENTRY [ 0x00000275`005e5080 - 0x00000275`005e4d00 ]
+0x008 Blink : 0x00000275`005e4430 _LIST_ENTRY [ 0x00000275`005e4d00 - 0x00000275`005e4620 ]
+0x010 InMemoryOrderLinks : _LIST_ENTRY [ 0x00000275`005e5450 - 0x00000275`005e4440 ]
+0x000 Flink : 0x00000275`005e5450 _LIST_ENTRY [ 0x00000275`005e5090 - 0x00000275`005e4d10 ]
+0x008 Blink : 0x00000275`005e4440 _LIST_ENTRY [ 0x00000275`005e4d10 - 0x00000275`005e4630 ]
+0x020 InInitializationOrderLinks : _LIST_ENTRY [ 0x00007ffc`29996470 - 0x00000275`005e5460 ]
+0x000 Flink : 0x00007ffc`29996470 _LIST_ENTRY [ 0x00000275`005e4450 - 0x00000275`005e4d20 ]
+0x008 Blink : 0x00000275`005e5460 _LIST_ENTRY [ 0x00000275`005e4d20 - 0x00000275`005e4450 ]
+0x030 DllBase : 0x00007ffc`286f0000 Void // <=== 指向KERNEL32.dll基址
+0x038 EntryPoint : 0x00007ffc`287025e0 Void
+0x040 SizeOfImage : 0xc4000
+0x048 FullDllName : _UNICODE_STRING "C:\\WINDOWS\\System32\\KERNEL32.DLL"
+0x000 Length : 0x40
+0x002 MaximumLength : 0x42
+0x008 Buffer : 0x00000275`005e4ef0 "C:\\WINDOWS\\System32\\KERNEL32.DLL"
+0x058 BaseDllName : _UNICODE_STRING "KERNEL32.DLL"
+0x000 Length : 0x18
+0x002 MaximumLength : 0x1a
+0x008 Buffer : 0x00000275`005e4f18 "KERNEL32.DLL"
+0x068 FlagGroup : [4] "???"

略...

0:000> dt -r1 0x00000275`005e5450-0x10 _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x00000275`005e5080 - 0x00000275`005e4d00 ]
+0x000 Flink : 0x00000275`005e5080 _LIST_ENTRY [ 0x00000275`005e8270 - 0x00000275`005e5440 ]
+0x008 Blink : 0x00000275`005e4d00 _LIST_ENTRY [ 0x00000275`005e5440 - 0x00000275`005e4430 ]
+0x010 InMemoryOrderLinks : _LIST_ENTRY [ 0x00000275`005e5090 - 0x00000275`005e4d10 ]
+0x000 Flink : 0x00000275`005e5090 _LIST_ENTRY [ 0x00000275`005e8280 - 0x00000275`005e5450 ]
+0x008 Blink : 0x00000275`005e4d10 _LIST_ENTRY [ 0x00000275`005e5450 - 0x00000275`005e4440 ]
+0x020 InInitializationOrderLinks : _LIST_ENTRY [ 0x00000275`005e4d20 - 0x00000275`005e4450 ]
+0x000 Flink : 0x00000275`005e4d20 _LIST_ENTRY [ 0x00007ffc`29996470 - 0x00000275`005e5460 ]
+0x008 Blink : 0x00000275`005e4450 _LIST_ENTRY [ 0x00000275`005e5460 - 0x00007ffc`29996470 ]
+0x030 DllBase : 0x00007ffc`270e0000 Void // <=== 指向KERNELBASE.dll基址
+0x038 EntryPoint : 0x00007ffc`27121850 Void
+0x040 SizeOfImage : 0x3ac000
+0x048 FullDllName : _UNICODE_STRING "C:\\WINDOWS\\System32\\KERNELBASE.dll"
+0x000 Length : 0x44
+0x002 MaximumLength : 0x46
+0x008 Buffer : 0x00000275`005e5630 "C:\\WINDOWS\\System32\\KERNELBASE.dll"
+0x058 BaseDllName : _UNICODE_STRING "KERNELBASE.dll"
+0x000 Length : 0x1c
+0x002 MaximumLength : 0x1e
+0x008 Buffer : 0x00000275`005e5658 "KERNELBASE.dll"
+0x068 FlagGroup : [4] "???"

略...

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <iostream>
#include <windows.h>
#include <winternl.h>
#include <intrin.h>

#pragma comment(lib, "ntdll.lib")

int main() {
// 获取 PEB 地址
PVOID pPeb = reinterpret_cast<PVOID>(__readgsqword(0x60));

if (!pPeb) {
std::cerr << "Failed to get PEB address." << std::endl;
return 1;
}

// 计算 Ldr 地址的偏移量
ULONG64 ldrOffset = 0x18; // PEB 结构中 Ldr 成员的偏移量

// 计算 Ldr 地址
PVOID pLdr = *reinterpret_cast<PVOID*>(reinterpret_cast<PBYTE>(pPeb) + ldrOffset);

if (!pLdr) {
std::cerr << "Failed to get Ldr address." << std::endl;
return 1;
}

// 计算 InLoadOrderModuleList 地址的偏移量
ULONG64 moduleListOffset = offsetof(PEB_LDR_DATA, InMemoryOrderModuleList);

// 计算 InLoadOrderModuleList 地址
PLIST_ENTRY pModuleList = reinterpret_cast<PLIST_ENTRY>(reinterpret_cast<PBYTE>(pLdr) + moduleListOffset);

// 获取第一个模块的地址,通常是 ntdll.dll
PLIST_ENTRY pFirstEntry = pModuleList->Flink;
PLDR_DATA_TABLE_ENTRY pDataTableEntry = CONTAINING_RECORD(pFirstEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
PVOID pModExeBase = pDataTableEntry->DllBase;
UNICODE_STRING pModExeName = pDataTableEntry->FullDllName;
// 将 UNICODE_STRING 转换为 std::wstring
std::wstring ModExeModuleNameW(pModExeName.Buffer, pModExeName.Length / sizeof(WCHAR));
// 输出模块信息
std::wcout << L"Module: " << ModExeModuleNameW << L", Base Address: " << pModExeBase << std::endl;

PLDR_DATA_TABLE_ENTRY pKernel32Entry = nullptr;

// 计算第二个模块的地址,通常是 ntdll.dll
PLIST_ENTRY pSecondEntry = pFirstEntry->Flink;
PLDR_DATA_TABLE_ENTRY pSecondDataTableEntry = CONTAINING_RECORD(pSecondEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
PVOID pNtDllBase = pSecondDataTableEntry->DllBase;
UNICODE_STRING NtDllName = pSecondDataTableEntry->FullDllName;
// 将 UNICODE_STRING 转换为 std::wstring
std::wstring NtDllModuleNameW(NtDllName.Buffer, NtDllName.Length / sizeof(WCHAR));
// 输出模块信息
std::wcout << L"Module: " << NtDllModuleNameW << L", Base Address: " << pNtDllBase << std::endl;

// 计算第三个模块的地址,通常是 KERNEL32.dll
PLIST_ENTRY pThirdEntry = pSecondEntry->Flink;
PLDR_DATA_TABLE_ENTRY pThirdDataTableEntry = CONTAINING_RECORD(pThirdEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
PVOID pKernel32Base = pThirdDataTableEntry->DllBase;
UNICODE_STRING Kernel32Name = pThirdDataTableEntry->FullDllName;
// 将 UNICODE_STRING 转换为 std::wstring
std::wstring Kernel32ModuleNameW(Kernel32Name.Buffer, Kernel32Name.Length / sizeof(WCHAR));
// 输出模块信息
std::wcout << L"Module: " << Kernel32ModuleNameW << L", Base Address: " << pKernel32Base << std::endl;

return 0;
}

评论