Repository navigation
Expand file tree
/
Copy pathkdmapper.cpp
More file actions
215 lines (165 loc) · 7.65 KB
/
Copy pathkdmapper.cpp
File metadata and controls
215 lines (165 loc) · 7.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#include "kdmapper.hpp"
uint64_t kdmapper::AllocMdlMemory(HANDLE iqvw64e_device_handle, uint64_t size, uint64_t* mdlPtr) {
/*added by psec*/
LARGE_INTEGER LowAddress, HighAddress;
LowAddress.QuadPart = 0;
HighAddress.QuadPart = 0xffff'ffff'ffff'ffffULL;
uint64_t pages = (size / PAGE_SIZE) + 1;
auto mdl = intel_driver::MmAllocatePagesForMdl(iqvw64e_device_handle, LowAddress, HighAddress, LowAddress, pages * (uint64_t)PAGE_SIZE);
if (!mdl) {
Log(L"[-] Can't allocate pages for mdl" << std::endl);
return { 0 };
}
uint32_t byteCount = 0;
if (!intel_driver::ReadMemory(iqvw64e_device_handle, mdl + 0x028 /*_MDL : byteCount*/, &byteCount, sizeof(uint32_t))) {
Log(L"[-] Can't read the _MDL : byteCount" << std::endl);
return { 0 };
}
if (byteCount < size) {
Log(L"[-] Couldn't allocate enough memory, cleaning up" << std::endl);
intel_driver::MmFreePagesFromMdl(iqvw64e_device_handle, mdl);
intel_driver::FreePool(iqvw64e_device_handle, mdl);
return { 0 };
}
auto mappingStartAddress = intel_driver::MmMapLockedPagesSpecifyCache(iqvw64e_device_handle, mdl, nt::KernelMode, nt::MmCached, NULL, FALSE, nt::NormalPagePriority);
if (!mappingStartAddress) {
Log(L"[-] Can't set mdl pages cache, cleaning up." << std::endl);
intel_driver::MmFreePagesFromMdl(iqvw64e_device_handle, mdl);
intel_driver::FreePool(iqvw64e_device_handle, mdl);
return { 0 };
}
const auto result = intel_driver::MmProtectMdlSystemAddress(iqvw64e_device_handle, mdl, PAGE_EXECUTE_READWRITE);
if (!result) {
Log(L"[-] Can't change protection for mdl pages, cleaning up" << std::endl);
intel_driver::MmUnmapLockedPages(iqvw64e_device_handle, mappingStartAddress, mdl);
intel_driver::MmFreePagesFromMdl(iqvw64e_device_handle, mdl);
intel_driver::FreePool(iqvw64e_device_handle, mdl);
return { 0 };
}
Log(L"[+] Allocated pages for mdl" << std::endl);
if (mdlPtr)
*mdlPtr = mdl;
return mappingStartAddress;
}
uint64_t kdmapper::MapDriver(PIMAGE_NT_HEADERS nt_headers, HANDLE iqvw64e_device_handle, BYTE* data, ULONG64 param1, ULONG64 param2, bool free, bool destroyHeader, bool mdlMode, bool PassAllocationAddressAsFirstParam, mapCallback callback, NTSTATUS* exitCode) {
// const PIMAGE_NT_HEADERS64 nt_headers = portable_executable::GetNtHeaders(data);
if (!nt_headers) {
Log(L"[-] Invalid format of PE image" << std::endl);
return 0;
}
uint32_t image_size = nt_headers->OptionalHeader.SizeOfImage;
void* local_image_base = VirtualAlloc(nullptr, image_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (!local_image_base)
return 0;
DWORD TotalVirtualHeaderSize = (IMAGE_FIRST_SECTION(nt_headers))->VirtualAddress;
image_size = image_size - (destroyHeader ? TotalVirtualHeaderSize : 0);
uint64_t kernel_image_base = 0;
uint64_t mdlptr = 0;
if (mdlMode) {
kernel_image_base = AllocMdlMemory(iqvw64e_device_handle, image_size, &mdlptr);
}
else {
kernel_image_base = intel_driver::AllocatePool(iqvw64e_device_handle, nt::POOL_TYPE::NonPagedPool, image_size);
}
do {
if (!kernel_image_base) {
Log(L"[-] Failed to allocate remote image in kernel" << std::endl);
break;
}
Log(L"[+] Image base has been allocated at 0x" << reinterpret_cast<void*>(kernel_image_base) << std::endl);
// Copy image headers
memcpy(local_image_base, data, nt_headers->OptionalHeader.SizeOfHeaders);
// Copy image sections
const PIMAGE_SECTION_HEADER current_image_section = IMAGE_FIRST_SECTION(nt_headers);
for (auto i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i) {
auto local_section = reinterpret_cast<void*>(reinterpret_cast<uint64_t>(local_image_base) + current_image_section[i].VirtualAddress);
memcpy(local_section, reinterpret_cast<void*>(reinterpret_cast<uint64_t>(data) + current_image_section[i].PointerToRawData), current_image_section[i].SizeOfRawData);
}
uint64_t realBase = kernel_image_base;
if (destroyHeader) {
kernel_image_base -= TotalVirtualHeaderSize;
Log(L"[+] Skipped 0x" << std::hex << TotalVirtualHeaderSize << L" bytes of PE Header" << std::endl);
}
// Resolve relocs and imports
RelocateImageByDelta(portable_executable::GetRelocs(local_image_base), kernel_image_base - nt_headers->OptionalHeader.ImageBase);
if (!ResolveImports(iqvw64e_device_handle, portable_executable::GetImports(local_image_base))) {
Log(L"[-] Failed to resolve imports" << std::endl);
kernel_image_base = realBase;
break;
}
// Write fixed image to kernel
if (!intel_driver::WriteMemory(iqvw64e_device_handle, realBase, (PVOID)((uintptr_t)local_image_base + (destroyHeader ? TotalVirtualHeaderSize : 0)), image_size)) {
Log(L"[-] Failed to write local image to remote image" << std::endl);
kernel_image_base = realBase;
break;
}
// Call driver entry point
const uint64_t address_of_entry_point = kernel_image_base + nt_headers->OptionalHeader.AddressOfEntryPoint;
Log(L"[<] Calling DriverEntry 0x" << reinterpret_cast<void*>(address_of_entry_point) << std::endl);
if (callback) {
if (!callback(¶m1, ¶m2, realBase, image_size, mdlptr)) {
Log(L"[-] Callback returns false, failed!" << std::endl);
kernel_image_base = realBase;
break;
}
}
//NTSTATUS status = 0;
//if (!intel_driver::CallKernelFunction(iqvw64e_device_handle, &status, address_of_entry_point, (PassAllocationAddressAsFirstParam ? realBase : param1), param2)) {
// Log(L"[-] Failed to call driver entry" << std::endl);
// kernel_image_base = realBase;
// break;
//}
uintptr_t status = 0;
if (!intel_driver::CallKernelFunction(iqvw64e_device_handle, &status, address_of_entry_point, param1, param2))
{
Log(L"[-] Failed to call driver entry" << std::endl);
kernel_image_base = realBase;
break;
}
if (exitCode)
*exitCode = status;
Log(L"[+] DriverEntry returned 0x" << std::hex << status << std::endl);
VirtualFree(local_image_base, 0, MEM_RELEASE);
return status;
} while (false);
VirtualFree(local_image_base, 0, MEM_RELEASE);
return 0;
}
void kdmapper::RelocateImageByDelta(portable_executable::vec_relocs relocs, const uint64_t delta) {
for (const auto& current_reloc : relocs) {
for (auto i = 0u; i < current_reloc.count; ++i) {
const uint16_t type = current_reloc.item[i] >> 12;
const uint16_t offset = current_reloc.item[i] & 0xFFF;
if (type == IMAGE_REL_BASED_DIR64)
*reinterpret_cast<uint64_t*>(current_reloc.address + offset) += delta;
}
}
}
bool kdmapper::ResolveImports(HANDLE iqvw64e_device_handle, portable_executable::vec_imports imports) {
for (const auto& current_import : imports) {
ULONG64 Module = utils::GetKernelModuleAddress(current_import.module_name);
if (!Module) {
#if !defined(DISABLE_OUTPUT)
std::cout << "[-] Dependency " << current_import.module_name << " wasn't found" << std::endl;
#endif
return false;
}
for (auto& current_function_data : current_import.function_datas) {
uint64_t function_address = intel_driver::GetKernelModuleExport(iqvw64e_device_handle, Module, current_function_data.name);
if (!function_address) {
//Lets try with ntoskrnl
if (Module != intel_driver::ntoskrnlAddr) {
function_address = intel_driver::GetKernelModuleExport(iqvw64e_device_handle, intel_driver::ntoskrnlAddr, current_function_data.name);
if (!function_address) {
#if !defined(DISABLE_OUTPUT)
std::cout << "[-] Failed to resolve import " << current_function_data.name << " (" << current_import.module_name << ")" << std::endl;
#endif
return false;
}
}
}
*current_function_data.address = function_address;
}
}
return true;
}