windows驱动开发25.枚举进程信息,例如获取特定进程内特定模块的基址
获取特定进程内特定模块的基址写法一
遍历驱动模块需要用到一些未导出的函数与结构体定义
entry.c
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
//https://www.bilibili.com/video/BV1bU4y1m7y9/?spm_id_from=333.999.0.0&vd_source=5777815674b3f4e5c227299a8de61c9b
//Windows驱动开发-驱动中枚举进程信息-中文名称不乱码那种
NTSTATUS PsReferenceProcessFilePointer(IN PEPROCESS pEprocess, OUT PVOID* pFilePointer);
HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS pEprocess);
VOID DrvUnloadEnumProcess(PDRIVER_OBJECT pDriver);
NTSTATUS DriverEntryEnumProcess(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path);
PEPROCESS MyLookupProcess(HANDLE ProcessId);
VOID EnumProcess();
PVOID GetUserModuleBaseAddress(IN PEPROCESS EProcess, IN PUNICODE_STRING ModuleName, IN BOOLEAN IsWow64);
PVOID GetModuleExportAddress(IN PVOID ModuleBase, IN PCCHAR FunctionName, IN PEPROCESS EProcess);
// 获取进程的PEB
NTSYSAPI PVOID NTAPI PsGetProcessWow64Process(IN PEPROCESS Process); // 获取WOW64进程的PEB
NTKERNELAPI
PPEB
NTAPI
PsGetProcessPeb(IN PEPROCESS Process);
static VOID UnDriver(PDRIVER_OBJECT pDriverObj)
{
DbgPrint("[-] 驱动卸载 \n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
HANDLE ProcessID = (HANDLE)7924;
PEPROCESS EProcess = NULL;
NTSTATUS Status = STATUS_SUCCESS;
KAPC_STATE ApcState;
DbgPrint("Hello \n");
// 根据PID得到进程EProcess结构
Status = PsLookupProcessByProcessId(ProcessID, &EProcess);
if (Status != STATUS_SUCCESS)
{
DbgPrint("获取EProcessID失败 \n");
return Status;
}
// 判断目标进程是32位还是64位
BOOLEAN IsWow64 = (PsGetProcessWow64Process(EProcess) != NULL) ? TRUE : FALSE;
// 验证地址是否可读
if (!MmIsAddressValid(EProcess))
{
DbgPrint("地址不可读 \n");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
// 将当前线程连接到目标进程的地址空间(附加进程)
KeStackAttachProcess((PRKPROCESS)EProcess, &ApcState);
__try
{
UNICODE_STRING NtdllUnicodeString = { 0 };
PVOID NtdllAddress = NULL;
// 得到进程内ntdll.dll模块基地址
RtlInitUnicodeString(&NtdllUnicodeString, L"Ntdll.dll");
NtdllAddress = GetUserModuleBaseAddress(EProcess, &NtdllUnicodeString, IsWow64);
if (!NtdllAddress)
{
DbgPrint("没有找到基址 \n");
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
DbgPrint("[*] 模块ntdll.dll基址: %p \n", NtdllAddress);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
// 取消附加
KeUnstackDetachProcess(&ApcState);
Driver->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
// 获取特定进程内特定模块的基址
PVOID GetUserModuleBaseAddress(IN PEPROCESS EProcess, IN PUNICODE_STRING ModuleName, IN BOOLEAN IsWow64)
{
if (EProcess == NULL)
return NULL;
__try
{
// 设置延迟时间为250毫秒
LARGE_INTEGER Time = { 0 };
Time.QuadPart = -250ll * 10 * 1000;
// 如果是32位则执行如下代码
if (IsWow64)
{
// 得到PEB进程信息
PPEB32 Peb32 = (PPEB32)PsGetProcessWow64Process(EProcess);
if (Peb32 == NULL)
{
return NULL;
}
// 延迟加载等待时间
for (INT i = 0; !Peb32->Ldr && i < 10; i++)
{
KeDelayExecutionThread(KernelMode, TRUE, &Time);
}
// 没有PEB加载超时
if (!Peb32->Ldr)
{
return NULL;
}
// 搜索模块 InLoadOrderModuleList
for (PLIST_ENTRY32 ListEntry = (PLIST_ENTRY32)((PPEB_LDR_DATA32)Peb32->Ldr)->InLoadOrderModuleList.Flink; ListEntry != &((PPEB_LDR_DATA32)Peb32->Ldr)->InLoadOrderModuleList; ListEntry = (PLIST_ENTRY32)ListEntry->Flink)
{
UNICODE_STRING UnicodeString;
PLDR_DATA_TABLE_ENTRY32 LdrDataTableEntry32 = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);
RtlUnicodeStringInit(&UnicodeString, (PWCH)LdrDataTableEntry32->BaseDllName.Buffer);
// 找到了返回模块基址
if (RtlCompareUnicodeString(&UnicodeString, ModuleName, TRUE) == 0)
{
return (PVOID)LdrDataTableEntry32->DllBase;
}
}
}
// 如果是64位则执行如下代码
else
{
// 同理,先找64位PEB
PPEB Peb = PsGetProcessPeb(EProcess);
if (!Peb)
{
return NULL;
}
// 延迟加载
for (INT i = 0; !Peb->Ldr && i < 10; i++)
{
KeDelayExecutionThread(KernelMode, TRUE, &Time);
}
// 找不到PEB直接返回
if (!Peb->Ldr)
{
return NULL;
}
// 遍历链表
for (PLIST_ENTRY ListEntry = Peb->Ldr->InLoadOrderModuleList.Flink; ListEntry != &Peb->Ldr->InLoadOrderModuleList; ListEntry = ListEntry->Flink)
{
// 将特定链表转换为PLDR_DATA_TABLE_ENTRY格式
PLDR_DATA_TABLE_ENTRY LdrDataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
// 找到了则返回地址
if (RtlCompareUnicodeString(&LdrDataTableEntry->BaseDllName, ModuleName, TRUE) == 0)
{
return LdrDataTableEntry->DllBase;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return NULL;
}
return NULL;
}ImportStruct.h
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
typedef struct _LDR_DATA_TABLE_ENTRY32
{
LIST_ENTRY32 InLoadOrderLinks;
LIST_ENTRY32 InMemoryOrderLinks;
LIST_ENTRY32 InInitializationOrderLinks;
ULONG DllBase;
ULONG EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING32 FullDllName;
UNICODE_STRING32 BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY32 HashLinks;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY32, * PLDR_DATA_TABLE_ENTRY32;
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;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY HashLinks;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
// 64位PEB相关结构体定义
typedef struct _PEB_LDR_DATA {
ULONG Length;
UCHAR Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
typedef struct _PEB {
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
PVOID Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PVOID ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PVOID AtlThunkSListPtr;
PVOID IFEOKey;
PVOID CrossProcessFlags;
PVOID UserSharedInfoPtr;
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
PVOID ApiSetMap;
} PEB, * PPEB;
// 32位PEB相关结构体定义
typedef struct _PEB_LDR_DATA32 {
ULONG Length;
UCHAR Initialized;
ULONG SsHandle;
LIST_ENTRY32 InLoadOrderModuleList;
LIST_ENTRY32 InMemoryOrderModuleList;
LIST_ENTRY32 InInitializationOrderModuleList;
} PEB_LDR_DATA32, * PPEB_LDR_DATA32;
typedef struct _PEB32 {
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
ULONG Mutant;
ULONG ImageBaseAddress;
ULONG Ldr;
ULONG ProcessParameters;
ULONG SubSystemData;
ULONG ProcessHeap;
ULONG FastPebLock;
ULONG AtlThunkSListPtr;
ULONG IFEOKey;
ULONG CrossProcessFlags;
ULONG UserSharedInfoPtr;
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
ULONG ApiSetMap;
} PEB32, * PPEB32;
获取特定进程内特定模块的基址写法二
遍历驱动模块需要用到一些未导出的函数与结构体定义
entry.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NTSTATUS DriverUnload(PDRIVER_OBJECT pdriver)
{
DbgPrint("unload...\n");
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pdriver, PUNICODE_STRING path)
{
pdriver->DriverUnload = DriverUnload;
DbgPrint("loading...\n");
TestEnumModule();
return STATUS_SUCCESS;
}EnumDriver.h
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
//传入进程名得到PID
ULONG GetProcessIdByName(char* name);
VOID TestEnumModule();
// 通过PEPROCESS获取模块基址
PVOID GetProcessModuleBase(PEPROCESS pe, PWCHAR modname);
// HANDLE句柄转换为PID
ULONG HandleToPid(HANDLE handle);
// EProcess转换为Handle句柄
HANDLE EprocessToHandle(PEPROCESS eprocess);
typedef NTSTATUS(*PfnZwQueryInformationProcess)(
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength
);
NTKERNELAPI
PPEB
NTAPI
PsGetProcessPeb(IN PEPROCESS Process);
NTKERNELAPI
PVOID
NTAPI
PsGetProcessWow64Process(IN PEPROCESS Process);
////传入进程名字通过遍历进程得到PEPROCESS
NTKERNELAPI CHAR* PsGetProcessImageFileName(PEPROCESS Process);
// 定义函数指针
PfnZwQueryInformationProcess ZwQueryInformationProcess;EnumDriver.c
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
ULONG HandleToPid(HANDLE handle)
{
if (!handle)return 0;
PROCESS_BASIC_INFORMATION ProcessBasicInfor;
// 初始化字符串,并获取动态地址
UNICODE_STRING UtrZwQueryInformationProcessName = RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
ZwQueryInformationProcess = (PfnZwQueryInformationProcess)MmGetSystemRoutineAddress(&UtrZwQueryInformationProcessName);
// 调用查询
ZwQueryInformationProcess(
handle,
ProcessBasicInformation,
(PVOID)&ProcessBasicInfor,
sizeof(ProcessBasicInfor),
NULL);
// 返回进程PID
return ProcessBasicInfor.UniqueProcessId;
}
PEPROCESS GetProcessObjectByName(char* name)
{
if (!name)return NULL;
SIZE_T temp;
for (temp = 100; temp < 10000; temp += 4)
{
NTSTATUS status;
PEPROCESS ep;
status = PsLookupProcessByProcessId((HANDLE)temp, &ep);
if (NT_SUCCESS(status))
{
char* pn = PsGetProcessImageFileName(ep);
if (_stricmp(pn, name) == 0)
return ep;
}
}
return NULL;
}
ULONG GetProcessIdByName(char* name)
{
if (!name)return 0;
////传入进程名字通过遍历进程得到PEPROCESS
PEPROCESS eprocess = GetProcessObjectByName(name);
if (!eprocess)
return 0;
// EProcess转换为Handle句柄
HANDLE handle = EprocessToHandle(eprocess);
if (handle == 0)return 0;
// HANDLE句柄转换为PID
ULONG pid = HandleToPid(handle);
return pid;
}
HANDLE EprocessToHandle(PEPROCESS eprocess)
{
if (!eprocess)return NULL;
HANDLE hProcessHandle = (HANDLE)-1;
NTSTATUS status = ObOpenObjectByPointer(
eprocess,
OBJ_KERNEL_HANDLE,
0,
0,
*PsProcessType,
KernelMode,
&hProcessHandle
);
if (status == STATUS_SUCCESS)
{
return hProcessHandle;
}
return NULL;
}
PVOID GetProcessModuleBase(PEPROCESS pe, PWCHAR modname)
{
BOOLEAN iswow64 = TRUE;
PVOID base = PsGetProcessWow64Process(pe);
if (!base)
{
iswow64 = FALSE;
base = PsGetProcessPeb(pe);
}
if (!base)return NULL;
UNICODE_STRING temp = { 0 };
RtlInitUnicodeString(&temp, modname);
KAPC_STATE kapc = { 0 };
KeStackAttachProcess(pe, &kapc);
PVOID modbase = NULL;
if (!iswow64)
{
PLDR_DATA_TABLE_ENTRY entry = NULL;
PLIST_ENTRY start = ((PPEB)base)->Ldr->InMemoryOrderModuleList.Flink;
PLIST_ENTRY end = start;
do {
entry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(start, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
if (entry->DllBase != 0)
{
if (RtlCompareUnicodeString(&temp, &entry->BaseDllName, TRUE) == 0)
{
Log("%wz,%p\n", &entry->BaseDllName, entry->DllBase);
modbase = entry->DllBase;
KeUnstackDetachProcess(&kapc);
return modbase;
}
}
start = start->Flink;
} while (start != end);
}
else
{
PLDR_DATA_TABLE_ENTRY32 entry = ((PLDR_DATA_TABLE_ENTRY32)(((PPEB32)base)->Ldr))->InInitializationOrderLinks.Flink;
PLDR_DATA_TABLE_ENTRY32 end = entry;
do {
if (entry->DllBase != 0)
{
if (wcscmp(entry->BaseDllName.Buffer, modname) == 0)
{
Log("%p,%ws\n", entry->DllBase, entry->BaseDllName.Buffer);
modbase = entry->DllBase;
KeUnstackDetachProcess(&kapc);
return modbase;
}
}
entry = (PLDR_DATA_TABLE_ENTRY32)entry->InLoadOrderLinks.Blink;
} while (entry != end);
}
KeUnstackDetachProcess(&kapc);
return NULL;
}
VOID TestEnumModule()
{
//test x86_64
HANDLE pid = NULL;
CHAR pname[] = "Taskmgr.exe";
pid = GetProcessIdByName(pname);
if (!pid)
{
DbgPrint("error1 pid get false\n");
return;
}
PEPROCESS pe = NULL;
PsLookupProcessByProcessId(pid, &pe);
ObReferenceObject(pe);
PVOID mod = GetProcessModuleBase(pe, L"ntdll.dll");
DbgPrint("x64:%p\n", mod);
//test x86
ULONG pid2 = 0;
CHAR pname2[] = "DriverMoitor.exe";
pid2 = GetProcessIdByName(pname2);
if (!pid)
{
DbgPrint("error1 pid get false\n");
return;
}
PsLookupProcessByProcessId(pid2, &pe);
ObReferenceObject(pe);
mod = GetProcessModuleBase(pe, L"ntdll.dll");
Log("x86:%p\n", mod);
}ImportStruct.h
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
typedef struct _LDR_DATA_TABLE_ENTRY32
{
LIST_ENTRY32 InLoadOrderLinks;
LIST_ENTRY32 InMemoryOrderLinks;
LIST_ENTRY32 InInitializationOrderLinks;
ULONG DllBase;
ULONG EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING32 FullDllName;
UNICODE_STRING32 BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY32 HashLinks;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY32, * PLDR_DATA_TABLE_ENTRY32;
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;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY HashLinks;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
// 64位PEB相关结构体定义
typedef struct _PEB_LDR_DATA {
ULONG Length;
UCHAR Initialized;
PVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} PEB_LDR_DATA, * PPEB_LDR_DATA;
typedef struct _PEB {
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
PVOID Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PVOID ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PVOID FastPebLock;
PVOID AtlThunkSListPtr;
PVOID IFEOKey;
PVOID CrossProcessFlags;
PVOID UserSharedInfoPtr;
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
PVOID ApiSetMap;
} PEB, * PPEB;
// 32位PEB相关结构体定义
typedef struct _PEB_LDR_DATA32 {
ULONG Length;
UCHAR Initialized;
ULONG SsHandle;
LIST_ENTRY32 InLoadOrderModuleList;
LIST_ENTRY32 InMemoryOrderModuleList;
LIST_ENTRY32 InInitializationOrderModuleList;
} PEB_LDR_DATA32, * PPEB_LDR_DATA32;
typedef struct _PEB32 {
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR BitField;
ULONG Mutant;
ULONG ImageBaseAddress;
ULONG Ldr;
ULONG ProcessParameters;
ULONG SubSystemData;
ULONG ProcessHeap;
ULONG FastPebLock;
ULONG AtlThunkSListPtr;
ULONG IFEOKey;
ULONG CrossProcessFlags;
ULONG UserSharedInfoPtr;
ULONG SystemReserved;
ULONG AtlThunkSListPtr32;
ULONG ApiSetMap;
} PEB32, * PPEB32;
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
