diff --git a/client/client/client.sln b/client/client/client.sln deleted file mode 100644 index cdaa340..0000000 --- a/client/client/client.sln +++ /dev/null @@ -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 diff --git a/client/client/client/client.cpp b/client/client/client/client.cpp deleted file mode 100644 index 4c4e06b..0000000 --- a/client/client/client/client.cpp +++ /dev/null @@ -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 -#include -#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; -} diff --git a/client/client/client/driver.h b/client/client/client/driver.h deleted file mode 100644 index 8e44acf..0000000 --- a/client/client/client/driver.h +++ /dev/null @@ -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(buffer), address, size); - } - - void WriteMemory(uint64_t address, void* buffer, uint64_t size) - { - MemCopy(address, reinterpret_cast(buffer), size); - } -} \ No newline at end of file diff --git a/client/client/client/helper.h b/client/client/client/helper.h deleted file mode 100644 index 73e1eac..0000000 --- a/client/client/client/helper.h +++ /dev/null @@ -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(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(&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; - } -} \ No newline at end of file diff --git a/client/client/client/utils.h b/client/client/client/utils.h deleted file mode 100644 index 5dc6c1e..0000000 --- a/client/client/client/utils.h +++ /dev/null @@ -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(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(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size); - } - - if (!NT_SUCCESS(status)) - { - VirtualFree(buffer, 0, MEM_RELEASE); - return 0; - } - - const auto modules = static_cast(buffer); - - for (auto i = 0u; i < modules->NumberOfModules; ++i) - { - const std::string current_module_name = std::string(reinterpret_cast(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(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(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(export_data) - export_base; - - const auto name_table = reinterpret_cast(export_data->AddressOfNames + delta); - const auto ordinal_table = reinterpret_cast(export_data->AddressOfNameOrdinals + delta); - const auto function_table = reinterpret_cast(export_data->AddressOfFunctions + delta); - - for (auto i = 0u; i < export_data->NumberOfNames; ++i) - { - const std::string current_function_name = std::string(reinterpret_cast(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 - bool CallKernelFunction(T* out_result, uint64_t kernel_function_address, const A ...arguments) - { - constexpr auto call_void = std::is_same_v; - - 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(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(NtGdiDdDDIReclaimAllocations2); - - *out_result = Function(arguments...); - } - else - { - using FunctionFn = void(__stdcall*)(A...); - const auto Function = static_cast(NtGdiDdDDIReclaimAllocations2); - - Function(arguments...); - } - - // Restore the pointer - - Driver::WriteMemory(kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address)); - return true; - } -} \ No newline at end of file diff --git a/client/efi-mapper/kdmapper.sln b/client/efi-mapper/kdmapper.sln new file mode 100644 index 0000000..048f2a8 --- /dev/null +++ b/client/efi-mapper/kdmapper.sln @@ -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 diff --git a/client/efi-mapper/kdmapper/efi_driver.cpp b/client/efi-mapper/kdmapper/efi_driver.cpp new file mode 100644 index 0000000..0d31b58 --- /dev/null +++ b/client/efi-mapper/kdmapper/efi_driver.cpp @@ -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(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(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(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(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(export_data) - export_base; + + const auto name_table = reinterpret_cast(export_data->AddressOfNames + delta); + const auto ordinal_table = reinterpret_cast(export_data->AddressOfNameOrdinals + delta); + const auto function_table = reinterpret_cast(export_data->AddressOfFunctions + delta); + + for (auto i = 0u; i < export_data->NumberOfNames; ++i) + { + const std::string current_function_name = std::string(reinterpret_cast(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(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(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(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(static_cast(GetCurrentProcessId()))) + continue; + + if (current_system_handle.HandleValue == device_handle) + { + object = reinterpret_cast(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; +} \ No newline at end of file diff --git a/client/efi-mapper/kdmapper/efi_driver.hpp b/client/efi-mapper/kdmapper/efi_driver.hpp new file mode 100644 index 0000000..9e32232 --- /dev/null +++ b/client/efi-mapper/kdmapper/efi_driver.hpp @@ -0,0 +1,113 @@ +#pragma once +#include +#include +#include +#include +#include + +#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 + bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments) + { + constexpr auto call_void = std::is_same_v; + + 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(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(NtGdiDdDDIReclaimAllocations2); + + *out_result = Function(arguments...); + } + else + { + using FunctionFn = void(__stdcall*)(A...); + const auto Function = static_cast(NtGdiDdDDIReclaimAllocations2); + + Function(arguments...); + } + + // Restore the pointer + + WriteMemory(device_handle, kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address)); + return true; + } +} \ No newline at end of file diff --git a/client/efi-mapper/kdmapper/kdmapper.cpp b/client/efi-mapper/kdmapper/kdmapper.cpp new file mode 100644 index 0000000..efc3f9f --- /dev/null +++ b/client/efi-mapper/kdmapper/kdmapper.cpp @@ -0,0 +1,145 @@ +#include "kdmapper.hpp" + +uint64_t kdmapper::MapDriver(HANDLE iqvw64e_device_handle, const std::string& driver_path) +{ + std::vector 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(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(reinterpret_cast(local_image_base) + current_image_section[i].VirtualAddress); + memcpy(local_section, reinterpret_cast(reinterpret_cast(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(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(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; +} \ No newline at end of file diff --git a/client/efi-mapper/kdmapper/kdmapper.hpp b/client/efi-mapper/kdmapper/kdmapper.hpp new file mode 100644 index 0000000..4874d4e --- /dev/null +++ b/client/efi-mapper/kdmapper/kdmapper.hpp @@ -0,0 +1,19 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +#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); +} \ No newline at end of file diff --git a/client/client/client/client.vcxproj b/client/efi-mapper/kdmapper/kdmapper.vcxproj similarity index 67% rename from client/client/client/client.vcxproj rename to client/efi-mapper/kdmapper/kdmapper.vcxproj index 99b0134..74263bd 100644 --- a/client/client/client/client.vcxproj +++ b/client/efi-mapper/kdmapper/kdmapper.vcxproj @@ -1,5 +1,5 @@ - + Debug @@ -19,10 +19,9 @@ - 16.0 - {73BB66C2-5447-4DA2-8790-E9CE90AF6821} - Win32Proj - client + 15.0 + {518E0636-BA8F-459D-ACAC-81BD33475E3E} + kdmapper 10.0 @@ -30,20 +29,20 @@ Application true v142 - Unicode + MultiByte Application false v142 true - Unicode + MultiByte Application true v142 - Unicode + MultiByte false @@ -51,7 +50,8 @@ false v142 true - Unicode + MultiByte + false @@ -71,93 +71,69 @@ - - true - - - true - $(SolutionDir)build\bin\ - $(SolutionDir)build\int\ - - - false - - - false - + - - Level3 + Disabled true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true - - Console - true - - - - Level3 + Level4 true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp17 + false - - Console - true - ntdll.lib;%(AdditionalDependencies) - - - Level3 + MaxSpeed true true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - Console true true - true - - - Level3 + Level4 + MaxSpeed true true true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + true + stdcpp17 - Console true true - true - + + + + + + - - - - + + + + + + diff --git a/client/efi-mapper/kdmapper/main.cpp b/client/efi-mapper/kdmapper/main.cpp new file mode 100644 index 0000000..982113e --- /dev/null +++ b/client/efi-mapper/kdmapper/main.cpp @@ -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; +} \ No newline at end of file diff --git a/client/client/client/nt.h b/client/efi-mapper/kdmapper/nt.hpp similarity index 74% rename from client/client/client/nt.h rename to client/efi-mapper/kdmapper/nt.hpp index 991c90c..045cda9 100644 --- a/client/client/client/nt.h +++ b/client/efi-mapper/kdmapper/nt.hpp @@ -1,7 +1,6 @@ #pragma once #include #include -#include #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 } } \ No newline at end of file diff --git a/client/efi-mapper/kdmapper/portable_executable.cpp b/client/efi-mapper/kdmapper/portable_executable.cpp new file mode 100644 index 0000000..d705dd3 --- /dev/null +++ b/client/efi-mapper/kdmapper/portable_executable.cpp @@ -0,0 +1,86 @@ +#include "portable_executable.hpp" + +PIMAGE_NT_HEADERS64 portable_executable::GetNtHeaders(void* image_base) +{ + const auto dos_header = reinterpret_cast(image_base); + + if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) + return nullptr; + + const auto nt_headers = reinterpret_cast(reinterpret_cast(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(reinterpret_cast(image_base) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); + const auto reloc_end = reinterpret_cast(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(image_base) + current_base_relocation->VirtualAddress; + reloc_info.item = reinterpret_cast(reinterpret_cast(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(reinterpret_cast(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(reinterpret_cast(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(reinterpret_cast(image_base) + current_import_descriptor->Name)); + + auto current_first_thunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->FirstThunk); + auto current_originalFirstThunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->OriginalFirstThunk); + + while (current_originalFirstThunk->u1.Function) + { + ImportFunctionInfo import_function_data; + + auto thunk_data = reinterpret_cast(reinterpret_cast(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; +} \ No newline at end of file diff --git a/client/efi-mapper/kdmapper/portable_executable.hpp b/client/efi-mapper/kdmapper/portable_executable.hpp new file mode 100644 index 0000000..8aacae6 --- /dev/null +++ b/client/efi-mapper/kdmapper/portable_executable.hpp @@ -0,0 +1,35 @@ +#pragma once +#include +#include +#include +#include + +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 function_datas; + }; + + using vec_sections = std::vector; + using vec_relocs = std::vector; + using vec_imports = std::vector; + + PIMAGE_NT_HEADERS64 GetNtHeaders(void* image_base); + vec_relocs GetRelocs(void* image_base); + vec_imports GetImports(void* image_base); +} \ No newline at end of file diff --git a/client/efi-mapper/kdmapper/service.cpp b/client/efi-mapper/kdmapper/service.cpp new file mode 100644 index 0000000..7a7c4eb --- /dev/null +++ b/client/efi-mapper/kdmapper/service.cpp @@ -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; +} \ No newline at end of file diff --git a/client/efi-mapper/kdmapper/service.hpp b/client/efi-mapper/kdmapper/service.hpp new file mode 100644 index 0000000..e4356a8 --- /dev/null +++ b/client/efi-mapper/kdmapper/service.hpp @@ -0,0 +1,10 @@ +#pragma once +#include +#include +#include + +namespace service +{ + bool RegisterAndStart(const std::string& driver_path); + bool StopAndRemove(const std::string& driver_name); +}; \ No newline at end of file diff --git a/client/efi-mapper/kdmapper/utils.cpp b/client/efi-mapper/kdmapper/utils.cpp new file mode 100644 index 0000000..0295ed8 --- /dev/null +++ b/client/efi-mapper/kdmapper/utils.cpp @@ -0,0 +1,68 @@ +#include "utils.hpp" + +bool utils::ReadFileToMemory(const std::string& file_path, std::vector* out_buffer) +{ + std::ifstream file_ifstream(file_path, std::ios::binary); + + if (!file_ifstream) + return false; + + out_buffer->assign((std::istreambuf_iterator(file_ifstream)), std::istreambuf_iterator()); + 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(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(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size); + } + + if (!NT_SUCCESS(status)) + { + VirtualFree(buffer, 0, MEM_RELEASE); + return 0; + } + + const auto modules = static_cast(buffer); + + for (auto i = 0u; i < modules->NumberOfModules; ++i) + { + const std::string current_module_name = std::string(reinterpret_cast(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(modules->Modules[i].ImageBase); + + VirtualFree(buffer, 0, MEM_RELEASE); + return result; + } + } + + VirtualFree(buffer, 0, MEM_RELEASE); + return 0; +} \ No newline at end of file diff --git a/client/efi-mapper/kdmapper/utils.hpp b/client/efi-mapper/kdmapper/utils.hpp new file mode 100644 index 0000000..fc022df --- /dev/null +++ b/client/efi-mapper/kdmapper/utils.hpp @@ -0,0 +1,17 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +#include "nt.hpp" + +namespace utils +{ + bool ReadFileToMemory(const std::string& file_path, std::vector* out_buffer); + bool CreateFileFromMemory(const std::string& desired_file_path, const char* address, size_t size); + uint64_t GetKernelModuleAddress(const std::string& module_name); +} \ No newline at end of file