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"?>
|
||||
<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">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -19,10 +19,9 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{73BB66C2-5447-4DA2-8790-E9CE90AF6821}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>client</RootNamespace>
|
||||
<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" />
|
||||
@@ -30,20 +29,20 @@
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<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>Unicode</CharacterSet>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<SpectreMitigation>false</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
@@ -51,7 +50,8 @@
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<SpectreMitigation>false</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<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" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<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>
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<TreatWarningAsError>false</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>ntdll.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<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>
|
||||
<ClInclude Include="driver.h" />
|
||||
<ClInclude Include="helper.h" />
|
||||
<ClInclude Include="nt.h" />
|
||||
<ClInclude Include="utils.h" />
|
||||
<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">
|
||||
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
|
||||
#include <Windows.h>
|
||||
#include <winternl.h>
|
||||
#include <Tlhelp32.h>
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
|
||||
namespace nt
|
||||
@@ -12,7 +11,7 @@ namespace nt
|
||||
constexpr auto SystemModuleInformation = 11;
|
||||
constexpr auto SystemHandleInformation = 16;
|
||||
constexpr auto SystemExtendedHandleInformation = 64;
|
||||
|
||||
|
||||
typedef struct _SYSTEM_HANDLE
|
||||
{
|
||||
PVOID Object;
|
||||
@@ -23,14 +22,14 @@ namespace nt
|
||||
USHORT ObjectTypeIndex;
|
||||
ULONG HandleAttributes;
|
||||
ULONG Reserved;
|
||||
} SYSTEM_HANDLE, * PSYSTEM_HANDLE;
|
||||
} 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;
|
||||
} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
|
||||
|
||||
typedef enum _POOL_TYPE {
|
||||
NonPagedPool,
|
||||
@@ -70,37 +69,37 @@ namespace nt
|
||||
USHORT LoadCount;
|
||||
USHORT OffsetToFileName;
|
||||
UCHAR FullPathName[256];
|
||||
} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION;
|
||||
} 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;
|
||||
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
|
||||
|
||||
extern "C"
|
||||
extern "C"
|
||||
{
|
||||
NTSYSAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RtlAdjustPrivilege(
|
||||
_In_ ULONG Privilege,
|
||||
_In_ BOOLEAN Enable,
|
||||
_In_ BOOLEAN Client,
|
||||
_Out_ PBOOLEAN WasEnabled
|
||||
);
|
||||
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
|
||||
);
|
||||
}
|
||||
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