Tue, Apr 14, 2020 9:02:29 PM
This commit is contained in:
266
client/efi-mapper/kdmapper/efi_driver.cpp
Normal file
266
client/efi-mapper/kdmapper/efi_driver.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
#include "efi_driver.hpp"
|
||||
|
||||
NTSTATUS efi_driver::SetSystemEnvironmentPrivilege(BOOLEAN Enable, PBOOLEAN WasEnabled)
|
||||
{
|
||||
if (WasEnabled != nullptr)
|
||||
*WasEnabled = FALSE;
|
||||
|
||||
BOOLEAN SeSystemEnvironmentWasEnabled;
|
||||
const NTSTATUS Status = nt::RtlAdjustPrivilege(SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
|
||||
Enable,
|
||||
FALSE,
|
||||
&SeSystemEnvironmentWasEnabled);
|
||||
|
||||
if (NT_SUCCESS(Status) && WasEnabled != nullptr)
|
||||
*WasEnabled = SeSystemEnvironmentWasEnabled;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
GUID DummyGuid
|
||||
= { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } };
|
||||
void efi_driver::SendCommand(MemoryCommand* cmd)
|
||||
{
|
||||
UNICODE_STRING VariableName = RTL_CONSTANT_STRING(VARIABLE_NAME);
|
||||
nt::NtSetSystemEnvironmentValueEx(&VariableName,
|
||||
&DummyGuid,
|
||||
cmd,
|
||||
sizeof(MemoryCommand),
|
||||
ATTRIBUTES);
|
||||
}
|
||||
|
||||
bool efi_driver::Init()
|
||||
{
|
||||
BOOLEAN SeSystemEnvironmentWasEnabled;
|
||||
NTSTATUS status = SetSystemEnvironmentPrivilege(true, &SeSystemEnvironmentWasEnabled);
|
||||
return NT_SUCCESS(status);
|
||||
}
|
||||
|
||||
bool efi_driver::MemCopy(HANDLE device_handle, uint64_t destination, uint64_t source, uint64_t size)
|
||||
{
|
||||
MemoryCommand* cmd = new MemoryCommand();
|
||||
cmd->operation = 0;
|
||||
cmd->magic = COMMAND_MAGIC;
|
||||
cmd->data1 = destination;
|
||||
cmd->data2 = source;
|
||||
cmd->size = (int)size;
|
||||
|
||||
SendCommand(cmd);
|
||||
|
||||
return true; // yolo
|
||||
}
|
||||
|
||||
bool efi_driver::SetMemory(HANDLE device_handle, uint64_t address, uint32_t value, uint64_t size)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
MemCopy(device_handle, address + i, (uintptr_t)&value, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool efi_driver::ReadMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size)
|
||||
{
|
||||
return MemCopy(device_handle, reinterpret_cast<uint64_t>(buffer), address, size);
|
||||
}
|
||||
|
||||
bool efi_driver::WriteMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size)
|
||||
{
|
||||
return MemCopy(device_handle, address, reinterpret_cast<uint64_t>(buffer), size);
|
||||
}
|
||||
|
||||
uint64_t efi_driver::AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type, uint64_t size)
|
||||
{
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
static uint64_t kernel_ExAllocatePool = 0;
|
||||
|
||||
if (!kernel_ExAllocatePool)
|
||||
kernel_ExAllocatePool = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExAllocatePool");
|
||||
|
||||
uint64_t allocated_pool = 0;
|
||||
|
||||
if (!CallKernelFunction(device_handle, &allocated_pool, kernel_ExAllocatePool, pool_type, size))
|
||||
return 0;
|
||||
|
||||
return allocated_pool;
|
||||
}
|
||||
|
||||
bool efi_driver::FreePool(HANDLE device_handle, uint64_t address)
|
||||
{
|
||||
if (!address)
|
||||
return 0;
|
||||
|
||||
static uint64_t kernel_ExFreePool = 0;
|
||||
|
||||
if (!kernel_ExFreePool)
|
||||
kernel_ExFreePool = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExFreePool");
|
||||
|
||||
return CallKernelFunction<void>(device_handle, nullptr, kernel_ExFreePool, address);
|
||||
}
|
||||
|
||||
uint64_t efi_driver::GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string & function_name)
|
||||
{
|
||||
if (!kernel_module_base)
|
||||
return 0;
|
||||
|
||||
IMAGE_DOS_HEADER dos_header = { 0 };
|
||||
IMAGE_NT_HEADERS64 nt_headers = { 0 };
|
||||
|
||||
if (!ReadMemory(device_handle, kernel_module_base, &dos_header, sizeof(dos_header)) || dos_header.e_magic != IMAGE_DOS_SIGNATURE ||
|
||||
!ReadMemory(device_handle, kernel_module_base + dos_header.e_lfanew, &nt_headers, sizeof(nt_headers)) || nt_headers.Signature != IMAGE_NT_SIGNATURE)
|
||||
return 0;
|
||||
|
||||
const auto export_base = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
const auto export_base_size = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
|
||||
if (!export_base || !export_base_size)
|
||||
return 0;
|
||||
|
||||
const auto export_data = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(VirtualAlloc(nullptr, export_base_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
||||
|
||||
if (!ReadMemory(device_handle, kernel_module_base + export_base, export_data, export_base_size))
|
||||
{
|
||||
VirtualFree(export_data, 0, MEM_RELEASE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto delta = reinterpret_cast<uint64_t>(export_data) - export_base;
|
||||
|
||||
const auto name_table = reinterpret_cast<uint32_t*>(export_data->AddressOfNames + delta);
|
||||
const auto ordinal_table = reinterpret_cast<uint16_t*>(export_data->AddressOfNameOrdinals + delta);
|
||||
const auto function_table = reinterpret_cast<uint32_t*>(export_data->AddressOfFunctions + delta);
|
||||
|
||||
for (auto i = 0u; i < export_data->NumberOfNames; ++i)
|
||||
{
|
||||
const std::string current_function_name = std::string(reinterpret_cast<char*>(name_table[i] + delta));
|
||||
|
||||
if (!_stricmp(current_function_name.c_str(), function_name.c_str()))
|
||||
{
|
||||
const auto function_ordinal = ordinal_table[i];
|
||||
const auto function_address = kernel_module_base + function_table[function_ordinal];
|
||||
|
||||
if (function_address >= kernel_module_base + export_base && function_address <= kernel_module_base + export_base + export_base_size)
|
||||
{
|
||||
VirtualFree(export_data, 0, MEM_RELEASE);
|
||||
return 0; // No forwarded exports on 64bit?
|
||||
}
|
||||
|
||||
VirtualFree(export_data, 0, MEM_RELEASE);
|
||||
return function_address;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualFree(export_data, 0, MEM_RELEASE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool efi_driver::GetNtGdiDdDDIReclaimAllocations2KernelInfo(HANDLE device_handle, uint64_t * out_kernel_function_ptr, uint64_t * out_kernel_original_function_address)
|
||||
{
|
||||
// 488b05650e1400 mov rax, qword ptr [rip+offset]
|
||||
// ff150f211600 call cs:__guard_dispatch_icall_fptr
|
||||
|
||||
static uint64_t kernel_function_ptr = 0;
|
||||
static uint64_t kernel_original_function_address = 0;
|
||||
|
||||
if (!kernel_function_ptr || !kernel_original_function_address)
|
||||
{
|
||||
const uint64_t kernel_NtGdiDdDDIReclaimAllocations2 = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("win32kbase.sys"), "NtGdiDdDDIReclaimAllocations2");
|
||||
|
||||
if (!kernel_NtGdiDdDDIReclaimAllocations2)
|
||||
{
|
||||
std::cout << "[-] Failed to get export win32kbase.NtGdiDdDDIReclaimAllocations2" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint64_t kernel_function_ptr_offset_address = kernel_NtGdiDdDDIReclaimAllocations2 + 0x7;
|
||||
int32_t function_ptr_offset = 0; // offset is a SIGNED integer
|
||||
|
||||
if (!ReadMemory(device_handle, kernel_function_ptr_offset_address, &function_ptr_offset, sizeof(function_ptr_offset)))
|
||||
return false;
|
||||
|
||||
kernel_function_ptr = kernel_NtGdiDdDDIReclaimAllocations2 + 0xB + function_ptr_offset;
|
||||
|
||||
if (!ReadMemory(device_handle, kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address)))
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_kernel_function_ptr = kernel_function_ptr;
|
||||
*out_kernel_original_function_address = kernel_original_function_address;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool efi_driver::ClearMmUnloadedDrivers(HANDLE device_handle)
|
||||
{
|
||||
ULONG buffer_size = 0;
|
||||
void* buffer = nullptr;
|
||||
|
||||
NTSTATUS status = NtQuerySystemInformation(static_cast<SYSTEM_INFORMATION_CLASS>(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size);
|
||||
|
||||
while (status == nt::STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
|
||||
buffer = VirtualAlloc(nullptr, buffer_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
status = NtQuerySystemInformation(static_cast<SYSTEM_INFORMATION_CLASS>(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t object = 0;
|
||||
|
||||
auto system_handle_inforamtion = static_cast<nt::PSYSTEM_HANDLE_INFORMATION_EX>(buffer);
|
||||
|
||||
for (auto i = 0u; i < system_handle_inforamtion->HandleCount; ++i)
|
||||
{
|
||||
const nt::SYSTEM_HANDLE current_system_handle = system_handle_inforamtion->Handles[i];
|
||||
|
||||
if (current_system_handle.UniqueProcessId != reinterpret_cast<HANDLE>(static_cast<uint64_t>(GetCurrentProcessId())))
|
||||
continue;
|
||||
|
||||
if (current_system_handle.HandleValue == device_handle)
|
||||
{
|
||||
object = reinterpret_cast<uint64_t>(current_system_handle.Object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
|
||||
if (!object)
|
||||
return false;
|
||||
|
||||
uint64_t device_object = 0;
|
||||
|
||||
if (!ReadMemory(device_handle, object + 0x8, &device_object, sizeof(device_object)))
|
||||
return false;
|
||||
|
||||
uint64_t driver_object = 0;
|
||||
|
||||
if (!ReadMemory(device_handle, device_object + 0x8, &driver_object, sizeof(driver_object)))
|
||||
return false;
|
||||
|
||||
uint64_t driver_section = 0;
|
||||
|
||||
if (!ReadMemory(device_handle, driver_object + 0x28, &driver_section, sizeof(driver_section)))
|
||||
return false;
|
||||
|
||||
UNICODE_STRING us_driver_base_dll_name = { 0 };
|
||||
|
||||
if (!ReadMemory(device_handle, driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name)))
|
||||
return false;
|
||||
|
||||
us_driver_base_dll_name.Length = 0;
|
||||
|
||||
if (!WriteMemory(device_handle, driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
113
client/efi-mapper/kdmapper/efi_driver.hpp
Normal file
113
client/efi-mapper/kdmapper/efi_driver.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <atlstr.h>
|
||||
|
||||
#include "service.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace efi_driver
|
||||
{
|
||||
typedef struct _MemoryCommand
|
||||
{
|
||||
int magic;
|
||||
int operation;
|
||||
unsigned long long data1;
|
||||
unsigned long long data2;
|
||||
int size;
|
||||
} MemoryCommand;
|
||||
|
||||
#define VARIABLE_NAME L"yromeMifE" // EfiMemory
|
||||
#define COMMAND_MAGIC 0xDEAD
|
||||
|
||||
#define EFI_VARIABLE_NON_VOLATILE 0x00000001
|
||||
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
|
||||
#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
|
||||
#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
|
||||
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
|
||||
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
|
||||
#define EFI_VARIABLE_APPEND_WRITE 0x00000040
|
||||
#define ATTRIBUTES (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)
|
||||
|
||||
#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE (22L)
|
||||
|
||||
bool Init();
|
||||
NTSTATUS SetSystemEnvironmentPrivilege(BOOLEAN Enable, PBOOLEAN WasEnabled);
|
||||
void SendCommand(MemoryCommand* cmd);
|
||||
|
||||
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 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);
|
||||
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 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
|
||||
|
||||
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 (!WriteMemory(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
|
||||
|
||||
WriteMemory(device_handle, kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
145
client/efi-mapper/kdmapper/kdmapper.cpp
Normal file
145
client/efi-mapper/kdmapper/kdmapper.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
#include "kdmapper.hpp"
|
||||
|
||||
uint64_t kdmapper::MapDriver(HANDLE iqvw64e_device_handle, const std::string& driver_path)
|
||||
{
|
||||
std::vector<uint8_t> raw_image = { 0 };
|
||||
|
||||
if (!utils::ReadFileToMemory(driver_path, &raw_image))
|
||||
{
|
||||
std::cout << "[-] Failed to read image to memory" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const PIMAGE_NT_HEADERS64 nt_headers = portable_executable::GetNtHeaders(raw_image.data());
|
||||
|
||||
if (!nt_headers)
|
||||
{
|
||||
std::cout << "[-] Invalid format of PE image" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
std::cout << "[-] Image is not 64 bit" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t image_size = nt_headers->OptionalHeader.SizeOfImage;
|
||||
|
||||
void* local_image_base = VirtualAlloc(nullptr, image_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
uint64_t kernel_image_base = efi_driver::AllocatePool(iqvw64e_device_handle, nt::NonPagedPool, image_size);
|
||||
|
||||
do
|
||||
{
|
||||
if (!kernel_image_base)
|
||||
{
|
||||
std::cout << "[-] Failed to allocate remote image in kernel" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << "[+] Image base has been allocated at 0x" << reinterpret_cast<void*>(kernel_image_base) << std::endl;
|
||||
|
||||
// Copy image headers
|
||||
|
||||
memcpy(local_image_base, raw_image.data(), nt_headers->OptionalHeader.SizeOfHeaders);
|
||||
|
||||
// Copy image sections
|
||||
|
||||
const PIMAGE_SECTION_HEADER current_image_section = IMAGE_FIRST_SECTION(nt_headers);
|
||||
|
||||
for (auto i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i)
|
||||
{
|
||||
auto local_section = reinterpret_cast<void*>(reinterpret_cast<uint64_t>(local_image_base) + current_image_section[i].VirtualAddress);
|
||||
memcpy(local_section, reinterpret_cast<void*>(reinterpret_cast<uint64_t>(raw_image.data()) + current_image_section[i].PointerToRawData), current_image_section[i].SizeOfRawData);
|
||||
}
|
||||
|
||||
// Resolve relocs and imports
|
||||
|
||||
RelocateImageByDelta(portable_executable::GetRelocs(local_image_base), kernel_image_base - nt_headers->OptionalHeader.ImageBase);
|
||||
|
||||
if (!ResolveImports(iqvw64e_device_handle, portable_executable::GetImports(local_image_base)))
|
||||
{
|
||||
std::cout << "[-] Failed to resolve imports" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// Write fixed image to kernel
|
||||
|
||||
if (!efi_driver::WriteMemory(iqvw64e_device_handle, kernel_image_base, local_image_base, image_size))
|
||||
{
|
||||
std::cout << "[-] Failed to write local image to remote image" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
VirtualFree(local_image_base, 0, MEM_RELEASE);
|
||||
|
||||
// Call driver entry point
|
||||
|
||||
const uint64_t address_of_entry_point = kernel_image_base + nt_headers->OptionalHeader.AddressOfEntryPoint;
|
||||
|
||||
std::cout << "[<] Calling DriverEntry 0x" << reinterpret_cast<void*>(address_of_entry_point) << std::endl;
|
||||
|
||||
NTSTATUS status = 0;
|
||||
|
||||
if (!efi_driver::CallKernelFunction(iqvw64e_device_handle, &status, address_of_entry_point))
|
||||
{
|
||||
std::cout << "[-] Failed to call driver entry" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
std::cout << "[+] DriverEntry returned 0x" << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << status << std::nouppercase << std::dec << std::endl;
|
||||
|
||||
// Erase PE headers
|
||||
|
||||
efi_driver::SetMemory(iqvw64e_device_handle, kernel_image_base, 0, nt_headers->OptionalHeader.SizeOfHeaders);
|
||||
return kernel_image_base;
|
||||
|
||||
} while (false);
|
||||
|
||||
VirtualFree(local_image_base, 0, MEM_RELEASE);
|
||||
efi_driver::FreePool(iqvw64e_device_handle, kernel_image_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kdmapper::RelocateImageByDelta(portable_executable::vec_relocs relocs, const uint64_t delta)
|
||||
{
|
||||
for (const auto& current_reloc : relocs)
|
||||
{
|
||||
for (auto i = 0u; i < current_reloc.count; ++i)
|
||||
{
|
||||
const uint16_t type = current_reloc.item[i] >> 12;
|
||||
const uint16_t offset = current_reloc.item[i] & 0xFFF;
|
||||
|
||||
if (type == IMAGE_REL_BASED_DIR64)
|
||||
* reinterpret_cast<uint64_t*>(current_reloc.address + offset) += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool kdmapper::ResolveImports(HANDLE iqvw64e_device_handle, portable_executable::vec_imports imports)
|
||||
{
|
||||
for (const auto& current_import : imports)
|
||||
{
|
||||
if (!utils::GetKernelModuleAddress(current_import.module_name))
|
||||
{
|
||||
std::cout << "[-] Dependency " << current_import.module_name << " wasn't found" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& current_function_data : current_import.function_datas)
|
||||
{
|
||||
const uint64_t function_address = efi_driver::GetKernelModuleExport(iqvw64e_device_handle, utils::GetKernelModuleAddress(current_import.module_name), current_function_data.name);
|
||||
|
||||
if (!function_address)
|
||||
{
|
||||
std::cout << "[-] Failed to resolve import " << current_function_data.name << " (" << current_import.module_name << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
*current_function_data.address = function_address;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
19
client/efi-mapper/kdmapper/kdmapper.hpp
Normal file
19
client/efi-mapper/kdmapper/kdmapper.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <stdint.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
#include "portable_executable.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "nt.hpp"
|
||||
#include "efi_driver.hpp"
|
||||
|
||||
namespace kdmapper
|
||||
{
|
||||
uint64_t MapDriver(HANDLE iqvw64e_device_handle, const std::string& driver_path);
|
||||
void RelocateImageByDelta(portable_executable::vec_relocs relocs, const uint64_t delta);
|
||||
bool ResolveImports(HANDLE iqvw64e_device_handle, portable_executable::vec_imports imports);
|
||||
}
|
||||
141
client/efi-mapper/kdmapper/kdmapper.vcxproj
Normal file
141
client/efi-mapper/kdmapper/kdmapper.vcxproj
Normal file
@@ -0,0 +1,141 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{518E0636-BA8F-459D-ACAC-81BD33475E3E}</ProjectGuid>
|
||||
<RootNamespace>kdmapper</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<SpectreMitigation>false</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<SpectreMitigation>false</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="efi_driver.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="kdmapper.cpp" />
|
||||
<ClCompile Include="portable_executable.cpp" />
|
||||
<ClCompile Include="service.cpp" />
|
||||
<ClCompile Include="utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="efi_driver.hpp" />
|
||||
<ClInclude Include="kdmapper.hpp" />
|
||||
<ClInclude Include="nt.hpp" />
|
||||
<ClInclude Include="portable_executable.hpp" />
|
||||
<ClInclude Include="service.hpp" />
|
||||
<ClInclude Include="utils.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
35
client/efi-mapper/kdmapper/main.cpp
Normal file
35
client/efi-mapper/kdmapper/main.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "kdmapper.hpp"
|
||||
|
||||
int main(const int argc, char** argv)
|
||||
{
|
||||
if (argc != 2 || std::filesystem::path(argv[1]).extension().string().compare(".sys"))
|
||||
{
|
||||
std::cout << "[-] Incorrect usage" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::string driver_path = argv[1];
|
||||
|
||||
if (!std::filesystem::exists(driver_path))
|
||||
{
|
||||
std::cout << "[-] File " << driver_path << " doesn't exist" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
HANDLE iqvw64e_device_handle = nullptr; // dummy handle because I am lazy piece of shit
|
||||
|
||||
bool status = efi_driver::Init();
|
||||
if (!status)
|
||||
{
|
||||
std::cout << "[-] Failed to init driver" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!kdmapper::MapDriver(iqvw64e_device_handle, driver_path))
|
||||
{
|
||||
std::cout << "[-] Failed to map " << driver_path << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "[+] success" << std::endl;
|
||||
}
|
||||
105
client/efi-mapper/kdmapper/nt.hpp
Normal file
105
client/efi-mapper/kdmapper/nt.hpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <winternl.h>
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
|
||||
namespace nt
|
||||
{
|
||||
constexpr auto PAGE_SIZE = 0x1000;
|
||||
constexpr auto STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
|
||||
|
||||
constexpr auto SystemModuleInformation = 11;
|
||||
constexpr auto SystemHandleInformation = 16;
|
||||
constexpr auto SystemExtendedHandleInformation = 64;
|
||||
|
||||
typedef struct _SYSTEM_HANDLE
|
||||
{
|
||||
PVOID Object;
|
||||
HANDLE UniqueProcessId;
|
||||
HANDLE HandleValue;
|
||||
ULONG GrantedAccess;
|
||||
USHORT CreatorBackTraceIndex;
|
||||
USHORT ObjectTypeIndex;
|
||||
ULONG HandleAttributes;
|
||||
ULONG Reserved;
|
||||
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
|
||||
|
||||
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
|
||||
{
|
||||
ULONG_PTR HandleCount;
|
||||
ULONG_PTR Reserved;
|
||||
SYSTEM_HANDLE Handles[1];
|
||||
} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
|
||||
|
||||
typedef enum _POOL_TYPE {
|
||||
NonPagedPool,
|
||||
NonPagedPoolExecute,
|
||||
PagedPool,
|
||||
NonPagedPoolMustSucceed,
|
||||
DontUseThisType,
|
||||
NonPagedPoolCacheAligned,
|
||||
PagedPoolCacheAligned,
|
||||
NonPagedPoolCacheAlignedMustS,
|
||||
MaxPoolType,
|
||||
NonPagedPoolBase,
|
||||
NonPagedPoolBaseMustSucceed,
|
||||
NonPagedPoolBaseCacheAligned,
|
||||
NonPagedPoolBaseCacheAlignedMustS,
|
||||
NonPagedPoolSession,
|
||||
PagedPoolSession,
|
||||
NonPagedPoolMustSucceedSession,
|
||||
DontUseThisTypeSession,
|
||||
NonPagedPoolCacheAlignedSession,
|
||||
PagedPoolCacheAlignedSession,
|
||||
NonPagedPoolCacheAlignedMustSSession,
|
||||
NonPagedPoolNx,
|
||||
NonPagedPoolNxCacheAligned,
|
||||
NonPagedPoolSessionNx
|
||||
} POOL_TYPE;
|
||||
|
||||
typedef struct _RTL_PROCESS_MODULE_INFORMATION
|
||||
{
|
||||
HANDLE Section;
|
||||
PVOID MappedBase;
|
||||
PVOID ImageBase;
|
||||
ULONG ImageSize;
|
||||
ULONG Flags;
|
||||
USHORT LoadOrderIndex;
|
||||
USHORT InitOrderIndex;
|
||||
USHORT LoadCount;
|
||||
USHORT OffsetToFileName;
|
||||
UCHAR FullPathName[256];
|
||||
} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
|
||||
|
||||
typedef struct _RTL_PROCESS_MODULES
|
||||
{
|
||||
ULONG NumberOfModules;
|
||||
RTL_PROCESS_MODULE_INFORMATION Modules[1];
|
||||
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlAdjustPrivilege(
|
||||
_In_ ULONG Privilege,
|
||||
_In_ BOOLEAN Enable,
|
||||
_In_ BOOLEAN Client,
|
||||
_Out_ PBOOLEAN WasEnabled
|
||||
);
|
||||
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtSetSystemEnvironmentValueEx(
|
||||
_In_ PUNICODE_STRING VariableName,
|
||||
_In_ LPGUID VendorGuid,
|
||||
_In_reads_bytes_opt_(ValueLength) PVOID Value,
|
||||
_In_ ULONG ValueLength,
|
||||
_In_ ULONG Attributes
|
||||
);
|
||||
}
|
||||
|
||||
#define RTL_CONSTANT_STRING(s) { sizeof(s) - sizeof((s)[0]), sizeof(s), (PWSTR)s }
|
||||
}
|
||||
86
client/efi-mapper/kdmapper/portable_executable.cpp
Normal file
86
client/efi-mapper/kdmapper/portable_executable.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "portable_executable.hpp"
|
||||
|
||||
PIMAGE_NT_HEADERS64 portable_executable::GetNtHeaders(void* image_base)
|
||||
{
|
||||
const auto dos_header = reinterpret_cast<PIMAGE_DOS_HEADER>(image_base);
|
||||
|
||||
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return nullptr;
|
||||
|
||||
const auto nt_headers = reinterpret_cast<PIMAGE_NT_HEADERS64>(reinterpret_cast<uint64_t>(image_base) + dos_header->e_lfanew);
|
||||
|
||||
if (nt_headers->Signature != IMAGE_NT_SIGNATURE)
|
||||
return nullptr;
|
||||
|
||||
return nt_headers;
|
||||
}
|
||||
|
||||
portable_executable::vec_relocs portable_executable::GetRelocs(void* image_base)
|
||||
{
|
||||
const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base);
|
||||
|
||||
if (!nt_headers)
|
||||
return {};
|
||||
|
||||
vec_relocs relocs;
|
||||
|
||||
auto current_base_relocation = reinterpret_cast<PIMAGE_BASE_RELOCATION>(reinterpret_cast<uint64_t>(image_base) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
|
||||
const auto reloc_end = reinterpret_cast<uint64_t>(current_base_relocation) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
|
||||
|
||||
while (current_base_relocation->VirtualAddress && current_base_relocation->VirtualAddress < reloc_end && current_base_relocation->SizeOfBlock)
|
||||
{
|
||||
RelocInfo reloc_info;
|
||||
|
||||
reloc_info.address = reinterpret_cast<uint64_t>(image_base) + current_base_relocation->VirtualAddress;
|
||||
reloc_info.item = reinterpret_cast<uint16_t*>(reinterpret_cast<uint64_t>(current_base_relocation) + sizeof(IMAGE_BASE_RELOCATION));
|
||||
reloc_info.count = (current_base_relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(uint16_t);
|
||||
|
||||
relocs.push_back(reloc_info);
|
||||
|
||||
current_base_relocation = reinterpret_cast<PIMAGE_BASE_RELOCATION>(reinterpret_cast<uint64_t>(current_base_relocation) + current_base_relocation->SizeOfBlock);
|
||||
}
|
||||
|
||||
return relocs;
|
||||
}
|
||||
|
||||
portable_executable::vec_imports portable_executable::GetImports(void* image_base)
|
||||
{
|
||||
const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base);
|
||||
|
||||
if (!nt_headers)
|
||||
return {};
|
||||
|
||||
vec_imports imports;
|
||||
|
||||
auto current_import_descriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(reinterpret_cast<uint64_t>(image_base) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
||||
|
||||
while (current_import_descriptor->FirstThunk)
|
||||
{
|
||||
ImportInfo import_info;
|
||||
|
||||
import_info.module_name = std::string(reinterpret_cast<char*>(reinterpret_cast<uint64_t>(image_base) + current_import_descriptor->Name));
|
||||
|
||||
auto current_first_thunk = reinterpret_cast<PIMAGE_THUNK_DATA64>(reinterpret_cast<uint64_t>(image_base) + current_import_descriptor->FirstThunk);
|
||||
auto current_originalFirstThunk = reinterpret_cast<PIMAGE_THUNK_DATA64>(reinterpret_cast<uint64_t>(image_base) + current_import_descriptor->OriginalFirstThunk);
|
||||
|
||||
while (current_originalFirstThunk->u1.Function)
|
||||
{
|
||||
ImportFunctionInfo import_function_data;
|
||||
|
||||
auto thunk_data = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(reinterpret_cast<uint64_t>(image_base) + current_originalFirstThunk->u1.AddressOfData);
|
||||
|
||||
import_function_data.name = thunk_data->Name;
|
||||
import_function_data.address = ¤t_first_thunk->u1.Function;
|
||||
|
||||
import_info.function_datas.push_back(import_function_data);
|
||||
|
||||
++current_originalFirstThunk;
|
||||
++current_first_thunk;
|
||||
}
|
||||
|
||||
imports.push_back(import_info);
|
||||
++current_import_descriptor;
|
||||
}
|
||||
|
||||
return imports;
|
||||
}
|
||||
35
client/efi-mapper/kdmapper/portable_executable.hpp
Normal file
35
client/efi-mapper/kdmapper/portable_executable.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace portable_executable
|
||||
{
|
||||
struct RelocInfo
|
||||
{
|
||||
uint64_t address;
|
||||
uint16_t* item;
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
struct ImportFunctionInfo
|
||||
{
|
||||
std::string name;
|
||||
uint64_t* address;
|
||||
};
|
||||
|
||||
struct ImportInfo
|
||||
{
|
||||
std::string module_name;
|
||||
std::vector<ImportFunctionInfo> function_datas;
|
||||
};
|
||||
|
||||
using vec_sections = std::vector<IMAGE_SECTION_HEADER>;
|
||||
using vec_relocs = std::vector<RelocInfo>;
|
||||
using vec_imports = std::vector<ImportInfo>;
|
||||
|
||||
PIMAGE_NT_HEADERS64 GetNtHeaders(void* image_base);
|
||||
vec_relocs GetRelocs(void* image_base);
|
||||
vec_imports GetImports(void* image_base);
|
||||
}
|
||||
54
client/efi-mapper/kdmapper/service.cpp
Normal file
54
client/efi-mapper/kdmapper/service.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "service.hpp"
|
||||
|
||||
bool service::RegisterAndStart(const std::string& driver_path)
|
||||
{
|
||||
const std::string driver_name = std::filesystem::path(driver_path).filename().string();
|
||||
const SC_HANDLE sc_manager_handle = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE);
|
||||
|
||||
if (!sc_manager_handle)
|
||||
return false;
|
||||
|
||||
SC_HANDLE service_handle = CreateService(sc_manager_handle, driver_name.c_str(), driver_name.c_str(), SERVICE_START | SERVICE_STOP | DELETE, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, driver_path.c_str(), nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
if (!service_handle)
|
||||
{
|
||||
service_handle = OpenService(sc_manager_handle, driver_name.c_str(), SERVICE_START);
|
||||
|
||||
if (!service_handle)
|
||||
{
|
||||
CloseServiceHandle(sc_manager_handle);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool result = StartService(service_handle, 0, nullptr);
|
||||
|
||||
CloseServiceHandle(service_handle);
|
||||
CloseServiceHandle(sc_manager_handle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool service::StopAndRemove(const std::string& driver_name)
|
||||
{
|
||||
const SC_HANDLE sc_manager_handle = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE);
|
||||
|
||||
if (!sc_manager_handle)
|
||||
return false;
|
||||
|
||||
const SC_HANDLE service_handle = OpenService(sc_manager_handle, driver_name.c_str(), SERVICE_STOP | DELETE);
|
||||
|
||||
if (!service_handle)
|
||||
{
|
||||
CloseServiceHandle(sc_manager_handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
SERVICE_STATUS status = { 0 };
|
||||
const bool result = ControlService(service_handle, SERVICE_CONTROL_STOP, &status) && DeleteService(service_handle);
|
||||
|
||||
CloseServiceHandle(service_handle);
|
||||
CloseServiceHandle(sc_manager_handle);
|
||||
|
||||
return result;
|
||||
}
|
||||
10
client/efi-mapper/kdmapper/service.hpp
Normal file
10
client/efi-mapper/kdmapper/service.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
namespace service
|
||||
{
|
||||
bool RegisterAndStart(const std::string& driver_path);
|
||||
bool StopAndRemove(const std::string& driver_name);
|
||||
};
|
||||
68
client/efi-mapper/kdmapper/utils.cpp
Normal file
68
client/efi-mapper/kdmapper/utils.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "utils.hpp"
|
||||
|
||||
bool utils::ReadFileToMemory(const std::string& file_path, std::vector<uint8_t>* out_buffer)
|
||||
{
|
||||
std::ifstream file_ifstream(file_path, std::ios::binary);
|
||||
|
||||
if (!file_ifstream)
|
||||
return false;
|
||||
|
||||
out_buffer->assign((std::istreambuf_iterator<char>(file_ifstream)), std::istreambuf_iterator<char>());
|
||||
file_ifstream.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool utils::CreateFileFromMemory(const std::string& desired_file_path, const char* address, size_t size)
|
||||
{
|
||||
std::ofstream file_ofstream(desired_file_path.c_str(), std::ios_base::out | std::ios_base::binary);
|
||||
|
||||
if (!file_ofstream.write(address, size))
|
||||
{
|
||||
file_ofstream.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
file_ofstream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t utils::GetKernelModuleAddress(const std::string& module_name)
|
||||
{
|
||||
void* buffer = nullptr;
|
||||
DWORD buffer_size = 0;
|
||||
|
||||
NTSTATUS status = NtQuerySystemInformation(static_cast<SYSTEM_INFORMATION_CLASS>(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size);
|
||||
|
||||
while (status == nt::STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
|
||||
buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
status = NtQuerySystemInformation(static_cast<SYSTEM_INFORMATION_CLASS>(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto modules = static_cast<nt::PRTL_PROCESS_MODULES>(buffer);
|
||||
|
||||
for (auto i = 0u; i < modules->NumberOfModules; ++i)
|
||||
{
|
||||
const std::string current_module_name = std::string(reinterpret_cast<char*>(modules->Modules[i].FullPathName) + modules->Modules[i].OffsetToFileName);
|
||||
|
||||
if (!_stricmp(current_module_name.c_str(), module_name.c_str()))
|
||||
{
|
||||
const uint64_t result = reinterpret_cast<uint64_t>(modules->Modules[i].ImageBase);
|
||||
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
return 0;
|
||||
}
|
||||
17
client/efi-mapper/kdmapper/utils.hpp
Normal file
17
client/efi-mapper/kdmapper/utils.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <TlHelp32.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "nt.hpp"
|
||||
|
||||
namespace utils
|
||||
{
|
||||
bool ReadFileToMemory(const std::string& file_path, std::vector<uint8_t>* out_buffer);
|
||||
bool CreateFileFromMemory(const std::string& desired_file_path, const char* address, size_t size);
|
||||
uint64_t GetKernelModuleAddress(const std::string& module_name);
|
||||
}
|
||||
Reference in New Issue
Block a user