Tue, Apr 14, 2020 9:02:29 PM
This commit is contained in:
@@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio Version 16
|
|
||||||
VisualStudioVersion = 16.0.29728.190
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "client\client.vcxproj", "{73BB66C2-5447-4DA2-8790-E9CE90AF6821}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
Debug|x86 = Debug|x86
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
Release|x86 = Release|x86
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{73BB66C2-5447-4DA2-8790-E9CE90AF6821}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{73BB66C2-5447-4DA2-8790-E9CE90AF6821}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{73BB66C2-5447-4DA2-8790-E9CE90AF6821}.Debug|x86.ActiveCfg = Debug|Win32
|
|
||||||
{73BB66C2-5447-4DA2-8790-E9CE90AF6821}.Debug|x86.Build.0 = Debug|Win32
|
|
||||||
{73BB66C2-5447-4DA2-8790-E9CE90AF6821}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{73BB66C2-5447-4DA2-8790-E9CE90AF6821}.Release|x64.Build.0 = Release|x64
|
|
||||||
{73BB66C2-5447-4DA2-8790-E9CE90AF6821}.Release|x86.ActiveCfg = Release|Win32
|
|
||||||
{73BB66C2-5447-4DA2-8790-E9CE90AF6821}.Release|x86.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {5032EDB2-BA80-44F5-A9C5-E09C36732671}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2020 Samuel Tulach
|
|
||||||
Copyright (c) 2019 z175
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include "nt.h"
|
|
||||||
#include "driver.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "helper.h"
|
|
||||||
|
|
||||||
#define EXPLORER_EXE L"explorer.exe"
|
|
||||||
#define PRINT_HEX(x) std::hex << std::setw(8) << std::setfill('0') << std::uppercase << x << std::nouppercase << std::dec
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
std::cout << "[>] Enabling SE_SYSTEM_ENVIRONMENT_PRIVILEGE..." << std::endl;
|
|
||||||
bool status = Driver::Init();
|
|
||||||
if (!status)
|
|
||||||
{
|
|
||||||
std::cout << "[-] Failed to enable privilege" << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "[>] Testing driver..." << std::endl;
|
|
||||||
status = Driver::Test();
|
|
||||||
if (!status)
|
|
||||||
{
|
|
||||||
std::cout << "[-] Driver test failed" << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "[>] Getting current process PEPROCESS..." << std::endl;
|
|
||||||
uintptr_t current = Helper::GetCurrentProcessKrnl();
|
|
||||||
if (!current)
|
|
||||||
{
|
|
||||||
std::cout << "[-] Failed to get current process" << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
std::cout << "[+] Current PEPROCESS 0x" << PRINT_HEX(current) << std::endl;
|
|
||||||
|
|
||||||
std::cout << "[>] Getting explorer.exe PEPROCESS..." << std::endl;
|
|
||||||
int pid = Utils::Find(EXPLORER_EXE);
|
|
||||||
if (!pid)
|
|
||||||
{
|
|
||||||
std::cout << "[-] Failed to find explorer.exe pid" << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t explorer = 0;
|
|
||||||
Helper::LookupProcess(pid, &explorer);
|
|
||||||
if (!explorer)
|
|
||||||
{
|
|
||||||
std::cout << "[-] Failed to get explorer.exe PEPROCESS" << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
std::cout << "[+] Target PEPROCESS 0x" << PRINT_HEX(explorer) << std::endl;
|
|
||||||
|
|
||||||
std::cout << "[>] Getting process base..." << std::endl;
|
|
||||||
uintptr_t baseaddress = Helper::GetSectionBase(explorer);
|
|
||||||
if (!baseaddress)
|
|
||||||
{
|
|
||||||
std::cout << "[-] Failed to get base address" << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
std::cout << "[+] Explorer.exe base 0x" << PRINT_HEX(baseaddress) << std::endl;
|
|
||||||
|
|
||||||
std::cout << "[>] Reading DOS header..." << std::endl;
|
|
||||||
IMAGE_DOS_HEADER* header = new IMAGE_DOS_HEADER;
|
|
||||||
SIZE_T retsize = 0;
|
|
||||||
NTSTATUS copystatus = Helper::CopyVirtualMemory(explorer, baseaddress, current, (uintptr_t)header, sizeof(IMAGE_DOS_HEADER), 0, &retsize);
|
|
||||||
|
|
||||||
std::cout << "[+] Test read:" << std::endl;
|
|
||||||
std::cout << "\tStatus: 0x" << PRINT_HEX(copystatus) << std::endl;
|
|
||||||
std::cout << "\tRead: 0x" << PRINT_HEX(retsize) << std::endl;
|
|
||||||
std::cout << "\tDOS magic: 0x" << PRINT_HEX(header->e_magic) << std::endl;
|
|
||||||
std::cout << "\tNT offset: 0x" << PRINT_HEX(header->e_lfanew) << std::endl;
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace 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
|
|
||||||
|
|
||||||
GUID DummyGuid
|
|
||||||
= { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } };
|
|
||||||
|
|
||||||
#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)
|
|
||||||
|
|
||||||
NTSTATUS 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SendCommand(MemoryCommand* cmd)
|
|
||||||
{
|
|
||||||
UNICODE_STRING VariableName = RTL_CONSTANT_STRING(VARIABLE_NAME);
|
|
||||||
NTSTATUS status = nt::NtSetSystemEnvironmentValueEx(&VariableName,
|
|
||||||
&DummyGuid,
|
|
||||||
cmd,
|
|
||||||
sizeof(MemoryCommand),
|
|
||||||
ATTRIBUTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Init()
|
|
||||||
{
|
|
||||||
BOOLEAN SeSystemEnvironmentWasEnabled;
|
|
||||||
NTSTATUS status = SetSystemEnvironmentPrivilege(true, &SeSystemEnvironmentWasEnabled);
|
|
||||||
return NT_SUCCESS(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Test()
|
|
||||||
{
|
|
||||||
uintptr_t read = 0;
|
|
||||||
uintptr_t value = 123;
|
|
||||||
|
|
||||||
MemoryCommand* cmd = new MemoryCommand();
|
|
||||||
cmd->operation = 0;
|
|
||||||
cmd->magic = COMMAND_MAGIC;
|
|
||||||
cmd->data1 = (uintptr_t)&read;
|
|
||||||
cmd->data2 = (uintptr_t)&value;
|
|
||||||
cmd->size = sizeof(uintptr_t);
|
|
||||||
|
|
||||||
SendCommand(cmd);
|
|
||||||
|
|
||||||
return (read == 123);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemCopy(uintptr_t destination, uintptr_t source, int size)
|
|
||||||
{
|
|
||||||
MemoryCommand* cmd = new MemoryCommand();
|
|
||||||
cmd->operation = 0;
|
|
||||||
cmd->magic = COMMAND_MAGIC;
|
|
||||||
cmd->data1 = destination;
|
|
||||||
cmd->data2 = source;
|
|
||||||
cmd->size = size;
|
|
||||||
|
|
||||||
SendCommand(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// there is no way for us to check if it succeeed to it's yolooo
|
|
||||||
void ReadMemory(uint64_t address, void* buffer, uint64_t size)
|
|
||||||
{
|
|
||||||
MemCopy(reinterpret_cast<uint64_t>(buffer), address, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteMemory(uint64_t address, void* buffer, uint64_t size)
|
|
||||||
{
|
|
||||||
MemCopy(address, reinterpret_cast<uint64_t>(buffer), size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Helper
|
|
||||||
{
|
|
||||||
uint64_t AllocatePool(nt::POOL_TYPE pool_type, uint64_t size)
|
|
||||||
{
|
|
||||||
if (!size)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
static uint64_t kernel_ExAllocatePool = 0;
|
|
||||||
|
|
||||||
if (!kernel_ExAllocatePool)
|
|
||||||
kernel_ExAllocatePool = Utils::GetKernelModuleExport(Utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExAllocatePool");
|
|
||||||
|
|
||||||
uint64_t allocated_pool = 0;
|
|
||||||
|
|
||||||
if (!Utils::CallKernelFunction(&allocated_pool, kernel_ExAllocatePool, pool_type, size))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return allocated_pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FreePool(uint64_t address)
|
|
||||||
{
|
|
||||||
if (!address)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
static uint64_t kernel_ExFreePool = 0;
|
|
||||||
|
|
||||||
if (!kernel_ExFreePool)
|
|
||||||
kernel_ExFreePool = Utils::GetKernelModuleExport(Utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExFreePool");
|
|
||||||
|
|
||||||
return Utils::CallKernelFunction<void>(nullptr, kernel_ExFreePool, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t GetCurrentProcessKrnl()
|
|
||||||
{
|
|
||||||
static uint64_t kernel_IoGetCurrentProcess = 0;
|
|
||||||
|
|
||||||
if (!kernel_IoGetCurrentProcess)
|
|
||||||
kernel_IoGetCurrentProcess = Utils::GetKernelModuleExport(Utils::GetKernelModuleAddress("ntoskrnl.exe"), "IoGetCurrentProcess");
|
|
||||||
|
|
||||||
uint64_t peprocess = 0;
|
|
||||||
|
|
||||||
if (!Utils::CallKernelFunction<uint64_t>(&peprocess, kernel_IoGetCurrentProcess))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return peprocess;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS LookupProcess(uint32_t pid, uintptr_t* peprocess)
|
|
||||||
{
|
|
||||||
static uint64_t kernel_PsLookupProcessByProcessId = 0;
|
|
||||||
|
|
||||||
if (!kernel_PsLookupProcessByProcessId)
|
|
||||||
kernel_PsLookupProcessByProcessId = Utils::GetKernelModuleExport(Utils::GetKernelModuleAddress("ntoskrnl.exe"), "PsLookupProcessByProcessId");
|
|
||||||
|
|
||||||
NTSTATUS status;
|
|
||||||
|
|
||||||
if (!Utils::CallKernelFunction(&status, kernel_PsLookupProcessByProcessId, pid, peprocess))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t GetSectionBase(uintptr_t peprocess)
|
|
||||||
{
|
|
||||||
if (!peprocess)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
static uint64_t kernel_PsGetProcessSectionBaseAddress = 0;
|
|
||||||
|
|
||||||
if (!kernel_PsGetProcessSectionBaseAddress)
|
|
||||||
kernel_PsGetProcessSectionBaseAddress = Utils::GetKernelModuleExport(Utils::GetKernelModuleAddress("ntoskrnl.exe"), "PsGetProcessSectionBaseAddress");
|
|
||||||
|
|
||||||
uint64_t baseaddr = 0;
|
|
||||||
|
|
||||||
if (!Utils::CallKernelFunction(&baseaddr, kernel_PsGetProcessSectionBaseAddress, peprocess))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return baseaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS CopyVirtualMemory(
|
|
||||||
uintptr_t sourceprocess,
|
|
||||||
uintptr_t sourceaddress,
|
|
||||||
uintptr_t destinationprocess,
|
|
||||||
uintptr_t destinationaddress,
|
|
||||||
SIZE_T size,
|
|
||||||
uint8_t mode,
|
|
||||||
PSIZE_T returnsize)
|
|
||||||
{
|
|
||||||
static uint64_t kernel_MmCopyVirtualMemory = 0;
|
|
||||||
|
|
||||||
if (!kernel_MmCopyVirtualMemory)
|
|
||||||
kernel_MmCopyVirtualMemory = Utils::GetKernelModuleExport(Utils::GetKernelModuleAddress("ntoskrnl.exe"), "MmCopyVirtualMemory");
|
|
||||||
|
|
||||||
NTSTATUS status;
|
|
||||||
|
|
||||||
if (!Utils::CallKernelFunction(&status, kernel_MmCopyVirtualMemory, sourceprocess, sourceaddress, destinationprocess, destinationaddress, size, mode, returnsize))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,215 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Utils
|
|
||||||
{
|
|
||||||
uint32_t Find(const wchar_t* proc)
|
|
||||||
{
|
|
||||||
auto snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
||||||
auto pe = PROCESSENTRY32{ sizeof(PROCESSENTRY32) };
|
|
||||||
|
|
||||||
if (Process32First(snapshot, &pe)) {
|
|
||||||
do {
|
|
||||||
if (wcscmp(proc, pe.szExeFile) == 0) {
|
|
||||||
CloseHandle(snapshot);
|
|
||||||
return pe.th32ProcessID;
|
|
||||||
}
|
|
||||||
} while (Process32Next(snapshot, &pe));
|
|
||||||
}
|
|
||||||
CloseHandle(snapshot);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t GetKernelModuleExport(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 };
|
|
||||||
|
|
||||||
Driver::ReadMemory(kernel_module_base, &dos_header, sizeof(dos_header));
|
|
||||||
|
|
||||||
if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
Driver::ReadMemory(kernel_module_base + dos_header.e_lfanew, &nt_headers, sizeof(nt_headers));
|
|
||||||
|
|
||||||
if (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));
|
|
||||||
|
|
||||||
Driver::ReadMemory(kernel_module_base + export_base, export_data, export_base_size);
|
|
||||||
|
|
||||||
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 GetNtGdiDdDDIReclaimAllocations2KernelInfo(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(GetKernelModuleAddress("win32kbase.sys"), "NtGdiDdDDIReclaimAllocations2");
|
|
||||||
|
|
||||||
if (!kernel_NtGdiDdDDIReclaimAllocations2)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint64_t kernel_function_ptr_offset_address = kernel_NtGdiDdDDIReclaimAllocations2 + 0x7;
|
|
||||||
int32_t function_ptr_offset = 0; // offset is a SIGNED integer
|
|
||||||
|
|
||||||
Driver::ReadMemory(kernel_function_ptr_offset_address, &function_ptr_offset, sizeof(function_ptr_offset));
|
|
||||||
|
|
||||||
kernel_function_ptr = kernel_NtGdiDdDDIReclaimAllocations2 + 0xB + function_ptr_offset;
|
|
||||||
|
|
||||||
Driver::ReadMemory(kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address));
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_kernel_function_ptr = kernel_function_ptr;
|
|
||||||
*out_kernel_original_function_address = kernel_original_function_address;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename ...A>
|
|
||||||
bool CallKernelFunction(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(LoadLibraryA("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(&kernel_function_ptr, &kernel_original_function_address))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Overwrite the pointer with kernel_function_address
|
|
||||||
|
|
||||||
Driver::WriteMemory(kernel_function_ptr, &kernel_function_address, sizeof(kernel_function_address));
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
Driver::WriteMemory(kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
31
client/efi-mapper/kdmapper.sln
Normal file
31
client/efi-mapper/kdmapper.sln
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.28010.2019
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kdmapper", "kdmapper\kdmapper.vcxproj", "{518E0636-BA8F-459D-ACAC-81BD33475E3E}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{518E0636-BA8F-459D-ACAC-81BD33475E3E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{518E0636-BA8F-459D-ACAC-81BD33475E3E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{518E0636-BA8F-459D-ACAC-81BD33475E3E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{518E0636-BA8F-459D-ACAC-81BD33475E3E}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{518E0636-BA8F-459D-ACAC-81BD33475E3E}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{518E0636-BA8F-459D-ACAC-81BD33475E3E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{518E0636-BA8F-459D-ACAC-81BD33475E3E}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{518E0636-BA8F-459D-ACAC-81BD33475E3E}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {83D5D338-2A6D-49D5-B1DF-BDD34FB5CC9F}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
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);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
@@ -19,10 +19,9 @@
|
|||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>16.0</VCProjectVersion>
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
<ProjectGuid>{73BB66C2-5447-4DA2-8790-E9CE90AF6821}</ProjectGuid>
|
<ProjectGuid>{518E0636-BA8F-459D-ACAC-81BD33475E3E}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<RootNamespace>kdmapper</RootNamespace>
|
||||||
<RootNamespace>client</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
@@ -30,20 +29,20 @@
|
|||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
<SpectreMitigation>false</SpectreMitigation>
|
<SpectreMitigation>false</SpectreMitigation>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
@@ -51,7 +50,8 @@
|
|||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v142</PlatformToolset>
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
<SpectreMitigation>false</SpectreMitigation>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
@@ -71,93 +71,69 @@
|
|||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup />
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<OutDir>$(SolutionDir)build\bin\</OutDir>
|
|
||||||
<IntDir>$(SolutionDir)build\int\</IntDir>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PrecompiledHeader>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
|
<TreatWarningAsError>false</TreatWarningAsError>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<AdditionalDependencies>ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PrecompiledHeader>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
</PrecompiledHeader>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="client.cpp" />
|
<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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="driver.h" />
|
<ClInclude Include="efi_driver.hpp" />
|
||||||
<ClInclude Include="helper.h" />
|
<ClInclude Include="kdmapper.hpp" />
|
||||||
<ClInclude Include="nt.h" />
|
<ClInclude Include="nt.hpp" />
|
||||||
<ClInclude Include="utils.h" />
|
<ClInclude Include="portable_executable.hpp" />
|
||||||
|
<ClInclude Include="service.hpp" />
|
||||||
|
<ClInclude Include="utils.hpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
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;
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
#include <Tlhelp32.h>
|
|
||||||
#pragma comment(lib, "ntdll.lib")
|
#pragma comment(lib, "ntdll.lib")
|
||||||
|
|
||||||
namespace nt
|
namespace nt
|
||||||
@@ -12,7 +11,7 @@ namespace nt
|
|||||||
constexpr auto SystemModuleInformation = 11;
|
constexpr auto SystemModuleInformation = 11;
|
||||||
constexpr auto SystemHandleInformation = 16;
|
constexpr auto SystemHandleInformation = 16;
|
||||||
constexpr auto SystemExtendedHandleInformation = 64;
|
constexpr auto SystemExtendedHandleInformation = 64;
|
||||||
|
|
||||||
typedef struct _SYSTEM_HANDLE
|
typedef struct _SYSTEM_HANDLE
|
||||||
{
|
{
|
||||||
PVOID Object;
|
PVOID Object;
|
||||||
@@ -23,14 +22,14 @@ namespace nt
|
|||||||
USHORT ObjectTypeIndex;
|
USHORT ObjectTypeIndex;
|
||||||
ULONG HandleAttributes;
|
ULONG HandleAttributes;
|
||||||
ULONG Reserved;
|
ULONG Reserved;
|
||||||
} SYSTEM_HANDLE, * PSYSTEM_HANDLE;
|
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
|
||||||
|
|
||||||
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
|
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
|
||||||
{
|
{
|
||||||
ULONG_PTR HandleCount;
|
ULONG_PTR HandleCount;
|
||||||
ULONG_PTR Reserved;
|
ULONG_PTR Reserved;
|
||||||
SYSTEM_HANDLE Handles[1];
|
SYSTEM_HANDLE Handles[1];
|
||||||
} SYSTEM_HANDLE_INFORMATION_EX, * PSYSTEM_HANDLE_INFORMATION_EX;
|
} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
|
||||||
|
|
||||||
typedef enum _POOL_TYPE {
|
typedef enum _POOL_TYPE {
|
||||||
NonPagedPool,
|
NonPagedPool,
|
||||||
@@ -70,37 +69,37 @@ namespace nt
|
|||||||
USHORT LoadCount;
|
USHORT LoadCount;
|
||||||
USHORT OffsetToFileName;
|
USHORT OffsetToFileName;
|
||||||
UCHAR FullPathName[256];
|
UCHAR FullPathName[256];
|
||||||
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;
|
} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
|
||||||
|
|
||||||
typedef struct _RTL_PROCESS_MODULES
|
typedef struct _RTL_PROCESS_MODULES
|
||||||
{
|
{
|
||||||
ULONG NumberOfModules;
|
ULONG NumberOfModules;
|
||||||
RTL_PROCESS_MODULE_INFORMATION Modules[1];
|
RTL_PROCESS_MODULE_INFORMATION Modules[1];
|
||||||
} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES;
|
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
NTSYSAPI
|
NTSYSAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
RtlAdjustPrivilege(
|
RtlAdjustPrivilege(
|
||||||
_In_ ULONG Privilege,
|
_In_ ULONG Privilege,
|
||||||
_In_ BOOLEAN Enable,
|
_In_ BOOLEAN Enable,
|
||||||
_In_ BOOLEAN Client,
|
_In_ BOOLEAN Client,
|
||||||
_Out_ PBOOLEAN WasEnabled
|
_Out_ PBOOLEAN WasEnabled
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSYSCALLAPI
|
NTSYSCALLAPI
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
NtSetSystemEnvironmentValueEx(
|
NtSetSystemEnvironmentValueEx(
|
||||||
_In_ PUNICODE_STRING VariableName,
|
_In_ PUNICODE_STRING VariableName,
|
||||||
_In_ LPGUID VendorGuid,
|
_In_ LPGUID VendorGuid,
|
||||||
_In_reads_bytes_opt_(ValueLength) PVOID Value,
|
_In_reads_bytes_opt_(ValueLength) PVOID Value,
|
||||||
_In_ ULONG ValueLength,
|
_In_ ULONG ValueLength,
|
||||||
_In_ ULONG Attributes
|
_In_ ULONG Attributes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RTL_CONSTANT_STRING(s) { sizeof(s) - sizeof((s)[0]), sizeof(s), (PWSTR)s }
|
#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