/
说明:Win10 1809
1.为物理地址扩展的 内核模块ntoskrnl.exe申请一块新的SizeOfImage大小的内存
2.将ntoskrnl.exe拉伸读取至新申请的内存
3.修复新申请的ntoskrnl.exe重定位表
4.修复新申请的ntoskrnl.exe系统服务表
5.在KiSystemCall64关键部位加钩子
6.处理你感兴趣的程序 让它调用新的内核模块 /
ReX64Knrl.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
|
#pragma once
#include <ntifs.h>
#include <ntimage.h>
PVOID pNewBuffer
=
nullptr;
typedef struct _SYSTEM_SERVICE_TABLE
/
/
SSDT结构
{
PVOID serviceTableBase;
PVOID serviceCounterTableBase;
ULONGLONG numberofServices;
PVOID paramTableBase;
}SYSTEM_SERVICE_TABLE,
*
PSYSTEM_SERVICE_TABLE;
typedef struct _BaseAddr_Size
{
DWORD_PTR mMoudleBaseAddress;
DWORD_PTR mMoudleSizeOf;
}BaseAddr_Size,
*
PBaseAddr_Size;
typedef struct _PE
{
IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS32 NtHeaders;
IMAGE_SECTION_HEADER SectionHeader;
}PE,
*
pPE;
typedef struct _LDR_DATA_TABLE_ENTRY
{
struct _LIST_ENTRY InLoadOrderLinks;
/
/
0x0
struct _LIST_ENTRY InMemoryOrderLinks;
/
/
0x8
struct _LIST_ENTRY InInitializationOrderLinks;
/
/
0x10
VOID
*
DllBase;
/
/
0x18
VOID
*
EntryPoint;
/
/
0x1c
ULONG SizeOfImage;
/
/
0x20
struct _UNICODE_STRING FullDllName;
/
/
0x24
struct _UNICODE_STRING BaseDllName;
/
/
0x2c
ULONG Flags;
/
/
0x34
USHORT LoadCount;
/
/
0x38
USHORT TlsIndex;
/
/
0x3a
union
{
struct _LIST_ENTRY HashLinks;
/
/
0x3c
struct
{
VOID
*
SectionPointer;
/
/
0x3c
ULONG CheckSum;
/
/
0x40
}u;
};
union
{
ULONG TimeDateStamp;
/
/
0x44
VOID
*
LoadedImports;
/
/
0x44
};
VOID
*
EntryPointActivationContext;
/
/
0x48
VOID
*
PatchInformation;
/
/
0x4c
}LDR_DATA_TABLE_ENTRY,
*
PLDR_DATA_TABLE_ENTRY;
/
/
0x50
bytes (sizeof)
EXTERN_C{
VOID UnLoad(PDRIVER_OBJECT pDriver);
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg);
}
NTSTATUS GetKernelImageBase_1(IN PDRIVER_OBJECT pDriver, IN PUNICODE_STRING szMoudeName, OUT PBaseAddr_Size mBeseAddrOfSize);
PVOID GetNewKernelBuffer_1(IN PUNICODE_STRING pStrKernelPathName);
VOID RepirRelocTable(IN DWORD_PTR uNewModule, IN DWORD_PTR uOldModule);
NTSTATUS RepirSSDT(IN PDRIVER_OBJECT pDriver, IN ULONG64 pNewKernelBuffer, IN ULONG64 uOldModule);
NTSTATUS GetSSDT(IN PDRIVER_OBJECT pdriver, OUT PVOID
*
addr);
/
/
通过链表找到ssdt
|
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
|
#pragma once
#include "ReX64Knrl.h"
#pragma warning (disable:4310)
VOID UnLoad(PDRIVER_OBJECT pDriver)
{
UNREFERENCED_PARAMETER(pDriver);
if
(pNewBuffer) ExFreePool(pNewBuffer);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
UNREFERENCED_PARAMETER(pReg);
pDriver
-
>DriverUnload
=
UnLoad;
DbgBreakPoint();
NTSTATUS status
=
STATUS_UNSUCCESSFUL;
UNICODE_STRING szMoudleName
=
RTL_CONSTANT_STRING(L
"ntoskrnl.exe"
);
BaseAddr_Size sz
=
{
0
};
status
=
GetKernelImageBase_1(pDriver, &szMoudleName, &sz);
if
(NT_SUCCESS(status))
{
DbgPrintEx(
77
,
0
,
"GetKernelImageBase_1 sucess!\n"
);
}
else
{
DbgPrintEx(
77
,
0
,
"GetKernelImageBase_1 Faild!\n"
);
return
STATUS_UNSUCCESSFUL;
}
UNICODE_STRING szFileName
=
RTL_CONSTANT_STRING(L
"\\??\\C:\\Windows\\system32\\ntoskrnl.exe"
);
/
/
ntdll.dll
/
/
\\??\\C:\\WINDOWS\\system32\\ntkrnlpa.exe
PVOID pNewKernelBuffer
=
GetNewKernelBuffer_1(&szFileName);
if
(!MmIsAddressValid(pNewKernelBuffer))
{
DbgPrintEx(
77
,
0
,
"pNewKernelBuffer is faild"
);
return
STATUS_UNSUCCESSFUL;
}
DbgPrintEx(
77
,
0
,
"pNewKernelBuffer is: %llx"
, pNewKernelBuffer);
/
/
基址重定位
RepirRelocTable((DWORD_PTR)pNewKernelBuffer, sz.mMoudleBaseAddress);
/
/
系统服务表重定位
status
=
RepirSSDT(pDriver, (ULONG64)pNewKernelBuffer, sz.mMoudleBaseAddress);
if
(NT_SUCCESS(status))
{
DbgPrintEx(
77
,
0
,
"RepirSSDT sucess!\n"
);
}
else
{
DbgPrintEx(
77
,
0
,
"RepirSSDT Faild!\n"
);
return
STATUS_UNSUCCESSFUL;
}
/
/
>>>>>>>> 插入HOOK 代码
return
STATUS_SUCCESS;
}
/
/
[获取当前内核模块基址_1]
NTSTATUS GetKernelImageBase_1(IN PDRIVER_OBJECT pDriver, IN PUNICODE_STRING szMoudeName, OUT PBaseAddr_Size mBeseAddrOfSize)
{
PLIST_ENTRY pCurrObject
=
(PLIST_ENTRY)pDriver
-
>DriverSection;
PLIST_ENTRY pNextObject
=
pCurrObject
-
>Flink;
PLDR_DATA_TABLE_ENTRY szTemp
=
nullptr;
while
(pCurrObject !
=
pNextObject)
{
szTemp
=
(PLDR_DATA_TABLE_ENTRY)pNextObject;
if
(RtlCompareUnicodeString(&szTemp
-
>BaseDllName, szMoudeName, TRUE)
=
=
NULL)
{
mBeseAddrOfSize
-
>mMoudleBaseAddress
=
(DWORD_PTR)(szTemp
-
>DllBase);
mBeseAddrOfSize
-
>mMoudleSizeOf
=
szTemp
-
>SizeOfImage;
DbgPrintEx(
77
,
0
,
"DllBase:0x%llX SizeOfImage:0x%X BaseDllName:%wZ FullDllName:%wZ "
, szTemp
-
>DllBase, szTemp
-
>SizeOfImage, szTemp
-
>BaseDllName, szTemp
-
>FullDllName);
return
STATUS_SUCCESS;
}
pNextObject
=
pNextObject
-
>Flink;
}
return
STATUS_UNSUCCESSFUL;
}
/
/
[
1
、获取新的内核模块虚拟缓存]
PVOID GetNewKernelBuffer_1(IN PUNICODE_STRING pStrKernelPathName)
{
PE pe
=
{
0
};
HANDLE hFile
=
NULL;
OBJECT_ATTRIBUTES objectAttributes
=
{
0
};
IO_STATUS_BLOCK ioStatusBlock
=
{
0
};
InitializeObjectAttributes(&objectAttributes, pStrKernelPathName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
NTSTATUS ntStatus
=
ZwCreateFile(&hFile, GENERIC_READ, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, NULL,
0
);
if
(!NT_SUCCESS(ntStatus))
{
KdPrint((
"ZwCreateFile错误:%x\n"
, ntStatus));
return
NULL;
}
LARGE_INTEGER fileOffset
=
{
0
};
fileOffset.QuadPart
=
0
;
/
/
读取DOS头
ntStatus
=
ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, &pe.DosHeader, sizeof(IMAGE_DOS_HEADER), &fileOffset, NULL);
if
(!NT_SUCCESS(ntStatus))
{
KdPrint((
"ZwReadFile错误:%x\n"
, ntStatus));
goto exit;
}
fileOffset.QuadPart
+
=
pe.DosHeader.e_lfanew;
/
/
读取NT头
ntStatus
=
ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, &pe.NtHeaders, sizeof(IMAGE_NT_HEADERS), &fileOffset, NULL);
if
(!NT_SUCCESS(ntStatus))
{
KdPrint((
"ZwReadFile错误:%x\n"
, ntStatus));
goto exit;
}
pNewBuffer
=
ExAllocatePool(NonPagedPool, pe.NtHeaders.OptionalHeader.SizeOfImage);
if
(pNewBuffer
=
=
NULL)
{
KdPrint((
"pNewBuffer错误\n"
));
goto exit;
}
PVOID pTempBuffer
=
pNewBuffer;
RtlCopyMemory(pTempBuffer, &pe.DosHeader, sizeof(IMAGE_DOS_HEADER));
pTempBuffer
=
(PVOID)((DWORD_PTR)pTempBuffer
+
pe.DosHeader.e_lfanew);
RtlCopyMemory(pTempBuffer, &pe.NtHeaders, sizeof(IMAGE_NT_HEADERS));
fileOffset.QuadPart
+
=
sizeof(IMAGE_NT_HEADERS);
pTempBuffer
=
(PVOID)((DWORD_PTR)pTempBuffer
+
sizeof(IMAGE_NT_HEADERS));
/
/
读取节表
ntStatus
=
ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, pTempBuffer, (sizeof(IMAGE_SECTION_HEADER)
*
pe.NtHeaders.FileHeader.NumberOfSections), &fileOffset, NULL);
if
(!NT_SUCCESS(ntStatus))
{
KdPrint((
"ZwReadFile错误:%x\n"
, ntStatus));
pNewBuffer
=
nullptr;
goto exit;
}
PIMAGE_SECTION_HEADER pTempSectionHeader
=
(PIMAGE_SECTION_HEADER)pTempBuffer;
/
/
读取节内容
for
(ULONG32 uCount
=
0
; uCount < pe.NtHeaders.FileHeader.NumberOfSections; uCount
+
+
)
{
pTempBuffer
=
(PVOID)((DWORD_PTR)pNewBuffer
+
pTempSectionHeader
-
>VirtualAddress);
fileOffset.QuadPart
=
pTempSectionHeader
-
>PointerToRawData;
ntStatus
=
ZwReadFile(hFile, NULL, NULL, NULL, &ioStatusBlock, pTempBuffer, pTempSectionHeader
-
>SizeOfRawData, &fileOffset, NULL);
if
(!NT_SUCCESS(ntStatus))
{
KdPrint((
"ZwReadFile错误:%x\n"
, ntStatus));
pNewBuffer
=
nullptr;
goto exit;
}
pTempSectionHeader
+
+
;
}
exit:
if
(hFile) ZwClose(hFile);
/
/
if
(pNewBuffer) ExFreePool(pNewBuffer);
return
pNewBuffer;
}
/
/
修复重定位表
VOID RepirRelocTable(IN DWORD_PTR uNewModule,IN DWORD_PTR uOldModule)
{
UNREFERENCED_PARAMETER(uOldModule);
PIMAGE_DOS_HEADER pDosHeader
=
NULL;
PIMAGE_NT_HEADERS pNtHeaders
=
NULL;
PIMAGE_BASE_RELOCATION pRelocation
=
NULL;
PIMAGE_DATA_DIRECTORY pData
=
NULL;
pDosHeader
=
(PIMAGE_DOS_HEADER)uNewModule;
pNtHeaders
=
(PIMAGE_NT_HEADERS)((DWORD_PTR)pDosHeader
+
pDosHeader
-
>e_lfanew);
pData
=
pNtHeaders
-
>OptionalHeader.DataDirectory;
/
/
定位重定位表
pRelocation
=
(PIMAGE_BASE_RELOCATION)((DWORD_PTR)uNewModule
+
pData[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
/
/
由于新的内核里面的全局变量地址都是用的老的 所以要加上它们之间的偏移量 就等于我们新的内核全局变量地址
DWORD_PTR uOffset
=
uNewModule
-
pNtHeaders
-
>OptionalHeader.ImageBase;
/
/
需要改正的偏移
while
(pRelocation
-
>VirtualAddress !
=
0
&& pRelocation
-
>SizeOfBlock !
=
0
&& pRelocation
-
>VirtualAddress !
=
01
)
{
LONG32 uNumOfRelocs
=
(pRelocation
-
>SizeOfBlock
-
8
)
/
2
;
/
/
取得重定位数量
PUSHORT pUShort
=
(PUSHORT)((DWORD_PTR)pRelocation
+
8
);
for
(DWORD_PTR uCount
=
0
; uCount < uNumOfRelocs; uCount
+
+
, pUShort
+
+
)
{
if
(((
*
pUShort) >>
12
)
=
=
IMAGE_REL_BASED_DIR64)
{
PULONG64 pUlong32
=
(PULONG64)(((
*
pUShort) &
0x0FFF
)
+
pRelocation
-
>VirtualAddress
+
uNewModule);
*
pUlong32
+
=
uOffset;
/
/
改好数据写入目的地址
}
}
pRelocation
=
(PIMAGE_BASE_RELOCATION)((DWORD_PTR)pRelocation
+
pRelocation
-
>SizeOfBlock);
}
}
/
/
修复新的系统服务表
NTSTATUS RepirSSDT(IN PDRIVER_OBJECT pDriver, IN ULONG64 pNewKernelBuffer, IN ULONG64 uOldModule)
{
ULONG64 g_uOffset
=
pNewKernelBuffer
-
uOldModule;
PVOID szAddr
=
nullptr;
NTSTATUS status
=
GetSSDT(pDriver, &szAddr);
if
(!NT_SUCCESS(status))
{
DbgPrintEx(
77
,
0
,
"GetSSDT Faile!\n"
);
return
STATUS_UNSUCCESSFUL;
}
PSYSTEM_SERVICE_TABLE m_pOldSSDT
=
{
0
};
m_pOldSSDT
=
(PSYSTEM_SERVICE_TABLE)szAddr;
PSYSTEM_SERVICE_TABLE m_pNewSSDT
=
(PSYSTEM_SERVICE_TABLE)((ULONGLONG)m_pOldSSDT
+
g_uOffset);
m_pNewSSDT
-
>numberofServices
=
m_pOldSSDT
-
>numberofServices;
ULONG64 m_uOffset
=
(ULONG64)m_pOldSSDT
-
>serviceTableBase
-
uOldModule;
m_pNewSSDT
-
>serviceTableBase
=
(PULONG32)(pNewKernelBuffer
+
m_uOffset);
m_uOffset
=
((ULONGLONG)m_pOldSSDT
-
>serviceCounterTableBase
-
uOldModule);
m_pNewSSDT
-
>serviceCounterTableBase
=
(PULONG32)(pNewKernelBuffer
+
m_uOffset);
m_uOffset
=
((ULONGLONG)m_pOldSSDT
-
>paramTableBase
-
uOldModule);
m_pNewSSDT
-
>paramTableBase
=
(PCHAR)(pNewKernelBuffer
+
m_uOffset);
RtlCopyMemory((PULONGLONG)m_pNewSSDT
-
>paramTableBase, (PULONGLONG)m_pOldSSDT
-
>paramTableBase, (ULONG64)m_pNewSSDT
-
>numberofServices);
/
/
复制参数
m_uOffset
=
(ULONG64)m_pNewSSDT
-
>serviceTableBase
-
pNewKernelBuffer;
/
/
计算ssdt表中函数地址 注:win10 ssdt表中函数地址为:高
28
位为偏移 低
4
位为参数个数
-
4
不足
4
个参数时为零
for
(ULONG32 uCount
=
0
; uCount < m_pNewSSDT
-
>numberofServices; uCount
+
+
)
{
((PULONG32)(UCHAR
*
)(m_pNewSSDT
-
>serviceTableBase))[uCount]
=
(ULONG32)((((PULONG32)(UCHAR
*
)(m_pNewSSDT
-
>serviceTableBase))[uCount]
-
m_uOffset) <<
4
)
+
(((CHAR)((UCHAR
*
)(m_pNewSSDT
-
>paramTableBase))[uCount]) >>
2
);
}
return
STATUS_SUCCESS;
}
NTSTATUS GetSSDT(IN PDRIVER_OBJECT pdriver, OUT PVOID
*
addr)
/
/
通过链表找到ssdt
{
PLDR_DATA_TABLE_ENTRY entry
=
(PLDR_DATA_TABLE_ENTRY)pdriver
-
>DriverSection;
PLDR_DATA_TABLE_ENTRY head
=
entry;
UNICODE_STRING temp
=
{
0
};
RtlInitUnicodeString(&temp, L
"ntoskrnl.exe"
);
PCHAR start
=
NULL;
ULONG size
=
0
;
do
{
/
/
通过链表找到ntoskrnl.exe 内核文件。
if
(RtlCompareUnicodeString(&temp, &entry
-
>BaseDllName, TRUE)
=
=
NULL)
{
/
/
DbgPrintEx(DPFLTR_IHVDRIVER_ID,
0
,
"%wZ\n"
, &entry
-
>BaseDllName);
start
=
(PCHAR)entry
-
>DllBase;
size
=
entry
-
>SizeOfImage;
break
;
}
entry
=
(PLDR_DATA_TABLE_ENTRY)entry
-
>InLoadOrderLinks.Flink;
}
while
(entry !
=
head);
for
(ULONG i
=
0
; i < size; i
+
+
)
{
if
(MmIsAddressValid(start))
{
if
(
*
start
=
=
(CHAR)
0x4c
&&
*
(CHAR
*
)(start
+
1
)
=
=
(CHAR)
0x8d
&&
*
(CHAR
*
)(start
+
2
)
=
=
(CHAR)
0x15
)
/
/
注:必需强制转换字符串类型
{
start
+
=
7
;
if
(MmIsAddressValid(start))
{
if
(
*
start
=
=
(CHAR)
0x4c
&&
*
(CHAR
*
)(start
+
1
)
=
=
(CHAR)
0x8d
&&
*
(CHAR
*
)(start
+
2
)
=
=
(CHAR)
0x1d
)
{
*
(PULONGLONG)addr
=
*
(PULONG)(start
-
4
)
+
(ULONGLONG)start;
return
STATUS_SUCCESS;
}
}
}
}
if
(MmIsAddressValid(start))
{
start
+
+
;
}
}
return
STATUS_UNSUCCESSFUL;
}
|
更多【 x86内核重载改写成x64内核重载】相关视频教程:www.yxfzedu.com