apc注入

1.entry.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//entry.c
#include "Inject.h"

BOOLEAN isdebug = TRUE;
NTSTATUS DriverUnload(PDRIVER_OBJECT pdriver)
{
UnTestInjectAPC();
DebugMessage("unload...\n");
return STATUS_SUCCESS;
}
PDRIVER_OBJECT g_DriverObject = NULL;
NTSTATUS DriverEntry(PDRIVER_OBJECT pdriver, PUNICODE_STRING path)
{
pdriver->DriverUnload = DriverUnload;
DbgPrint("loading...\n");
g_DriverObject = pdriver;
TestInjectAPC();
return STATUS_SUCCESS;
}

2.Inject.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
//Inject.h
#pragma once

#include "DllInject.h"
#include "C:\D\test\CC++\cc++lib\driver\ntfill.h"

VOID TestInjectAPC();

ULONG_PTR GetKernelModuleBase(PUCHAR moduleName, PULONG pModuleSize);
CHAR g_injectshellcode[];
PVOID CreateInjectCode(PVOID r3addr, PWCHAR dllpath);

PVOID SearchHexcode(PCHAR search_hex, ULONG hex_size, PVOID strataddr, ULONG search_long);
PVOID FindKernelSystemRoutine(PCHAR shellcode, SIZE_T size);
NTSTATUS DllInjectRemote(HANDLE pid, PWCHAR dllpath);

VOID InjectApc_KernelRoutine(PRKAPC Apc,PKNORMAL_ROUTINE* NormalRoutine,PVOID* NormalContext,
PVOID* SystemArgument1,PVOID* SystemArgument2);

PVOID g_inject_shellcode;


VOID InjectApc_PreApc(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2);
NTSTATUS DLLInjectApc(HANDLE pid, PWCHAR dllpath);

VOID UnTestInjectAPC();
VOID TestInjectAPC();

3. EnumModule.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <ntifs.h>
//#include "EnumDriver.h"


#include "C:\D\test\CC++\cc++lib\driver\def.h"

ULONG HandleToPid(HANDLE handle);

PEPROCESS GetProcessObjectByName(char* name);

ULONG GetProcessIdByName(char* name);

HANDLE EprocessToHandle(PEPROCESS eprocess);

PVOID GetProcessModuleBase(PEPROCESS pe, PWCHAR modname);

VOID TestEnumModule();

4.DllInject.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
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
#pragma once
#include <ntifs.h>
#include <wdm.h>
#include <intrin.h>
#include <windef.h>
#include "C:\D\test\CC++\cc++lib\driver\NativeEnums.h"
#include "C:\D\test\CC++\cc++lib\driver\NativeStructs.h"
#include "C:\D\test\CC++\cc++lib\driver\Imports.h"
#include "C:\D\test\CC++\cc++lib\driver\ntfill.h"
#include "ntstrsafe.h"
#define DebugMessage(x, ...) DbgPrintEx(0,0,x,__VA_ARGS__)


NTSYSAPI BOOLEAN NTAPI PsIsProtectedProcess(IN PEPROCESS Process); // 检测进程是否受保护
NTSYSAPI PVOID NTAPI PsGetProcessWow64Process(IN PEPROCESS Process); // 获取WOW64进程的PEB
PVOID GetKernel32Address(IN PEPROCESS Process, IN BOOLEAN IsWow64);
#define IMAGE_DOS_SIGN 0x5A4D // MZ
#define IMAGE_NT_SIGN 0x00004550 // PE00
#define IMAGE_NT_OPT_HDR32_MAGIC 0x10B // 32位PE
#define IMAGE_NT_OPT_HDR64_MAGIC 0x20B // 64位PE

typedef struct _IMAGE_DOS_HDR {
USHORT e_magic;
USHORT e_cblp;
USHORT e_cp;
USHORT e_crlc;
USHORT e_cparhdr;
USHORT e_minalloc;
USHORT e_maxalloc;
USHORT e_ss;
USHORT e_sp;
USHORT e_csum;
USHORT e_ip;
USHORT e_cs;
USHORT e_lfarlc;
USHORT e_ovno;
USHORT e_res[4];
USHORT e_oemid;
USHORT e_oeminfo;
USHORT e_res2[10];
LONG e_lfanew;
} IMAGE_DOS_HDR, * PIMAGE_DOS_HDR;

typedef struct _IMAGE_FILE_HDR {
USHORT Machine;
USHORT NumberOfSections;
ULONG TimeDateStamp;
ULONG PointerToSymbolTable;
ULONG NumberOfSymbols;
USHORT SizeOfOptionalHeader;
USHORT Characteristics;
} IMAGE_FILE_HDR, * PIMAGE_FILE_HDR;

typedef struct _IMAGE_DATA_DIR {
ULONG VirtualAddress;
ULONG Size;
} IMAGE_DATA_DIR, * PIMAGE_DATA_DIR;

typedef struct _IMAGE_OPT_HDR64 {
USHORT Magic;
UCHAR MajorLinkerVersion;
UCHAR MinorLinkerVersion;
ULONG SizeOfCode;
ULONG SizeOfInitializedData;
ULONG SizeOfUninitializedData;
ULONG AddressOfEntryPoint;
ULONG BaseOfCode;
ULONGLONG ImageBase;
ULONG SectionAlignment;
ULONG FileAlignment;
USHORT MajorOperatingSystemVersion;
USHORT MinorOperatingSystemVersion;
USHORT MajorImageVersion;
USHORT MinorImageVersion;
USHORT MajorSubsystemVersion;
USHORT MinorSubsystemVersion;
ULONG Win32VersionValue;
ULONG SizeOfImage;
ULONG SizeOfHeaders;
ULONG CheckSum;
USHORT Subsystem;
USHORT DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
ULONG LoaderFlags;
ULONG NumberOfRvaAndSizes;
IMAGE_DATA_DIR DataDirectory[16];
} IMAGE_OPT_HDR64, * PIMAGE_OPT_HDR64;

typedef struct _IMAGE_OPT_HDR32 {
USHORT Magic;
UCHAR MajorLinkerVersion;
UCHAR MinorLinkerVersion;
ULONG SizeOfCode;
ULONG SizeOfInitializedData;
ULONG SizeOfUninitializedData;
ULONG AddressOfEntryPoint;
ULONG BaseOfCode;
ULONG BaseOfData;
ULONG ImageBase;
ULONG SectionAlignment;
ULONG FileAlignment;
USHORT MajorOperatingSystemVersion;
USHORT MinorOperatingSystemVersion;
USHORT MajorImageVersion;
USHORT MinorImageVersion;
USHORT MajorSubsystemVersion;
USHORT MinorSubsystemVersion;
ULONG Win32VersionValue;
ULONG SizeOfImage;
ULONG SizeOfHeaders;
ULONG CheckSum;
USHORT Subsystem;
USHORT DllCharacteristics;
ULONG SizeOfStackReserve;
ULONG SizeOfStackCommit;
ULONG SizeOfHeapReserve;
ULONG SizeOfHeapCommit;
ULONG LoaderFlags;
ULONG NumberOfRvaAndSizes;
IMAGE_DATA_DIR DataDirectory[16];
} IMAGE_OPT_HDR32, * PIMAGE_OPT_HDR32;

typedef struct _IMAGE_NT_HDR32 {
ULONG Signature;
IMAGE_FILE_HDR FileHeader;
IMAGE_OPT_HDR32 OptHeader32;
} IMAGE_NT_HDR32, * PIMAGE_NT_HDR32;

typedef struct _IMAGE_NT_HDR64 {
ULONG Signature;
IMAGE_FILE_HDR FileHeader;
IMAGE_OPT_HDR64 OptHeader64;
} IMAGE_NT_HDR64, * PIMAGE_NT_HDR64;

typedef struct _IMAGE_EXPORT_DIR {
ULONG Characteristics;
ULONG TimeDateStamp;
USHORT MajorVersion;
USHORT MinorVersion;
ULONG Name;
ULONG Base;
ULONG NumberOfFunctions;
ULONG NumberOfNames;
ULONG AddressOfFunctions;
ULONG AddressOfNames;
ULONG AddressOfNameOrdinals;
} IMAGE_EXPORT_DIR, * PIMAGE_EXPORT_DIR;

typedef struct _IMAGE_SECTION_HDR {
UCHAR Name[8];
union {
ULONG PhysicalAddress;
ULONG VirtualSize;
} Misc;
ULONG VirtualAddress;
ULONG SizeOfRawData;
ULONG PointerToRawData;
ULONG PointerToRelocations;
ULONG PointerToLinenumbers;
USHORT NumberOfRelocations;
USHORT NumberOfLinenumbers;
ULONG Characteristics;
} IMAGE_SECTION_HDR, * PIMAGE_SECTION_HDR;
PVOID GetExportFuncAddr(IN PVOID DllBase, IN PCSTR FuncName);

5.Inject.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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//inject.c
//#include "process.h"
//#include "file.h"
//#include "kernel.h"
#include "inject.h"
#include "C:\D\test\CC++\cc++lib\driver\def.h"
#include "C:\D\test\CC++\cc++lib\driver\ntldr.h"
#include "EnumModule.h"

VOID TestInjectAPC();
/*取驱动模块基址与大小*/
ULONG_PTR GetKernelModuleBase(PUCHAR moduleName, PULONG pModuleSize) {
RTL_PROCESS_MODULES SysModules = { 0 };
PRTL_PROCESS_MODULES pModules = &SysModules;
ULONG SystemInformationLength = 0;
//查询系统中所有内核模块,底层也是遍历链表
NTSTATUS status = ZwQuerySystemInformation(SystemModuleInformation, pModules, sizeof(RTL_PROCESS_MODULES), &SystemInformationLength);
if (status == STATUS_INFO_LENGTH_MISMATCH) {
pModules = ExAllocatePool(NonPagedPool, SystemInformationLength + sizeof(RTL_PROCESS_MODULES));
RtlZeroMemory(pModules, SystemInformationLength + sizeof(RTL_PROCESS_MODULES));
status = ZwQuerySystemInformation(SystemModuleInformation, pModules, SystemInformationLength + sizeof(RTL_PROCESS_MODULES), &SystemInformationLength);
if (!NT_SUCCESS(status)) {
ExFreePool(pModules);
return 0;
}
}
if (!strcmp("ntoskrnl.exe", moduleName) || !strcmp("ntkrnlpa.exe.exe", moduleName)) {
*pModuleSize = pModules->Modules[0].ImageSize;
ULONG_PTR ret = pModules->Modules[0].ImageBase;
if (SystemInformationLength) {
ExFreePool(pModules);
}
return ret;
}
for (ULONG i = 0; i < pModules->NumberOfModules; i++) {
if (strstr(pModules->Modules[i].FullPathName, moduleName)) {
*pModuleSize = pModules->Modules[i].ImageSize;
ULONG_PTR ret = pModules->Modules[i].ImageBase;
if (SystemInformationLength) {
ExFreePool(pModules);
}
return ret;
}
}
if (SystemInformationLength) {
ExFreePool(pModules);
}
return 0;
}
static CHAR g_injectshellcode[] = {
0x48,0x31,0xC9,//XOR RCX,RCX
0x48,0x31,0xD2,//xor rdx,rdx
0x49,0xB8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//mov r8,punicode_string
0x49,0xB9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//mov r8,punicode_string
0x48,0xB8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//mov ldrLoaddll
0x48,0x83,0xEC,0x48,//sub rsp,48
0xff,0xd0,//call rax
0x48,0x83,0xC4,0x48,0xC3,0x90 };//add rsp,48 + ret
PVOID CreateInjectCode(PVOID r3addr, PWCHAR dllpath)
{
UNICODE_STRING str = { 0 };
PVOID retaddr = NULL;
RtlInitUnicodeString(&str, dllpath);
PVOID ldrloaddll = GetExportFuncAddr(GetProcessModuleBase(IoGetCurrentProcess(), L"ntdll.dll"), "LdrLoadDll");
if (!ldrloaddll)return NULL;
__try
{
RtlCopyMemory(r3addr, &str, sizeof(USHORT) * 2);
*(PULONG64)((ULONG64)r3addr + sizeof(USHORT) * 2 + 4) = (PULONG64)r3addr + 20;
RtlCopyMemory((PVOID)((PULONG64)r3addr + 20), str.Buffer, str.Length);
*(PULONG64)(g_injectshellcode + 8) = r3addr;
*(PULONG64)(g_injectshellcode + 18) = (ULONG64)r3addr + 400;
*(PULONG64)(g_injectshellcode + 28) = (ULONG64)ldrloaddll;
retaddr = (PVOID)((ULONG64)r3addr + 420);
RtlCopyMemory(retaddr, g_injectshellcode, sizeof(g_injectshellcode));
}
__except (1) { retaddr = NULL; }
return retaddr;
}

PVOID SearchHexcode(PCHAR search_hex, ULONG hex_size, PVOID strataddr, ULONG search_long)
{
if (!MmIsAddressValid(strataddr))
return NULL;
PCHAR cmpaddr = (PCHAR)strataddr;
for (size_t i = 0; i < search_long; i++)
{
ULONG equal = 0;
for (size_t u = 0; u < hex_size; u++)
{
if (MmIsAddressValid((PCHAR)(cmpaddr + u)) && *(PCHAR)(cmpaddr + u) == search_hex[u])
equal++;
else
break;
}
if (equal == hex_size)
return cmpaddr++;
}
return NULL;
}
PVOID FindKernelSystemRoutine(PCHAR shellcode, SIZE_T size)
{
ULONG modsize = 0;
PVOID modbase = GetKernelModuleBase("ntoskrnl.exe", &modsize);
if (!modbase || !modsize)
return;
return SearchHexcode(shellcode, size, modbase, modsize);
}
NTSTATUS DllInjectRemote(HANDLE pid, PWCHAR dllpath)
{
CHAR hex[] = { 0x40,0x55,0x53,0x56,0x57,0x41,0x54,0x41,0x55,0x41,0x56,0x41,0x57,0x48,0x81,0xEC,0x38,
0x03,0x00,0x00,0x48,0x8d,0x6c,0x24,0x70,0x48,0x8b,0x05,0xC0,0x0C,0x56,0x00 };
PEPROCESS pr = NULL;
PVOID pe = NULL;
UNICODE_STRING str = { 0 };
KAPC_STATE kapc = { 0 };
PVOID newaddr = NULL;
SIZE_T mem_length = 0x1000;
PVOID shelladdr = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
HANDLE hthread = NULL;
LARGE_INTEGER timeout = { .QuadPart = -10 * 1000 * 1000 * 10 };
FN_NtCreateThreadEx NtCreateThreadEx = NULL;

if (!NT_SUCCESS(PsLookupProcessByProcessId(pid, &pe)))
return STATUS_UNSUCCESSFUL;
ObDereferenceObject(pe);
NtCreateThreadEx = FindKernelSystemRoutine(hex, sizeof(hex));
if (!MmIsAddressValid(NtCreateThreadEx))
return STATUS_UNSUCCESSFUL;
KeStackAttachProcess(pe, &kapc);
status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &newaddr, 0, &mem_length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(status))
{
KeUnstackDetachProcess(&kapc);
return STATUS_UNSUCCESSFUL;
}
shelladdr = CreateInjectCode(newaddr, dllpath);
if (!shelladdr)
goto end;
status = NtCreateThreadEx(&hthread, THREAD_ALL_ACCESS, NULL, ZwCurrentProcess(), shelladdr, NULL, 0, 0, 0x10000, 0x100000, NULL);
if (NT_SUCCESS(status))
{
ZwWaitForSingleObject(hthread, FALSE, &timeout);
ZwClose(hthread);
}
end:
ZwFreeVirtualMemory(ZwCurrentProcess(), &newaddr, &mem_length, MEM_RELEASE);
KeUnstackDetachProcess(&kapc);
return status;

}

VOID InjectApc_KernelRoutine(
PRKAPC Apc,
PKNORMAL_ROUTINE* NormalRoutine,
PVOID* NormalContext,
PVOID* SystemArgument1,
PVOID* SystemArgument2)
{
ExFreePool(Apc);
}
PVOID g_inject_shellcode = NULL;

VOID InjectApc_PreApc(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
PVOID newaddr = NULL;
size_t length = 0X1000;
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING dllpath = { 0 };
if (!g_inject_shellcode)
{
status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &newaddr, 0, &length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(status))return;
g_inject_shellcode = CreateInjectCode(newaddr, (PWCHAR)NormalContext);
if (!g_inject_shellcode)
{
ZwFreeVirtualMemory(ZwCurrentProcess(), &newaddr, &length, MEM_RELEASE);
return;
}
}
PRKAPC kapc = (PRKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC));
KeInitializeApc(kapc, PsGetCurrentThread(), OriginalApcEnvironment,
InjectApc_KernelRoutine, NULL, (PKNORMAL_ROUTINE)g_inject_shellcode, UserMode, NULL);
KeInsertQueueApc(kapc, NULL, NULL, IO_NO_INCREMENT);
}
NTSTATUS DLLInjectApc(HANDLE pid, PWCHAR dllpath)
{
g_inject_shellcode = NULL;
for (size_t i = 4; i < 0x10000; i += 4)
{
PETHREAD pethread = NULL;
if (NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)i, &pethread)))
{
if (PsGetThreadProcessId(pethread) == pid)
{
PRKAPC kapc = (PRKAPC)ExAllocatePool(NonPagedPool, sizeof(KAPC));
KeInitializeApc(kapc, pethread, OriginalApcEnvironment,
InjectApc_KernelRoutine, NULL, InjectApc_PreApc, KernelMode, (PVOID)dllpath);
KeInsertQueueApc(kapc, NULL, NULL, IO_NO_INCREMENT);
}
ObDereferenceObject(pethread);
}
}

}

VOID UnTestInjectAPC()
{
}
VOID TestInjectAPC()
{
char pname[] = "Taskmgr.exe";
//CHAR pname[] = "DriverMonitor.exe";
HANDLE pid = 0;
pid = GetProcessIdByName(pname);
DLLInjectApc(pid, L"C:\\Users\\lyx\\Desktop\\Dll1.dll");
}

6.EnumModule.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
#include "EnumModule.h"
#include "C:\D\test\CC++\cc++lib\driver\NativeEnums.h"
#include "C:\D\test\CC++\cc++lib\driver\NativeStructs.h"
#include "C:\D\test\CC++\cc++lib\driver\Imports.h"
#include "C:\D\test\CC++\cc++lib\driver\ntfill.h"


ULONG HandleToPid(HANDLE handle)
{
if (!handle)return 0;
PROCESS_BASIC_INFORMATION ProcessBasicInfor;

// 初始化字符串,并获取动态地址
UNICODE_STRING UtrZwQueryInformationProcessName = RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");
// 定义函数指针
PfnZwQueryInformationProcess 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);
}

7.DllInject.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
#include "DllInject.h"


PVOID GetExportFuncAddr(IN PVOID DllBase, IN PCSTR FuncName)
{
PULONG Ent = NULL; // 名称表
PULONG Eat = NULL; // 地址表
PUSHORT Eot = NULL; // 序号表
PIMAGE_DOS_HDR DosHdr = NULL;
PIMAGE_NT_HDR32 NtHdr32 = NULL;
PIMAGE_NT_HDR64 NtHdr64 = NULL;
PIMAGE_EXPORT_DIR ExportDir = NULL;
// 检测参数是否有效
if (!DllBase || !FuncName) return NULL;
__try {
// 检测DOS头是否匹配
DosHdr = (PIMAGE_DOS_HDR)DllBase;
if (DosHdr->e_magic != IMAGE_DOS_SIGN) return NULL;
// 检测NT头是否匹配
NtHdr32 = (PIMAGE_NT_HDR32)((PUCHAR)DllBase + DosHdr->e_lfanew);
NtHdr64 = (PIMAGE_NT_HDR64)((PUCHAR)DllBase + DosHdr->e_lfanew);
if (NtHdr32->Signature != IMAGE_NT_SIGN) return NULL;
// 检测是32位PE文件还是64位PE文件
if (NtHdr32->OptHeader32.Magic == IMAGE_NT_OPT_HDR32_MAGIC)
{
ExportDir = (PIMAGE_EXPORT_DIR)(NtHdr32->OptHeader32.
DataDirectory[0].VirtualAddress + (ULONG_PTR)DllBase);
}
else
{
ExportDir = (PIMAGE_EXPORT_DIR)(NtHdr64->OptHeader64.
DataDirectory[0].VirtualAddress + (ULONG_PTR)DllBase);
}
// 获取导出表的相关信息
Eot = (PUSHORT)(ExportDir->AddressOfNameOrdinals + (ULONG_PTR)DllBase);
Ent = (PULONG)(ExportDir->AddressOfNames + (ULONG_PTR)DllBase);
Eat = (PULONG)(ExportDir->AddressOfFunctions + (ULONG_PTR)DllBase);
// 对比名称表中的函数名是否匹配
for (ULONG i = 0; i < ExportDir->NumberOfNames; i++)
{
// 在序号表中相同的位置存储了地址表的索引
if (!strcmp((PCHAR)(Ent[i] + (ULONG_PTR)DllBase), FuncName))
return (PVOID)(Eat[Eot[i]] + (ULONG_PTR)DllBase);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
return NULL;
}
PVOID GetKernel32Address(IN PEPROCESS Process, IN BOOLEAN IsWow64)
{
LARGE_INTEGER Timeout = { 0 };
__try {
#ifdef AMD64
if (IsWow64)
{
// 在64位进程中遍历WOW64模块
PLIST_ENTRY32 ListEntry32 = NULL;
PPEB_LDR_DATA32 PebLdrData32 = NULL;
PLDR_DATA_TABLE_ENTRY32 TableEntry32 = NULL;
PPEB32 Peb32 = (PPEB32)PsGetProcessWow64Process(Process);
if (!Peb32) return NULL;
// 等待Ldr已初始化完毕
Timeout.QuadPart = -10LL * 1000 * 250; // 250毫秒
for (INT i = 0; (!Peb32->Ldr) && (i < 10); i++)
KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
if (!Peb32->Ldr) return NULL;
// 遍历已加载模块列表(注意多线程竞争问题)
// 在R3中是用快照的方式获取,其中使用的是临界区
PebLdrData32 = (PPEB_LDR_DATA32)Peb32->Ldr;
ListEntry32 = (PLIST_ENTRY32)PebLdrData32->InLoadOrderModuleList.Flink;
while (ListEntry32 != &PebLdrData32->InLoadOrderModuleList)
{
TableEntry32 = CONTAINING_RECORD(
ListEntry32, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks);
if (TableEntry32->BaseDllName.Buffer && TableEntry32->BaseDllName.Length)
{
// 对比模块名称
if (!_wcsnicmp((PWCHAR)TableEntry32->BaseDllName.Buffer,
L"Kernel32.dll", TableEntry32->BaseDllName.Length / 2))
{
return (PVOID)TableEntry32->DllBase;
}
}
ListEntry32 = (PLIST_ENTRY32)ListEntry32->Flink;
}
}
else
{
#endif
// 获取进程的PEB信息
PLIST_ENTRY ListEntry = NULL;
PPEB_LDR_DATA PebLdrData = NULL;
PLDR_DATA_TABLE_ENTRY TableEntry = NULL;
PPEB Peb = PsGetProcessPeb(Process);
if (!Peb) return NULL;
#ifndef AMD64
UNREFERENCED_PARAMETER(IsWow64);
#endif
// 等待Ldr已初始化完毕
Timeout.QuadPart = -10LL * 1000 * 250; // 250毫秒
for (INT i = 0; (!Peb->Ldr) && (i < 10); i++)
KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
if (!Peb->Ldr) return NULL;
// 遍历已加载模块列表(注意多线程竞争问题)
// 在R3中是用快照的方式获取,其中使用的是临界区
PebLdrData = (PPEB_LDR_DATA)Peb->Ldr;
ListEntry = (PLIST_ENTRY)PebLdrData->InLoadOrderModuleList.Flink;
while (ListEntry != &PebLdrData->InLoadOrderModuleList)
{
TableEntry = CONTAINING_RECORD(
ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
if (TableEntry->BaseDllName.Buffer && TableEntry->BaseDllName.Length)
{
// 对比模块名称
if (!_wcsnicmp(TableEntry->BaseDllName.Buffer,
L"Kernel32.dll", TableEntry->BaseDllName.Length / 2))
{
return (PVOID)TableEntry->DllBase;
}
}
ListEntry = (PLIST_ENTRY)ListEntry->Flink;
}
#ifdef AMD64
}
#endif
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
return NULL;
}