├── Kernel-DLL-Injector ├── Communication.cpp ├── Communication.hpp ├── Kernel Dll Injector.filters ├── Kernel Dll Injector.sln ├── Kernel Dll Injector.user ├── Kernel Dll Injector.vcxproj ├── Kernel Dll Injector.vcxproj.user ├── Loader.cpp ├── Loader.hpp ├── Mapper.cpp ├── Mapper.hpp ├── MemoryUtils.cpp ├── MemoryUtils.hpp ├── Operation.hpp ├── ProcessUtils.cpp ├── ProcessUtils.hpp ├── driver.hpp ├── intel_driver.cpp ├── intel_driver.hpp ├── intel_driver_resource.hpp ├── kdmapper.cpp ├── kdmapper.hpp ├── lazy_importer.hpp ├── nt.hpp ├── portable_executable.cpp ├── portable_executable.hpp ├── service.cpp ├── service.hpp ├── utils.cpp ├── utils.hpp └── xorstr.hpp ├── README.md ├── example.gif └── test.dll /Kernel-DLL-Injector/Communication.cpp: -------------------------------------------------------------------------------- 1 | #include "Communication.hpp" 2 | 3 | OperationCallback Communication::Init(string moduleName, string exportName) 4 | { 5 | auto hModule = LoadLibraryA(moduleName.c_str()); 6 | 7 | if (!hModule) 8 | { 9 | printf(xor ("[-] Communication init error: Failed to load library.\n")); 10 | return nullptr; 11 | } 12 | 13 | OperationCallback callback = (OperationCallback)GetProcAddress(hModule, exportName.c_str()); 14 | 15 | if (!callback) 16 | { 17 | printf(xor ("[-] Communication init error: Export not found.\n")); 18 | return nullptr; 19 | } 20 | 21 | return callback; 22 | } 23 | 24 | bool Communication::TestOperation(OperationCallback operation) 25 | { 26 | PACKET_BASE packet{}; 27 | 28 | packet.op = TEST; 29 | packet.side = SIDE::SERVER; 30 | packet.magic = 0xBEED0FEA; 31 | 32 | constexpr ULONG firstCall = 1; 33 | 34 | auto veh = AddVectoredExceptionHandler(firstCall, [](PEXCEPTION_POINTERS exceptionHandler) -> LONG 35 | { 36 | auto context = exceptionHandler->ContextRecord; 37 | context->Rip += 8; 38 | 39 | return EXCEPTION_CONTINUE_EXECUTION; 40 | }); 41 | 42 | if (!veh) 43 | return false; 44 | 45 | if (!operation(0x000004, 0x128, packet, 0xBEED0FEA, 0x1, 0x1)) 46 | { 47 | printf(xor ("[+] Test operation failed.\n")); 48 | return false; 49 | } 50 | 51 | if (!RemoveVectoredExceptionHandler(veh)) 52 | return false; 53 | 54 | return packet.client.test.valid; 55 | } 56 | 57 | NTSTATUS Communication::CopyVirtualMemory(OperationCallback operation, ULONGLONG srcPid, uintptr_t srcAddr, ULONGLONG targetPid, uintptr_t targetAddr, SIZE_T size) 58 | { 59 | PACKET_BASE packet{}; 60 | 61 | packet.op = COPY_VIRTUAL_MEMORY; 62 | packet.side = SIDE::SERVER; 63 | packet.magic = 0xBEED0FEA; 64 | 65 | auto& serverRequest = packet.server.copy_virtual_memory; 66 | 67 | serverRequest.sourcePid = srcPid; 68 | serverRequest.sourceAddress = srcAddr; 69 | 70 | serverRequest.targetPid = targetPid; 71 | serverRequest.targetAddress = targetAddr; 72 | 73 | serverRequest.size = size; 74 | 75 | constexpr ULONG firstCall = 1; 76 | 77 | auto veh = AddVectoredExceptionHandler(firstCall, [](PEXCEPTION_POINTERS exceptionHandler) -> LONG 78 | { 79 | auto context = exceptionHandler->ContextRecord; 80 | context->Rip += 8; 81 | 82 | return EXCEPTION_CONTINUE_EXECUTION; 83 | }); 84 | 85 | if (!veh) 86 | return false; 87 | 88 | if (!operation(0x000004, 0x128, packet, 0xBEED0FEA, 0x1, 0x1)) 89 | { 90 | //printf(xor ("[+] Copy virtual memory operation failed.\n")); 91 | return STATUS_INVALID_HANDLE; 92 | } 93 | 94 | if (!RemoveVectoredExceptionHandler(veh)) 95 | return false; 96 | 97 | auto clientRequest = packet.client.copy_virtual_memory; 98 | 99 | return NTSTATUS(clientRequest.size); 100 | } 101 | 102 | uint64_t Communication::GetModuleBaseOperation(OperationCallback operation, ULONGLONG processId, wstring moduleName) 103 | { 104 | PACKET_BASE packet{}; 105 | 106 | packet.op = GET_MODULE_BASE_SIZE; 107 | packet.side = SIDE::SERVER; 108 | packet.magic = 0xBEED0FEA; 109 | 110 | auto& serverRequest = packet.server; 111 | moduleName.copy(serverRequest.get_module.name, moduleName.length()); 112 | 113 | serverRequest.get_module.pid = processId; 114 | 115 | constexpr ULONG firstCall = 1; 116 | 117 | auto veh = AddVectoredExceptionHandler(firstCall, [](PEXCEPTION_POINTERS exceptionHandler) -> LONG 118 | { 119 | auto context = exceptionHandler->ContextRecord; 120 | context->Rip += 8; 121 | 122 | return EXCEPTION_CONTINUE_EXECUTION; 123 | }); 124 | 125 | if (!veh) 126 | return false; 127 | 128 | if (!operation(0x000004, 0x128, packet, 0xBEED0FEA, 0x1, 0x1)) 129 | { 130 | printf(xor ("[+] Get module base operation failed.\n")); 131 | return -1; 132 | } 133 | 134 | if (!RemoveVectoredExceptionHandler(veh)) 135 | return false; 136 | 137 | auto clientRequest = packet.client.get_module; 138 | 139 | return clientRequest.baseAddress; 140 | } 141 | 142 | uint64_t Communication::AllocateVirtualMemory(OperationCallback operation, ULONGLONG targetPid, size_t size, uint32_t allocationType, uint32_t protect, uintptr_t sourceAddress) 143 | { 144 | PACKET_BASE packet{}; 145 | 146 | packet.op = ALLOC_VIRTUAL_MEMORY; 147 | packet.side = SIDE::SERVER; 148 | packet.magic = 0xBEED0FEA; 149 | 150 | auto& serverRequest = packet.server.alloc_virtual_memory; 151 | 152 | serverRequest.targetPid = targetPid; 153 | serverRequest.sourceAddress = sourceAddress; 154 | 155 | serverRequest.allocationType = allocationType; 156 | serverRequest.protect = protect; 157 | 158 | serverRequest.size = size; 159 | serverRequest.code = STATUS_INTERRUPTED; 160 | 161 | constexpr ULONG firstCall = 1; 162 | 163 | auto veh = AddVectoredExceptionHandler(firstCall, [](PEXCEPTION_POINTERS exceptionHandler) -> LONG 164 | { 165 | auto context = exceptionHandler->ContextRecord; 166 | context->Rip += 8; 167 | 168 | return EXCEPTION_CONTINUE_EXECUTION; 169 | }); 170 | 171 | if (!veh) 172 | return false; 173 | 174 | if (!operation(0x000004, 0x128, packet, 0xBEED0FEA, 0x1, 0x1)) 175 | { 176 | printf(xor ("[+] Allocate virtual memory operation failed.\n")); 177 | return -1; 178 | } 179 | 180 | if (!RemoveVectoredExceptionHandler(veh)) 181 | return false; 182 | 183 | auto clientRequest = packet.client.alloc_virtual_memory; 184 | 185 | return clientRequest.targetAddress; 186 | } 187 | 188 | NTSTATUS Communication::ProtectVirtualMemory(OperationCallback operation, ULONGLONG targetPid, size_t size, uint32_t protect, uintptr_t sourceAddress) 189 | { 190 | PACKET_BASE packet{}; 191 | 192 | packet.op = PROTECT_VIRTUAL_MEMORY; 193 | packet.side = SIDE::SERVER; 194 | packet.magic = 0xBEED0FEA; 195 | 196 | auto& serverRequest = packet.server.protect_virtual_memory; 197 | 198 | serverRequest.targetPid = targetPid; 199 | serverRequest.sourceAddress = sourceAddress; 200 | 201 | serverRequest.protect = protect; 202 | 203 | serverRequest.size = size; 204 | serverRequest.code = STATUS_INTERRUPTED; 205 | 206 | constexpr ULONG firstCall = 1; 207 | 208 | auto veh = AddVectoredExceptionHandler(firstCall, [](PEXCEPTION_POINTERS exceptionHandler) -> LONG 209 | { 210 | auto context = exceptionHandler->ContextRecord; 211 | context->Rip += 8; 212 | 213 | return EXCEPTION_CONTINUE_EXECUTION; 214 | }); 215 | 216 | if (!veh) 217 | return false; 218 | 219 | if (!operation(0x000004, 0x128, packet, 0xBEED0FEA, 0x1, 0x1)) 220 | { 221 | printf(xor ("[+] Protect virtual memory operation failed.\n")); 222 | return -1; 223 | } 224 | 225 | if (!RemoveVectoredExceptionHandler(veh)) 226 | return false; 227 | 228 | auto clientRequest = packet.client.protect_virtual_memory; 229 | 230 | protect = clientRequest.protect; 231 | 232 | return NTSTATUS(clientRequest.code); 233 | } 234 | 235 | NTSTATUS Communication::FreeVirtualMemory(OperationCallback operation, ULONGLONG targetPid, uintptr_t address) 236 | { 237 | PACKET_BASE packet{}; 238 | 239 | packet.op = FREE_VIRTUAL_MEMORY; 240 | packet.side = SIDE::SERVER; 241 | packet.magic = 0xBEED0FEA; 242 | 243 | auto& serverRequest = packet.server.free_memory; 244 | 245 | serverRequest.targetPid = targetPid; 246 | serverRequest.address = address; 247 | 248 | serverRequest.code = STATUS_INTERRUPTED; 249 | 250 | constexpr ULONG firstCall = 1; 251 | 252 | auto veh = AddVectoredExceptionHandler(firstCall, [](PEXCEPTION_POINTERS exceptionHandler) -> LONG 253 | { 254 | auto context = exceptionHandler->ContextRecord; 255 | context->Rip += 8; 256 | 257 | return EXCEPTION_CONTINUE_EXECUTION; 258 | }); 259 | 260 | if (!veh) 261 | return false; 262 | 263 | if (!operation(0x000004, 0x128, packet, 0xBEED0FEA, 0x1, 0x1)) 264 | { 265 | printf(xor ("[+] Free virtual memory operation failed.\n")); 266 | return -1; 267 | } 268 | 269 | if (!RemoveVectoredExceptionHandler(veh)) 270 | return false; 271 | 272 | auto clientRequest = packet.client.free_memory; 273 | 274 | return NTSTATUS(clientRequest.code); 275 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Communication.hpp: -------------------------------------------------------------------------------- 1 | #include "Operation.hpp" 2 | 3 | class Communication 4 | { 5 | public: 6 | static OperationCallback Init(string moduleName, string exportName); 7 | 8 | static bool TestOperation(OperationCallback operation); 9 | 10 | static NTSTATUS CopyVirtualMemory(OperationCallback operation, ULONGLONG srcPid, uintptr_t srcAddr, ULONGLONG targetPid, uintptr_t targetAddr, SIZE_T size); 11 | static uint64_t GetModuleBaseOperation(OperationCallback operation, ULONGLONG processId, wstring moduleName); 12 | 13 | static uint64_t AllocateVirtualMemory(OperationCallback operation, ULONGLONG targetPid, size_t size, uint32_t allocationType, uint32_t protect, uintptr_t sourceAddress); 14 | static NTSTATUS ProtectVirtualMemory(OperationCallback operation, ULONGLONG targetPid, size_t size, uint32_t protect, uintptr_t sourceAddress); 15 | static NTSTATUS FreeVirtualMemory(OperationCallback operation, ULONGLONG targetPid, uintptr_t address); 16 | }; -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Kernel Dll Injector.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {61bc51c6-141d-4fc0-af67-58e35cc9d7e3} 6 | 7 | 8 | {b2e55e85-97af-4ae2-a2eb-224b0a13721c} 9 | 10 | 11 | {7dc26e77-57f2-4c44-8604-68c0cd31dede} 12 | 13 | 14 | {505f70e7-fa3e-4d5e-be18-5c5eea44110c} 15 | 16 | 17 | {f8f91e30-ead3-4827-97d9-9fbc5d1e6d6d} 18 | 19 | 20 | 21 | 22 | Core 23 | 24 | 25 | Core 26 | 27 | 28 | Utils 29 | 30 | 31 | Utils 32 | 33 | 34 | Vulnerable 35 | 36 | 37 | Vulnerable\kdshitter 38 | 39 | 40 | Vulnerable\kdshitter 41 | 42 | 43 | Vulnerable\kdshitter 44 | 45 | 46 | Vulnerable\kdshitter 47 | 48 | 49 | Vulnerable\kdshitter 50 | 51 | 52 | 53 | 54 | Core 55 | 56 | 57 | Core 58 | 59 | 60 | Core 61 | 62 | 63 | Utils 64 | 65 | 66 | Utils 67 | 68 | 69 | Utils 70 | 71 | 72 | Vulnerable 73 | 74 | 75 | Vulnerable\driver 76 | 77 | 78 | Vulnerable\kdshitter 79 | 80 | 81 | Vulnerable\kdshitter 82 | 83 | 84 | Vulnerable\kdshitter 85 | 86 | 87 | Vulnerable\kdshitter 88 | 89 | 90 | Vulnerable\kdshitter 91 | 92 | 93 | Vulnerable\kdshitter 94 | 95 | 96 | Vulnerable\kdshitter 97 | 98 | 99 | -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Kernel Dll Injector.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31605.320 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Kernel Dll Injector", "Kernel Dll Injector.vcxproj", "{B8437ACF-518D-4330-A9EB-96F4922CA818}" 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 | {B8437ACF-518D-4330-A9EB-96F4922CA818}.Debug|x64.ActiveCfg = Debug|x64 17 | {B8437ACF-518D-4330-A9EB-96F4922CA818}.Debug|x64.Build.0 = Debug|x64 18 | {B8437ACF-518D-4330-A9EB-96F4922CA818}.Debug|x86.ActiveCfg = Debug|Win32 19 | {B8437ACF-518D-4330-A9EB-96F4922CA818}.Debug|x86.Build.0 = Debug|Win32 20 | {B8437ACF-518D-4330-A9EB-96F4922CA818}.Release|x64.ActiveCfg = Release|x64 21 | {B8437ACF-518D-4330-A9EB-96F4922CA818}.Release|x64.Build.0 = Release|x64 22 | {B8437ACF-518D-4330-A9EB-96F4922CA818}.Release|x86.ActiveCfg = Release|Win32 23 | {B8437ACF-518D-4330-A9EB-96F4922CA818}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {72E3EB4D-A69E-45B8-8551-0268B1CCAB4C} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Kernel Dll Injector.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Kernel Dll Injector.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 | 16.0 23 | Win32Proj 24 | {b8437acf-518d-4330-a9eb-96f4922ca818} 25 | DullTarkov 26 | 10.0 27 | Kernel Dll Injector 28 | 29 | 30 | 31 | Application 32 | true 33 | v142 34 | Unicode 35 | 36 | 37 | Application 38 | false 39 | v142 40 | true 41 | Unicode 42 | 43 | 44 | Application 45 | true 46 | v142 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v142 53 | true 54 | MultiByte 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | true 76 | 77 | 78 | false 79 | 80 | 81 | true 82 | 83 | 84 | false 85 | C:\Program Files %28x86%29\Microsoft DirectX SDK (June 2010)\Include;$(IncludePath) 86 | C:\Program Files %28x86%29\Microsoft DirectX SDK (June 2010)\Lib\x64;$(LibraryPath) 87 | 88 | 89 | 90 | Level3 91 | true 92 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 93 | true 94 | 95 | 96 | Console 97 | true 98 | 99 | 100 | 101 | 102 | Level3 103 | true 104 | true 105 | true 106 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 107 | true 108 | 109 | 110 | Console 111 | true 112 | true 113 | true 114 | 115 | 116 | 117 | 118 | Level3 119 | true 120 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Console 125 | true 126 | 127 | 128 | 129 | 130 | Level3 131 | true 132 | true 133 | true 134 | _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_CRT_SECURE_NO_WARNINGS;JM_XORSTR_DISABLE_AVX_INTRINSICS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 135 | true 136 | MultiThreaded 137 | stdcpp17 138 | stdc17 139 | 140 | 141 | Console 142 | true 143 | true 144 | false 145 | RequireAdministrator 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 | -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Kernel Dll Injector.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Loader.cpp: -------------------------------------------------------------------------------- 1 | #include "MemoryUtils.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define Exit Sleep(1800); TerminateProcess(GetCurrentProcess(), 0) 10 | 11 | #define NT_SUCCESS(x) ((x) >= 0) 12 | #define INJECTED 2 13 | 14 | MemoryUtils* memoryUtils = nullptr; 15 | 16 | uint8_t* raw_data = 0; 17 | size_t data_size = 0; 18 | 19 | std::map imports; 20 | 21 | VOID DriverInit() 22 | { 23 | if (!Mapper::MapDriver()) 24 | { 25 | printf(xor ("[-] Failed to load driver.\n")); 26 | Exit; 27 | } 28 | } 29 | 30 | BOOL LoadLocalImage(const char* path) 31 | { 32 | std::ifstream file(path, std::ios::binary | std::ios::ate); 33 | 34 | if (!file) 35 | { 36 | printf(xor ("[-] Dll not found.\n")); 37 | return FALSE; 38 | } 39 | 40 | std::ifstream::pos_type pos{ file.tellg() }; 41 | 42 | data_size = pos; 43 | raw_data = new uint8_t[data_size]; 44 | 45 | if (!raw_data) 46 | return FALSE; 47 | 48 | file.seekg(0, std::ios::beg); 49 | file.read((char*)raw_data, data_size); 50 | 51 | file.close(); 52 | 53 | return TRUE; 54 | } 55 | 56 | PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(uint64_t rva, PIMAGE_NT_HEADERS nt_header) 57 | { 58 | PIMAGE_SECTION_HEADER section{ IMAGE_FIRST_SECTION(nt_header) }; 59 | 60 | for (int i = 0; i < nt_header->FileHeader.NumberOfSections; i++, section++) 61 | { 62 | uint64_t size{ section->Misc.VirtualSize }; 63 | 64 | if (!size) 65 | size = section->SizeOfRawData; 66 | 67 | if ((rva >= section->VirtualAddress) && (rva < (section->VirtualAddress + size))) 68 | return section; 69 | } 70 | 71 | return 0; 72 | } 73 | 74 | uint64_t* GetPtrFromRVA(uint64_t rva, IMAGE_NT_HEADERS* nt_header, uint8_t* image_base) 75 | { 76 | PIMAGE_SECTION_HEADER section_header{ GetEnclosingSectionHeader(rva, nt_header) }; 77 | 78 | if (!section_header) 79 | return 0; 80 | 81 | int64_t delta{ (int64_t)(section_header->VirtualAddress - section_header->PointerToRawData) }; 82 | 83 | return (uint64_t*)(image_base + rva - delta); 84 | } 85 | 86 | std::wstring AnsiToWstring(const std::string& input, DWORD locale = CP_UTF8) 87 | { 88 | wchar_t buf[8192] = { 0 }; 89 | MultiByteToWideChar(locale, 0, input.c_str(), (int)input.length(), buf, ARRAYSIZE(buf)); 90 | return buf; 91 | } 92 | 93 | /*uint64_t GetFuncAddress(const char* module_name, const char* func) 94 | { 95 | std::wstring module_name_utf = AnsiToWstring(string(module_name)); 96 | 97 | uint64_t remote_module{ memoryUtils->GetModuleBase(module_name_utf) }; 98 | 99 | if (!remote_module) 100 | { 101 | printf(xor ("[+] Failed to get module base from: %ws\n"), module_name_utf.c_str()); 102 | Exit; 103 | } 104 | 105 | uint64_t local_module{ (uint64_t)GetModuleHandleA(module_name) }; 106 | 107 | if (!local_module) 108 | { 109 | printf(xor ("[+] Failed to get module handle from: %s\n"), module_name); 110 | Exit; 111 | } 112 | 113 | uint64_t delta{ remote_module - local_module }; 114 | 115 | return ((uint64_t)GetProcAddress((HMODULE)local_module, func) + delta); 116 | }*/ 117 | 118 | BYTE RemoteLoaderWorkerCode[] = 119 | { 120 | 0x48, 0x83, 0xEC, 0x38, 0x48, 0xB8, 0x00, 0x00, 121 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x89, 122 | 0x44, 0x24, 0x20, 0x48, 0x8B, 0x44, 0x24, 0x20, 123 | 0x83, 0x38, 0x00, 0x75, 0x3D, 0x48, 0x8B, 0x44, 124 | 0x24, 0x20, 0xC7, 0x00, 0x01, 0x00, 0x00, 0x00, 125 | 0x48, 0x8B, 0x44, 0x24, 0x20, 0x48, 0x8B, 0x40, 126 | 0x08, 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x8B, 127 | 0x44, 0x24, 0x20, 0x48, 0x83, 0xC0, 0x18, 0x48, 128 | 0x8B, 0xC8, 0xFF, 0x54, 0x24, 0x28, 0x48, 0x8B, 129 | 0x4C, 0x24, 0x20, 0x48, 0x89, 0x41, 0x10, 0x48, 130 | 0x8B, 0x44, 0x24, 0x20, 0xC7, 0x00, 0x02, 0x00, 131 | 0x00, 0x00, 0x48, 0x83, 0xC4, 0x38, 0xC3, 0xCC 132 | }; 133 | 134 | typedef struct _REMOTE_LOADER 135 | { 136 | int32_t Status; 137 | uintptr_t LoadLibraryFunc; 138 | uintptr_t OutModuleBase; 139 | char ModuleName[80]; 140 | } REMOTE_LOADER; 141 | 142 | uintptr_t LoadRemoteLibrary(const char* moduleName, DWORD threadId) 143 | { 144 | uintptr_t moduleBase = 0; 145 | 146 | HMODULE hNtdll = LoadLibraryW(xor (L"ntdll.dll")); 147 | 148 | DWORD workerCodeSize = sizeof(RemoteLoaderWorkerCode) + sizeof(REMOTE_LOADER); 149 | PVOID localCode = VirtualAlloc(NULL, workerCodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 150 | 151 | RtlCopyMemory(localCode, &RemoteLoaderWorkerCode, sizeof(RemoteLoaderWorkerCode)); 152 | 153 | uint64_t workerBase = memoryUtils->AllocateMemory(4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 154 | 155 | uintptr_t workerCode = (uintptr_t)workerBase + sizeof(RemoteLoaderWorkerCode); 156 | *(uintptr_t*)((uintptr_t)localCode + 0x6) = workerCode; 157 | 158 | REMOTE_LOADER* remoteLoader = (REMOTE_LOADER*)((uintptr_t)localCode + sizeof(RemoteLoaderWorkerCode)); 159 | 160 | remoteLoader->LoadLibraryFunc = (uintptr_t)LoadLibraryA; 161 | strcpy_s(remoteLoader->ModuleName, 80, moduleName); 162 | 163 | memoryUtils->WriteMemory(workerBase, (uintptr_t)localCode, workerCodeSize); 164 | 165 | // EAC CAN SEE THIS (FLAG etc.) @_@ 166 | HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)workerBase, hNtdll, threadId); 167 | // 168 | 169 | while (remoteLoader->Status != INJECTED) 170 | { 171 | PostThreadMessage(threadId, WM_NULL, 0, 0); 172 | memoryUtils->ReadBuffer(workerCode, (PVOID)remoteLoader, sizeof(REMOTE_LOADER)); 173 | Sleep(10); 174 | } 175 | 176 | moduleBase = remoteLoader->OutModuleBase; 177 | 178 | UnhookWindowsHookEx(hHook); 179 | 180 | NTSTATUS status = memoryUtils->FreeMemory(workerBase); 181 | 182 | if (!NT_SUCCESS(status)) 183 | { 184 | printf(xor ("\n[-] Failed to free memory. Error: %p\n"), status); 185 | Exit; 186 | } 187 | 188 | VirtualFree(remoteLoader, 0, MEM_RELEASE); 189 | 190 | return moduleBase; 191 | } 192 | uint64_t GetRemoteProcAddress(const char* moduleName, const char* function) 193 | { 194 | HMODULE hModule = LoadLibraryExA(moduleName, NULL, DONT_RESOLVE_DLL_REFERENCES); 195 | 196 | if (!hModule) 197 | { 198 | printf(xor ("\n[-] Failed to load %s.\n"), moduleName); 199 | return 0; 200 | } 201 | 202 | uint64_t delta = (uint64_t)GetProcAddress(hModule, function); 203 | delta -= (uint64_t)hModule; 204 | 205 | FreeLibrary(hModule); 206 | 207 | return delta; 208 | } 209 | 210 | void SolveImports(PIMAGE_NT_HEADERS pNtHeader, uint8_t* localImage, DWORD threadId) 211 | { 212 | auto importTable = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; 213 | 214 | if (!importTable.VirtualAddress || !importTable.Size) 215 | return; 216 | 217 | auto pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)GetPtrFromRVA((uint64_t)(importTable.VirtualAddress), pNtHeader, localImage); 218 | 219 | char* moduleName; 220 | while ((moduleName = (char*)GetPtrFromRVA((uint64_t)(pImportDescriptor->Name), pNtHeader, localImage))) 221 | { 222 | uintptr_t remoteBase; 223 | remoteBase = LoadRemoteLibrary(moduleName, threadId); 224 | 225 | if (!remoteBase) 226 | { 227 | printf(xor ("\n[-] Failed to get remote %s base.\n"), moduleName); 228 | return; 229 | } 230 | 231 | auto pImageThunkData = (PIMAGE_THUNK_DATA)GetPtrFromRVA((DWORD64)(pImportDescriptor->FirstThunk), pNtHeader, localImage); 232 | 233 | while (pImageThunkData->u1.AddressOfData) 234 | { 235 | if (pImageThunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG) 236 | { 237 | pImageThunkData->u1.Function = remoteBase + GetRemoteProcAddress(moduleName, (LPCSTR)(pImageThunkData->u1.Ordinal & 0xFFFF)); 238 | } 239 | else 240 | { 241 | IMAGE_IMPORT_BY_NAME* iibn = (IMAGE_IMPORT_BY_NAME*)GetPtrFromRVA((DWORD64)(pImageThunkData->u1.AddressOfData), pNtHeader, localImage); 242 | 243 | pImageThunkData->u1.Function = remoteBase + GetRemoteProcAddress(moduleName, (LPCSTR)iibn->Name); 244 | } 245 | 246 | pImageThunkData++; 247 | } 248 | pImportDescriptor++; 249 | } 250 | } 251 | 252 | void SolveRelocations(uint64_t base, uint64_t relocation_base, IMAGE_NT_HEADERS* nt_header) 253 | { 254 | struct reloc_entry 255 | { 256 | ULONG to_rva; 257 | ULONG size; 258 | struct 259 | { 260 | WORD offset : 12; 261 | WORD type : 4; 262 | } item[1]; 263 | }; 264 | 265 | uintptr_t delta_offset = (uintptr_t)relocation_base - nt_header->OptionalHeader.ImageBase; 266 | 267 | if (!delta_offset) 268 | return; 269 | 270 | reloc_entry* reloc_ent = (reloc_entry*)GetPtrFromRVA((uint64_t)(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress), nt_header, (PBYTE)base); 271 | uintptr_t reloc_end = (uintptr_t)reloc_ent + nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 272 | 273 | if (reloc_ent == nullptr) 274 | return; 275 | 276 | while ((uintptr_t)reloc_ent < reloc_end && reloc_ent->size) 277 | { 278 | DWORD records_count = (reloc_ent->size - 8) >> 1; 279 | 280 | for (DWORD i = 0; i < records_count; i++) 281 | { 282 | WORD fix_type = (reloc_ent->item[i].type); 283 | WORD shift_delta = (reloc_ent->item[i].offset) % 4096; 284 | 285 | if (fix_type == IMAGE_REL_BASED_ABSOLUTE) 286 | continue; 287 | 288 | if (fix_type == IMAGE_REL_BASED_HIGHLOW || fix_type == IMAGE_REL_BASED_DIR64) 289 | { 290 | uintptr_t fix_va = (uintptr_t)GetPtrFromRVA((uint64_t)(reloc_ent->to_rva), nt_header, (PBYTE)base); 291 | 292 | if (!fix_va) 293 | fix_va = (uintptr_t)base; 294 | 295 | *(uintptr_t*)(fix_va + shift_delta) += delta_offset; 296 | } 297 | } 298 | 299 | reloc_ent = (reloc_entry*)((LPBYTE)reloc_ent + reloc_ent->size); 300 | } 301 | } 302 | 303 | void MapSections(uint64_t base, IMAGE_NT_HEADERS* nt_header) 304 | { 305 | auto header{ IMAGE_FIRST_SECTION(nt_header) }; 306 | size_t virtual_size{ 0 }; 307 | size_t bytes{ 0 }; 308 | 309 | while (nt_header->FileHeader.NumberOfSections && (bytes < nt_header->OptionalHeader.SizeOfImage)) 310 | { 311 | memoryUtils->WriteMemory(base + header->VirtualAddress, (uintptr_t)(raw_data + header->PointerToRawData), header->SizeOfRawData); 312 | 313 | virtual_size = header->VirtualAddress; 314 | virtual_size = (++header)->VirtualAddress - virtual_size; 315 | 316 | bytes += virtual_size; 317 | } 318 | 319 | return; 320 | } 321 | 322 | BOOL ParseImports(uint64_t moduleBase) 323 | { 324 | auto dos_header{ memoryUtils->Read< IMAGE_DOS_HEADER >(moduleBase) }; 325 | auto nt_headers{ memoryUtils->Read< IMAGE_NT_HEADERS >(moduleBase + dos_header.e_lfanew) }; 326 | auto descriptor{ memoryUtils->Read< IMAGE_IMPORT_DESCRIPTOR >(moduleBase + nt_headers.OptionalHeader.DataDirectory[1].VirtualAddress) }; 327 | 328 | int descriptor_count{ 0 }; 329 | int thunk_count{ 0 }; 330 | 331 | while (descriptor.Name) 332 | { 333 | auto first_thunk{ memoryUtils->Read< IMAGE_THUNK_DATA >(moduleBase + descriptor.FirstThunk) }; 334 | auto original_first_thunk{ memoryUtils->Read< IMAGE_THUNK_DATA >(moduleBase + descriptor.OriginalFirstThunk) }; 335 | thunk_count = 0; 336 | 337 | while (original_first_thunk.u1.AddressOfData) 338 | { 339 | char name[256]; 340 | memoryUtils->ReadBuffer(moduleBase + original_first_thunk.u1.AddressOfData + 0x2, (LPVOID)name, 256); 341 | 342 | std::string str_name(name); 343 | auto thunk_offset{ thunk_count * sizeof(uintptr_t) }; 344 | 345 | if (str_name.length() > 0) 346 | imports[str_name] = moduleBase + descriptor.FirstThunk + thunk_offset; 347 | 348 | ++thunk_count; 349 | first_thunk = memoryUtils->Read< IMAGE_THUNK_DATA >(moduleBase + descriptor.FirstThunk + sizeof(IMAGE_THUNK_DATA) * thunk_count); 350 | original_first_thunk = memoryUtils->Read< IMAGE_THUNK_DATA >(moduleBase + descriptor.OriginalFirstThunk + sizeof(IMAGE_THUNK_DATA) * thunk_count); 351 | } 352 | 353 | ++descriptor_count; 354 | descriptor = memoryUtils->Read< IMAGE_IMPORT_DESCRIPTOR >(moduleBase + nt_headers.OptionalHeader.DataDirectory[1].VirtualAddress + sizeof(IMAGE_IMPORT_DESCRIPTOR) * descriptor_count); 355 | } 356 | 357 | return (imports.size() > 0); 358 | } 359 | 360 | DWORD GetProcessInformationByWindow(LPCSTR WindowName, PDWORD pThreadId) 361 | { 362 | DWORD processId = 0; 363 | 364 | while (!processId) 365 | { 366 | HWND hwnd = FindWindowA(NULL, WindowName); 367 | 368 | if (hwnd) 369 | *pThreadId = GetWindowThreadProcessId(hwnd, &processId); 370 | 371 | Sleep(100); 372 | } 373 | 374 | return processId; 375 | } 376 | 377 | int main() 378 | { 379 | setlocale(0, ""); 380 | 381 | printf(xor ("[+] Initializing operation callback...\n")); 382 | 383 | OperationCallback operation = Communication::Init(xor ("win32u"), xor ("NtGdiEngCreatePalette")); 384 | 385 | if (!operation) 386 | { 387 | printf(xor ("[+] Failed to init operation callback")); 388 | Exit; 389 | } 390 | 391 | printf(xor ("[+] Success!\n\n")); 392 | 393 | bool status = Communication::TestOperation(operation); 394 | 395 | if (!status) 396 | { 397 | printf(xor ("[-] Driver not loaded.\n")); 398 | Mapper::MapDriver(); 399 | } 400 | else 401 | { 402 | printf(xor ("[+] Driver loaded!\n")); 403 | } 404 | 405 | Sleep(1200); 406 | 407 | DWORD threadId; 408 | DWORD processId = GetProcessInformationByWindow(xor ("WINDOW NAME"), &threadId); // WRITE WINDOW NAME for proccess <------ 409 | 410 | if (processId == 0 && threadId == 0) 411 | { 412 | for (;; Sleep(100)) 413 | { 414 | processId = GetProcessInformationByWindow(xor ("WINDOW NAME"), &threadId); // WRITE WINDOW NAME for proccesss <------ 415 | 416 | if (processId != 0 && threadId != 0) 417 | break; 418 | } 419 | } 420 | 421 | cout << xor ("\n[+] Injecting..."); 422 | 423 | memoryUtils = new MemoryUtils(operation, processId); 424 | 425 | string current_path = std::filesystem::current_path().string(); 426 | string image_path = current_path + xor ("\\test.dll"); // WRITE DLL PATH <------ 427 | 428 | if (!(LoadLocalImage(image_path.c_str()))) 429 | { 430 | Exit; 431 | } 432 | 433 | if (!raw_data) 434 | { 435 | printf(xor ("[-] Image buffer is empty.")); 436 | Exit; 437 | } 438 | 439 | uint8_t dll_stub[] = { "\x51\x52\x55\x56\x53\x57\x41\x50\x41\x51\x41\x52\x41\x53\x41\x54\x41\x55\x41\x56\x41\x57\x48\xB8\xFF\x00\xDE\xAD\xBE\xEF\x00\xFF\x48\xBA\xFF\x00\xDE\xAD\xC0\xDE\x00\xFF\x48\x89\x10\x48\x31\xC0\x48\x31\xD2\x48\x83\xEC\x28\x48\xB9\xDE\xAD\xBE\xEF\xDE\xAD\xBE\xEF\x48\x31\xD2\x48\x83\xC2\x01\x48\xB8\xDE\xAD\xC0\xDE\xDE\xAD\xC0\xDE\xFF\xD0\x48\x83\xC4\x28\x41\x5F\x41\x5E\x41\x5D\x41\x5C\x41\x5B\x41\x5A\x41\x59\x41\x58\x5F\x5B\x5E\x5D\x5A\x59\x48\x31\xC0\xC3" }; 440 | 441 | IMAGE_DOS_HEADER* dos_header{ (IMAGE_DOS_HEADER*)raw_data }; 442 | 443 | if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) 444 | { 445 | printf(xor ("[-] Invalid PE.")); 446 | Exit; 447 | } 448 | 449 | IMAGE_NT_HEADERS* nt_header{ (IMAGE_NT_HEADERS*)(&raw_data[dos_header->e_lfanew]) }; 450 | 451 | if (nt_header->Signature != IMAGE_NT_SIGNATURE) 452 | { 453 | printf(xor ("[-] Invalid NT header.")); 454 | Exit; 455 | } 456 | 457 | uint64_t base{ memoryUtils->AllocateMemory(nt_header->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE) }; 458 | 459 | if (!base) 460 | { 461 | printf(xor ("[-] Failed to allocate memory for local image.")); 462 | Exit; 463 | } 464 | 465 | printf(xor ("\n[+] Local image base: %p\n"), base); 466 | 467 | uint64_t stub_base{ memoryUtils->AllocateMemory(sizeof(dll_stub), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE) }; 468 | 469 | if (!stub_base) 470 | { 471 | printf(xor ("[-] Failed to allocate memory for shellcode.")); 472 | Exit; 473 | } 474 | 475 | printf(xor ("[Injector] Shellcode base: %p\n\n"), stub_base); 476 | 477 | 478 | PIMAGE_BASE_RELOCATION base_relocation{ (PIMAGE_BASE_RELOCATION)GetPtrFromRVA( 479 | nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, 480 | nt_header, 481 | raw_data) }; 482 | if (nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) 483 | { 484 | printf(xor ("[+] Fixing relocations...\n")); 485 | 486 | SolveRelocations((uint64_t)raw_data, base, nt_header); 487 | } 488 | 489 | SolveImports(nt_header, raw_data, threadId); 490 | 491 | uint64_t ProcessBase = memoryUtils->GetModuleBase(L"user32.dll"); 492 | 493 | if (!ProcessBase) 494 | { 495 | printf(xor ("\n[-] Failed to get process base.")); 496 | Exit; 497 | } 498 | 499 | printf(xor ("[Injector] Parsing imports...\n")); 500 | 501 | if (!ParseImports(ProcessBase)) 502 | { 503 | printf(xor ("\n[-] Failed to parse imports.")); 504 | Exit; 505 | } 506 | 507 | uint64_t iat_function_ptr{ imports[xor ("NtUserGetForegroundWindow")] }; 508 | 509 | if (!iat_function_ptr) 510 | { 511 | printf(xor ("[-] Target import not found.")); 512 | Exit; 513 | } 514 | 515 | uint64_t orginal_function_addr{ memoryUtils->Read(iat_function_ptr) }; 516 | 517 | printf(xor ("\n[+] IAT pointer: %p\n"), iat_function_ptr); 518 | 519 | *(uint64_t*)(dll_stub + 0x18) = iat_function_ptr; 520 | *(uint64_t*)(dll_stub + 0x22) = orginal_function_addr; 521 | 522 | memoryUtils->WriteMemory(base, (uintptr_t)raw_data, nt_header->FileHeader.SizeOfOptionalHeader + sizeof(nt_header->FileHeader) + sizeof(nt_header->Signature)); 523 | 524 | printf(xor ("\n[+] Mapping sections...\n")); 525 | 526 | MapSections(base, nt_header); 527 | 528 | uint64_t entry_point{ (uint64_t)base + nt_header->OptionalHeader.AddressOfEntryPoint }; 529 | 530 | *(uint64_t*)(dll_stub + 0x39) = (uint64_t)base; 531 | *(uint64_t*)(dll_stub + 0x4A) = entry_point; 532 | 533 | printf(xor ("\n[+] Entry Point: %p\n"), entry_point); 534 | 535 | memoryUtils->WriteMemory(stub_base, (uintptr_t)dll_stub, sizeof(dll_stub)); 536 | memoryUtils->ProtectMemory(iat_function_ptr, sizeof(uint64_t), PAGE_READWRITE); 537 | memoryUtils->WriteMemory(iat_function_ptr, (uintptr_t)&stub_base, sizeof(uint64_t)); 538 | 539 | Sleep(3000); 540 | 541 | if (iat_function_ptr != NULL) 542 | { 543 | memoryUtils->ProtectMemory(iat_function_ptr, sizeof(uint64_t), PAGE_READONLY); 544 | 545 | delete[] raw_data; 546 | 547 | printf(xor ("\n[+] Done!")); 548 | 549 | Sleep(1500); 550 | } 551 | 552 | return EXIT_SUCCESS; 553 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Loader.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "xorstr.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Mapper.cpp: -------------------------------------------------------------------------------- 1 | #include "Mapper.hpp" 2 | #include "kdmapper.hpp" 3 | 4 | #define Close (Sleep)(1800); TerminateProcess(GetCurrentProcess(), 0) 5 | 6 | HANDLE iqvw64e_device_handle; 7 | 8 | LONG WINAPI SimplestCrashHandler(EXCEPTION_POINTERS* ExceptionInfo) 9 | { 10 | std::cout << xor ("[!!] Crash at addr 0x") << ExceptionInfo->ExceptionRecord->ExceptionAddress << xor (" by 0x") << std::hex << ExceptionInfo->ExceptionRecord->ExceptionCode << std::endl; 11 | 12 | if (iqvw64e_device_handle) 13 | intel_driver::Unload(iqvw64e_device_handle); 14 | 15 | return EXCEPTION_EXECUTE_HANDLER; 16 | } 17 | 18 | BOOL Mapper::MapDriver() 19 | { 20 | SetUnhandledExceptionFilter(SimplestCrashHandler); 21 | 22 | srand((unsigned)time(NULL) * GetCurrentThreadId()); 23 | 24 | if (intel_driver::IsRunning()) 25 | { 26 | std::cout << xor ("\n[-] Driver is already in use.") << std::endl; 27 | Close; 28 | } 29 | 30 | iqvw64e_device_handle = intel_driver::Load(); 31 | 32 | if (!iqvw64e_device_handle || iqvw64e_device_handle == INVALID_HANDLE_VALUE) 33 | { 34 | std::cout << xor ("\n[-] Failed to load driver.") << std::endl; 35 | intel_driver::Unload(iqvw64e_device_handle); 36 | Close; 37 | } 38 | 39 | if (!intel_driver::ClearPiDDBCacheTable(iqvw64e_device_handle)) { 40 | std::cout << xor ("\n[-] Failed to Clean traces #1") << std::endl; 41 | intel_driver::Unload(iqvw64e_device_handle); 42 | Close; 43 | } 44 | 45 | if (!intel_driver::ClearKernelHashBucketList(iqvw64e_device_handle)) { 46 | std::cout << xor ("\n[-] Failed to Clean traces #2") << std::endl; 47 | Close; 48 | } 49 | 50 | if (!intel_driver::ClearMmUnloadedDrivers(iqvw64e_device_handle)) { 51 | std::cout << xor ("\n[-] Failed to Clean traces #3") << std::endl; 52 | Close; 53 | } 54 | 55 | if (!kdmapper::MapDriver(iqvw64e_device_handle)) 56 | { 57 | std::cout << xor ("\n[-] Failed to map driver.") << std::endl; 58 | intel_driver::Unload(iqvw64e_device_handle); 59 | Close; 60 | } 61 | 62 | intel_driver::Unload(iqvw64e_device_handle); 63 | std::cout << xor ("\n[+] driver mapped!") << std::endl; 64 | 65 | return TRUE; 66 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Mapper.hpp: -------------------------------------------------------------------------------- 1 | #include "Communication.hpp" 2 | 3 | class Mapper 4 | { 5 | public: 6 | static BOOL MapDriver(); 7 | }; -------------------------------------------------------------------------------- /Kernel-DLL-Injector/MemoryUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "MemoryUtils.hpp" 2 | 3 | MemoryUtils::MemoryUtils(OperationCallback operation, uint64_t pid) 4 | { 5 | operationCallback = operation; 6 | processId = pid; 7 | } 8 | 9 | NTSTATUS MemoryUtils::ReadBuffer(uint64_t address, LPVOID lpBuffer, SIZE_T nSize) 10 | { 11 | if (lpBuffer == 0) 12 | return STATUS_INVALID_PARAMETER; 13 | 14 | return Communication::CopyVirtualMemory(operationCallback, processId, address, GetCurrentProcessId(), uintptr_t(lpBuffer), nSize); 15 | } 16 | 17 | NTSTATUS MemoryUtils::WriteMemory(uint64_t address, uintptr_t dstAddress, SIZE_T nSize) 18 | { 19 | if (dstAddress == 0) 20 | return STATUS_INVALID_PARAMETER; 21 | 22 | return Communication::CopyVirtualMemory(operationCallback, GetCurrentProcessId(), dstAddress, processId, address, nSize); 23 | } 24 | 25 | uint64_t MemoryUtils::ReadChain(uint64_t base, const std::vector& offsets) 26 | { 27 | uint64_t result = Read(base + offsets.at(0)); 28 | 29 | for (int i = 1; i < offsets.size(); i++) 30 | result = Read(result + offsets.at(i)); 31 | 32 | return result; 33 | } 34 | 35 | uint64_t MemoryUtils::GetModuleBase(wstring moduleName) 36 | { 37 | return Communication::GetModuleBaseOperation(operationCallback, processId, moduleName); 38 | } 39 | 40 | string MemoryUtils::GetUnicodeString(uint64_t address, int strLength) 41 | { 42 | char16_t wcharTmp[64] = { '\0' }; 43 | ReadBuffer(address, wcharTmp, strLength * 2); 44 | 45 | std::string utfStr = std::wstring_convert, char16_t>{}.to_bytes(wcharTmp); 46 | 47 | return utfStr; 48 | } 49 | 50 | uint64_t MemoryUtils::AllocateMemory(size_t size, uint32_t allocation_type, uint32_t protect) 51 | { 52 | uint64_t address = 0; 53 | return Communication::AllocateVirtualMemory(operationCallback, processId, size, allocation_type, protect, address); 54 | } 55 | 56 | NTSTATUS MemoryUtils::ProtectMemory(uint64_t address, size_t size, uint32_t protect) 57 | { 58 | return Communication::ProtectVirtualMemory(operationCallback, processId, size, protect, address); 59 | } 60 | 61 | NTSTATUS MemoryUtils::FreeMemory(uint64_t address) 62 | { 63 | return Communication::FreeVirtualMemory(operationCallback, processId, address); 64 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/MemoryUtils.hpp: -------------------------------------------------------------------------------- 1 | #include "ProcessUtils.hpp" 2 | 3 | class MemoryUtils 4 | { 5 | public: 6 | MemoryUtils(OperationCallback operation, uint64_t pid); 7 | 8 | NTSTATUS ReadBuffer(uint64_t address, LPVOID lpBuffer, SIZE_T nSize); 9 | NTSTATUS WriteMemory(uint64_t address, uintptr_t dstAddress, SIZE_T nSize); 10 | 11 | template 12 | T Read(uint64_t address); 13 | 14 | uint64_t ReadChain(uint64_t base, const std::vector& offsets); 15 | 16 | uint64_t GetModuleBase(wstring moduleName); 17 | 18 | string GetUnicodeString(uint64_t address, int strLength); 19 | 20 | uint64_t AllocateMemory(size_t size, uint32_t allocation_type, uint32_t protect); 21 | NTSTATUS ProtectMemory(uint64_t address, size_t size, uint32_t protect); 22 | NTSTATUS FreeMemory(uint64_t address); 23 | 24 | private: 25 | OperationCallback operationCallback; 26 | 27 | uint64_t processId = 0; 28 | }; 29 | 30 | template 31 | inline T MemoryUtils::Read(uint64_t address) 32 | { 33 | T buffer{ }; 34 | ReadBuffer(address, &buffer, sizeof(T)); 35 | return buffer; 36 | } 37 | 38 | extern MemoryUtils* memoryUtils; -------------------------------------------------------------------------------- /Kernel-DLL-Injector/Operation.hpp: -------------------------------------------------------------------------------- 1 | #include "Loader.hpp" 2 | 3 | enum OP_CODE : BYTE 4 | { 5 | NONE = 11, 6 | TEST = 12, 7 | COPY_VIRTUAL_MEMORY = 14, 8 | GET_MODULE_BASE_SIZE = 17, 9 | ALLOC_VIRTUAL_MEMORY = 21, 10 | PROTECT_VIRTUAL_MEMORY = 33, 11 | FREE_VIRTUAL_MEMORY = 41 12 | }; 13 | 14 | enum class SIDE : BYTE 15 | { 16 | NONE, 17 | CLIENT, 18 | SERVER 19 | }; 20 | 21 | struct TEST_S 22 | { 23 | 24 | }; 25 | 26 | struct TEST_C 27 | { 28 | bool valid = false; 29 | }; 30 | 31 | struct COPY_VIRTUAL_MEMORY_SERVER 32 | { 33 | ULONGLONG targetPid; 34 | uintptr_t targetAddress; 35 | ULONGLONG sourcePid; 36 | uintptr_t sourceAddress; 37 | size_t size; 38 | }; 39 | 40 | struct GET_MODULE_SERVER 41 | { 42 | ULONGLONG pid; 43 | wchar_t name[32]; 44 | }; 45 | 46 | struct GET_MODULE_CLIENT 47 | { 48 | uintptr_t baseAddress; 49 | size_t module_size; 50 | }; 51 | 52 | struct ALLOC_VIRTUAL_MEMORY_SERVER 53 | { 54 | ULONG targetPid, allocationType, protect; 55 | uintptr_t sourceAddress; 56 | uintptr_t targetAddress; 57 | size_t size; 58 | size_t code; 59 | }; 60 | 61 | struct PROTECT_VIRTUAL_MEMORY_SERVER 62 | { 63 | ULONG targetPid, protect; 64 | uintptr_t sourceAddress; 65 | size_t size; 66 | size_t code; 67 | }; 68 | 69 | struct FREE_VIRTUAL_MEMORY_SERVER 70 | { 71 | ULONG targetPid; 72 | uintptr_t address; 73 | size_t code; 74 | }; 75 | 76 | struct PACKET_BASE 77 | { 78 | OP_CODE op; 79 | SIDE side; 80 | uint32_t magic; 81 | 82 | union 83 | { 84 | union 85 | { 86 | TEST_S test; 87 | 88 | COPY_VIRTUAL_MEMORY_SERVER copy_virtual_memory; 89 | GET_MODULE_SERVER get_module; 90 | 91 | ALLOC_VIRTUAL_MEMORY_SERVER alloc_virtual_memory; 92 | PROTECT_VIRTUAL_MEMORY_SERVER protect_virtual_memory; 93 | 94 | FREE_VIRTUAL_MEMORY_SERVER free_memory; 95 | } server; 96 | 97 | union 98 | { 99 | TEST_C test; 100 | 101 | COPY_VIRTUAL_MEMORY_SERVER copy_virtual_memory; 102 | GET_MODULE_CLIENT get_module; 103 | 104 | ALLOC_VIRTUAL_MEMORY_SERVER alloc_virtual_memory; 105 | PROTECT_VIRTUAL_MEMORY_SERVER protect_virtual_memory; 106 | 107 | FREE_VIRTUAL_MEMORY_SERVER free_memory; 108 | } client; 109 | }; 110 | }; 111 | 112 | typedef BOOL(*OperationCallback)(ULONG iMode, ULONG magic, PACKET_BASE& packet, FLONG flRed, FLONG flGreen, FLONG flBlue); -------------------------------------------------------------------------------- /Kernel-DLL-Injector/ProcessUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "ProcessUtils.hpp" 2 | 3 | #include 4 | 5 | DWORD ProcessUtils::GetProcessID(string processName) 6 | { 7 | if (processName.empty()) 8 | return NULL; 9 | 10 | HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); 11 | 12 | if (hSnap == INVALID_HANDLE_VALUE) 13 | return NULL; 14 | 15 | PROCESSENTRY32 pe; 16 | pe.dwSize = sizeof(pe); 17 | 18 | if (Process32First(hSnap, &pe)) 19 | { 20 | while (Process32Next(hSnap, &pe)) 21 | { 22 | if (!strcmp(pe.szExeFile, processName.c_str())) 23 | { 24 | CloseHandle(hSnap); 25 | return pe.th32ProcessID; 26 | } 27 | } 28 | } 29 | 30 | CloseHandle(hSnap); 31 | 32 | return NULL; 33 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/ProcessUtils.hpp: -------------------------------------------------------------------------------- 1 | #include "Mapper.hpp" 2 | 3 | class ProcessUtils 4 | { 5 | public: 6 | static DWORD GetProcessID(string processName); 7 | }; -------------------------------------------------------------------------------- /Kernel-DLL-Injector/intel_driver.cpp: -------------------------------------------------------------------------------- 1 | #include "intel_driver.hpp" 2 | 3 | char intel_driver::driver_name[100] = {}; 4 | uintptr_t PiDDBLockPtr; 5 | uintptr_t PiDDBCacheTablePtr; 6 | 7 | bool intel_driver::IsRunning() 8 | { 9 | const HANDLE file_handle = CreateFileA(xor ("\\\\.\\Nal"), FILE_ANY_ACCESS, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 10 | if (file_handle != nullptr && file_handle != INVALID_HANDLE_VALUE) 11 | { 12 | CloseHandle(file_handle); 13 | return true; 14 | } 15 | return false; 16 | } 17 | 18 | HANDLE intel_driver::Load() 19 | { 20 | //Randomize name for log in registry keys, usn jornal and other shits 21 | memset(intel_driver::driver_name, 0, sizeof(intel_driver::driver_name)); 22 | static const char alphanum[] = 23 | "abcdefghijklmnopqrstuvwxyz" 24 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 25 | int len = rand() % 20 + 10; 26 | for (int i = 0; i < len; ++i) 27 | intel_driver::driver_name[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; 28 | 29 | //std::cout << xor ("[<] Loading vulnerable driver") << std::endl; 30 | 31 | char temp_directory[MAX_PATH] = { 0 }; 32 | const uint32_t get_temp_path_ret = GetTempPathA(sizeof(temp_directory), temp_directory); 33 | 34 | if (!get_temp_path_ret || get_temp_path_ret > MAX_PATH) 35 | { 36 | std::cout << xor ("[-] Failed to get temp path") << std::endl; 37 | return nullptr; 38 | } 39 | if (temp_directory[strlen(temp_directory) - 1] == '\\') 40 | temp_directory[strlen(temp_directory) - 1] = 0x0; 41 | const std::string driver_path = std::string(temp_directory) + "\\" + driver_name; 42 | std::remove(driver_path.c_str()); 43 | 44 | if (!utils::CreateFileFromMemory(driver_path, reinterpret_cast(intel_driver_resource::driver), sizeof(intel_driver_resource::driver))) 45 | { 46 | std::cout << xor ("[-] Failed to create vulnerable driver file") << std::endl; 47 | return nullptr; 48 | } 49 | 50 | if (!service::RegisterAndStart(driver_path)) 51 | { 52 | std::cout << xor ("[-] Failed to register and start service for the vulnerable driver") << std::endl; 53 | std::remove(driver_path.c_str()); 54 | return nullptr; 55 | } 56 | 57 | return CreateFileA(xor ("\\\\.\\Nal"), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 58 | } 59 | 60 | void intel_driver::Unload(HANDLE device_handle) 61 | { 62 | //std::cout << xor ("[<] Unloading vulnerable driver") << std::endl; 63 | 64 | if (device_handle && device_handle != INVALID_HANDLE_VALUE) { 65 | CloseHandle(device_handle); 66 | } 67 | 68 | service::StopAndRemove(driver_name); 69 | 70 | char temp_directory[MAX_PATH] = { 0 }; 71 | 72 | const uint32_t get_temp_path_ret = GetTempPathA(sizeof(temp_directory), temp_directory); 73 | if (temp_directory[strlen(temp_directory) - 1] == '\\') 74 | temp_directory[strlen(temp_directory) - 1] = 0x0; 75 | const std::string driver_path = std::string(temp_directory) + "\\" + driver_name; 76 | 77 | //Destroy disk information before unlink from disk to prevent any recover of the file 78 | std::ofstream file_ofstream(driver_path.c_str(), std::ios_base::out | std::ios_base::binary); 79 | int newFileLen = sizeof(intel_driver_resource::driver) + ((long long)rand() % 2348767 + 56725); 80 | BYTE * randomData = new BYTE[newFileLen]; 81 | for (size_t i = 0; i < newFileLen; i++) { 82 | randomData[i] = (BYTE)(rand() % 255); 83 | } 84 | if (!file_ofstream.write((char*)randomData, newFileLen)) 85 | { 86 | std::cout << xor ("[!] Error dumping shit inside the disk") << std::endl; 87 | } 88 | else { 89 | //std::cout << xor ("[+] Vul driver data destroyed before unlink") << std::endl; 90 | } 91 | file_ofstream.close(); 92 | delete[] randomData; 93 | 94 | //unlink the file 95 | std::remove(driver_path.c_str()); 96 | } 97 | 98 | bool intel_driver::MemCopy(HANDLE device_handle, uint64_t destination, uint64_t source, uint64_t size) 99 | { 100 | if (!destination || !source || !size) 101 | return 0; 102 | 103 | COPY_MEMORY_BUFFER_INFO copy_memory_buffer = { 0 }; 104 | 105 | copy_memory_buffer.case_number = 0x33; 106 | copy_memory_buffer.source = source; 107 | copy_memory_buffer.destination = destination; 108 | copy_memory_buffer.length = size; 109 | 110 | DWORD bytes_returned = 0; 111 | return DeviceIoControl(device_handle, ioctl1, ©_memory_buffer, sizeof(copy_memory_buffer), nullptr, 0, &bytes_returned, nullptr); 112 | } 113 | 114 | bool intel_driver::SetMemory(HANDLE device_handle, uint64_t address, uint32_t value, uint64_t size) 115 | { 116 | if (!address || !size) 117 | return 0; 118 | 119 | FILL_MEMORY_BUFFER_INFO fill_memory_buffer = { 0 }; 120 | 121 | fill_memory_buffer.case_number = 0x30; 122 | fill_memory_buffer.destination = address; 123 | fill_memory_buffer.value = value; 124 | fill_memory_buffer.length = size; 125 | 126 | DWORD bytes_returned = 0; 127 | return DeviceIoControl(device_handle, ioctl1, &fill_memory_buffer, sizeof(fill_memory_buffer), nullptr, 0, &bytes_returned, nullptr); 128 | } 129 | 130 | bool intel_driver::GetPhysicalAddress(HANDLE device_handle, uint64_t address, uint64_t * out_physical_address) 131 | { 132 | if (!address) 133 | return 0; 134 | 135 | GET_PHYS_ADDRESS_BUFFER_INFO get_phys_address_buffer = { 0 }; 136 | 137 | get_phys_address_buffer.case_number = 0x25; 138 | get_phys_address_buffer.address_to_translate = address; 139 | 140 | DWORD bytes_returned = 0; 141 | 142 | if (!DeviceIoControl(device_handle, ioctl1, &get_phys_address_buffer, sizeof(get_phys_address_buffer), nullptr, 0, &bytes_returned, nullptr)) 143 | return false; 144 | 145 | *out_physical_address = get_phys_address_buffer.return_physical_address; 146 | return true; 147 | } 148 | 149 | uint64_t intel_driver::MapIoSpace(HANDLE device_handle, uint64_t physical_address, uint32_t size) 150 | { 151 | if (!physical_address || !size) 152 | return 0; 153 | 154 | MAP_IO_SPACE_BUFFER_INFO map_io_space_buffer = { 0 }; 155 | 156 | map_io_space_buffer.case_number = 0x19; 157 | map_io_space_buffer.physical_address_to_map = physical_address; 158 | map_io_space_buffer.size = size; 159 | 160 | DWORD bytes_returned = 0; 161 | 162 | if (!DeviceIoControl(device_handle, ioctl1, &map_io_space_buffer, sizeof(map_io_space_buffer), nullptr, 0, &bytes_returned, nullptr)) 163 | return 0; 164 | 165 | return map_io_space_buffer.return_virtual_address; 166 | } 167 | 168 | bool intel_driver::UnmapIoSpace(HANDLE device_handle, uint64_t address, uint32_t size) 169 | { 170 | if (!address || !size) 171 | return false; 172 | 173 | UNMAP_IO_SPACE_BUFFER_INFO unmap_io_space_buffer = { 0 }; 174 | 175 | unmap_io_space_buffer.case_number = 0x1A; 176 | unmap_io_space_buffer.virt_address = address; 177 | unmap_io_space_buffer.number_of_bytes = size; 178 | 179 | DWORD bytes_returned = 0; 180 | 181 | return DeviceIoControl(device_handle, ioctl1, &unmap_io_space_buffer, sizeof(unmap_io_space_buffer), nullptr, 0, &bytes_returned, nullptr); 182 | } 183 | 184 | bool intel_driver::ReadMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size) 185 | { 186 | return MemCopy(device_handle, reinterpret_cast(buffer), address, size); 187 | } 188 | 189 | bool intel_driver::WriteMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size) 190 | { 191 | return MemCopy(device_handle, address, reinterpret_cast(buffer), size); 192 | } 193 | 194 | bool intel_driver::WriteToReadOnlyMemory(HANDLE device_handle, uint64_t address, void* buffer, uint32_t size) 195 | { 196 | if (!address || !buffer || !size) 197 | return false; 198 | 199 | uint64_t physical_address = 0; 200 | 201 | if (!GetPhysicalAddress(device_handle, address, &physical_address)) 202 | { 203 | std::cout << xor ("[-] Failed to translate virtual address 0x") << reinterpret_cast(address) << std::endl; 204 | return false; 205 | } 206 | 207 | const uint64_t mapped_physical_memory = MapIoSpace(device_handle, physical_address, size); 208 | 209 | if (!mapped_physical_memory) 210 | { 211 | std::cout << xor ("[-] Failed to map IO space of 0x") << reinterpret_cast(physical_address) << std::endl; 212 | return false; 213 | } 214 | 215 | bool result = WriteMemory(device_handle, mapped_physical_memory, buffer, size); 216 | 217 | if (!UnmapIoSpace(device_handle, mapped_physical_memory, size)) 218 | std::cout << xor ("[!] Failed to unmap IO space of physical address 0x") << reinterpret_cast(physical_address) << std::endl; 219 | 220 | return result; 221 | } 222 | 223 | uint64_t intel_driver::AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type, uint64_t size) 224 | { 225 | if (!size) 226 | return 0; 227 | 228 | static uint64_t kernel_ExAllocatePool = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExAllocatePoolWithTag"); 229 | 230 | if (!kernel_ExAllocatePool) 231 | { 232 | std::cout << xor ("[!] Failed to find ExAllocatePool") << std::endl; 233 | return 0; 234 | } 235 | 236 | uint64_t allocated_pool = 0; 237 | 238 | if (!CallKernelFunction(device_handle, &allocated_pool, kernel_ExAllocatePool, pool_type, size, 'erhT')) 239 | return 0; 240 | 241 | return allocated_pool; 242 | } 243 | 244 | bool intel_driver::FreePool(HANDLE device_handle, uint64_t address) 245 | { 246 | if (!address) 247 | return 0; 248 | 249 | static uint64_t kernel_ExFreePool = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExFreePool"); 250 | 251 | if (!kernel_ExFreePool) { 252 | std::cout << xor ("[!] Failed to find ExAllocatePool") << std::endl; 253 | return 0; 254 | } 255 | 256 | return CallKernelFunction(device_handle, nullptr, kernel_ExFreePool, address); 257 | } 258 | 259 | uint64_t intel_driver::GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string & function_name) 260 | { 261 | if (!kernel_module_base) 262 | return 0; 263 | 264 | IMAGE_DOS_HEADER dos_header = { 0 }; 265 | IMAGE_NT_HEADERS64 nt_headers = { 0 }; 266 | 267 | if (!ReadMemory(device_handle, kernel_module_base, &dos_header, sizeof(dos_header)) || dos_header.e_magic != IMAGE_DOS_SIGNATURE || 268 | !ReadMemory(device_handle, kernel_module_base + dos_header.e_lfanew, &nt_headers, sizeof(nt_headers)) || nt_headers.Signature != IMAGE_NT_SIGNATURE) 269 | return 0; 270 | 271 | const auto export_base = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 272 | const auto export_base_size = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; 273 | 274 | if (!export_base || !export_base_size) 275 | return 0; 276 | 277 | const auto export_data = reinterpret_cast(VirtualAlloc(nullptr, export_base_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); 278 | 279 | if (!ReadMemory(device_handle, kernel_module_base + export_base, export_data, export_base_size)) 280 | { 281 | VirtualFree(export_data, 0, MEM_RELEASE); 282 | return 0; 283 | } 284 | 285 | const auto delta = reinterpret_cast(export_data) - export_base; 286 | 287 | const auto name_table = reinterpret_cast(export_data->AddressOfNames + delta); 288 | const auto ordinal_table = reinterpret_cast(export_data->AddressOfNameOrdinals + delta); 289 | const auto function_table = reinterpret_cast(export_data->AddressOfFunctions + delta); 290 | 291 | for (auto i = 0u; i < export_data->NumberOfNames; ++i) 292 | { 293 | const std::string current_function_name = std::string(reinterpret_cast(name_table[i] + delta)); 294 | 295 | if (!_stricmp(current_function_name.c_str(), function_name.c_str())) 296 | { 297 | const auto function_ordinal = ordinal_table[i]; 298 | const auto function_address = kernel_module_base + function_table[function_ordinal]; 299 | 300 | if (function_address >= kernel_module_base + export_base && function_address <= kernel_module_base + export_base + export_base_size) 301 | { 302 | VirtualFree(export_data, 0, MEM_RELEASE); 303 | return 0; // No forwarded exports on 64bit? 304 | } 305 | 306 | VirtualFree(export_data, 0, MEM_RELEASE); 307 | return function_address; 308 | } 309 | } 310 | 311 | VirtualFree(export_data, 0, MEM_RELEASE); 312 | return 0; 313 | } 314 | 315 | bool intel_driver::ClearMmUnloadedDrivers(HANDLE device_handle) 316 | { 317 | ULONG buffer_size = 0; 318 | void* buffer = nullptr; 319 | 320 | NTSTATUS status = NtQuerySystemInformation(static_cast(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size); 321 | 322 | while (status == nt::STATUS_INFO_LENGTH_MISMATCH) 323 | { 324 | VirtualFree(buffer, 0, MEM_RELEASE); 325 | 326 | buffer = VirtualAlloc(nullptr, buffer_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 327 | status = NtQuerySystemInformation(static_cast(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size); 328 | } 329 | 330 | if (!NT_SUCCESS(status) || buffer == 0) 331 | { 332 | if (buffer != 0) 333 | VirtualFree(buffer, 0, MEM_RELEASE); 334 | return false; 335 | } 336 | 337 | uint64_t object = 0; 338 | 339 | auto system_handle_inforamtion = static_cast(buffer); 340 | 341 | for (auto i = 0u; i < system_handle_inforamtion->HandleCount; ++i) 342 | { 343 | const nt::SYSTEM_HANDLE current_system_handle = system_handle_inforamtion->Handles[i]; 344 | 345 | if (current_system_handle.UniqueProcessId != reinterpret_cast(static_cast(GetCurrentProcessId()))) 346 | continue; 347 | 348 | if (current_system_handle.HandleValue == device_handle) 349 | { 350 | object = reinterpret_cast(current_system_handle.Object); 351 | break; 352 | } 353 | } 354 | 355 | VirtualFree(buffer, 0, MEM_RELEASE); 356 | 357 | if (!object) 358 | return false; 359 | 360 | uint64_t device_object = 0; 361 | 362 | if (!ReadMemory(device_handle, object + 0x8, &device_object, sizeof(device_object)) || !device_object) { 363 | std::cout << xor ("[!] Failed to find device_object") << std::endl; 364 | return false; 365 | } 366 | 367 | uint64_t driver_object = 0; 368 | 369 | if (!ReadMemory(device_handle, device_object + 0x8, &driver_object, sizeof(driver_object)) || !driver_object) { 370 | std::cout << xor ("[!] Failed to find driver_object") << std::endl; 371 | return false; 372 | } 373 | 374 | uint64_t driver_section = 0; 375 | 376 | if (!ReadMemory(device_handle, driver_object + 0x28, &driver_section, sizeof(driver_section)) || !driver_section) { 377 | std::cout << xor ("[!] Failed to find driver_section") << std::endl; 378 | return false; 379 | } 380 | 381 | UNICODE_STRING us_driver_base_dll_name = { 0 }; 382 | 383 | if (!ReadMemory(device_handle, driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name)) || us_driver_base_dll_name.Length == 0) { 384 | std::cout << xor ("[!] Failed to find driver name") << std::endl; 385 | return false; 386 | } 387 | 388 | wchar_t * unloadedName = new wchar_t[us_driver_base_dll_name.Length]; 389 | memset(unloadedName, 0, us_driver_base_dll_name.Length * sizeof(wchar_t)); 390 | 391 | ReadMemory(device_handle, (uintptr_t)us_driver_base_dll_name.Buffer, unloadedName, us_driver_base_dll_name.Length * sizeof(wchar_t)); 392 | 393 | us_driver_base_dll_name.Length = 0; //MiRememberUnloadedDriver will check if the length > 0 to save the unloaded driver 394 | 395 | if (!WriteMemory(device_handle, driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name))) { 396 | std::cout << xor ("[!] Failed to write driver name length") << std::endl; 397 | return false; 398 | } 399 | 400 | //std::wcout << L"[+] MmUnloadedDrivers Cleaned: " << unloadedName << std::endl; 401 | 402 | delete[] unloadedName; 403 | 404 | return true; 405 | } 406 | 407 | PVOID intel_driver::ResolveRelativeAddress(HANDLE device_handle, _In_ PVOID Instruction, _In_ ULONG OffsetOffset, _In_ ULONG InstructionSize) { 408 | ULONG_PTR Instr = (ULONG_PTR)Instruction; 409 | LONG RipOffset = 0; 410 | if (!ReadMemory(device_handle, Instr + OffsetOffset, &RipOffset, sizeof(LONG))) { 411 | return nullptr; 412 | } 413 | PVOID ResolvedAddr = (PVOID)(Instr + InstructionSize + RipOffset); 414 | return ResolvedAddr; 415 | } 416 | 417 | bool intel_driver::ExAcquireResourceExclusiveLite(HANDLE device_handle, PVOID Resource, BOOLEAN wait) 418 | { 419 | if (!Resource) 420 | return 0; 421 | 422 | static uint64_t kernel_ExAcquireResourceExclusiveLite = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExAcquireResourceExclusiveLite"); 423 | 424 | if (!kernel_ExAcquireResourceExclusiveLite) { 425 | std::cout << "[!] Failed to find ExAcquireResourceExclusiveLite" << std::endl; 426 | return 0; 427 | } 428 | 429 | BOOLEAN out; 430 | 431 | return (CallKernelFunction(device_handle, &out, kernel_ExAcquireResourceExclusiveLite, Resource, wait) && out); 432 | } 433 | 434 | bool intel_driver::ExReleaseResourceLite(HANDLE device_handle, PVOID Resource) 435 | { 436 | if (!Resource) 437 | return false; 438 | 439 | static uint64_t kernel_ExReleaseResourceLite = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExReleaseResourceLite"); 440 | 441 | if (!kernel_ExReleaseResourceLite) { 442 | std::cout << "[!] Failed to find ExReleaseResourceLite" << std::endl; 443 | return false; 444 | } 445 | 446 | return CallKernelFunction(device_handle, nullptr, kernel_ExReleaseResourceLite, Resource); 447 | } 448 | 449 | BOOLEAN intel_driver::RtlDeleteElementGenericTableAvl(HANDLE device_handle, PVOID Table, PVOID Buffer) 450 | { 451 | if (!Table) 452 | return false; 453 | 454 | static uint64_t kernel_RtlDeleteElementGenericTableAvl = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "RtlDeleteElementGenericTableAvl"); 455 | 456 | if (!kernel_RtlDeleteElementGenericTableAvl) { 457 | std::cout << "[!] Failed to find RtlDeleteElementGenericTableAvl" << std::endl; 458 | return false; 459 | } 460 | 461 | BOOLEAN out; 462 | 463 | return (CallKernelFunction(device_handle, &out, kernel_RtlDeleteElementGenericTableAvl, Table, Buffer) && out); 464 | } 465 | 466 | intel_driver::PiDDBCacheEntry* intel_driver::LookupEntry(HANDLE device_handle, PRTL_AVL_TABLE PiDDBCacheTable, ULONG timestamp) { 467 | PiDDBCacheEntry* firstEntry; 468 | if (!ReadMemory(device_handle, (uintptr_t)PiDDBCacheTable + (offsetof(struct _RTL_AVL_TABLE, BalancedRoot.RightChild)), &firstEntry, sizeof(_RTL_BALANCED_LINKS*))) { 469 | return nullptr; 470 | } 471 | 472 | (*(uintptr_t*)&firstEntry) += sizeof(RTL_BALANCED_LINKS); 473 | 474 | PiDDBCacheEntry* cache_entry; 475 | if (!ReadMemory(device_handle, (uintptr_t)firstEntry + (offsetof(struct _PiDDBCacheEntry, List.Flink)), &cache_entry, sizeof(_LIST_ENTRY*))) { 476 | return nullptr; 477 | } 478 | 479 | while (TRUE) { 480 | ULONG itemTimeDateStamp = 0; 481 | if (!ReadMemory(device_handle, (uintptr_t)cache_entry + (offsetof(struct _PiDDBCacheEntry, TimeDateStamp)), &itemTimeDateStamp, sizeof(ULONG))) { 482 | return nullptr; 483 | } 484 | if (itemTimeDateStamp == timestamp) { 485 | //printf("[+] PiDDBCacheTable result -> TimeStamp: %x\n", itemTimeDateStamp); 486 | return cache_entry; 487 | } 488 | if ((uintptr_t)cache_entry == (uintptr_t)firstEntry) { 489 | break; 490 | } 491 | if (!ReadMemory(device_handle, (uintptr_t)cache_entry + (offsetof(struct _PiDDBCacheEntry, List.Flink)), &cache_entry, sizeof(_LIST_ENTRY*))) { 492 | return nullptr; 493 | } 494 | } 495 | return nullptr; 496 | } 497 | 498 | 499 | bool intel_driver::ClearPiDDBCacheTable(HANDLE device_handle) { //PiDDBCacheTable added on LoadDriver 500 | 501 | uint64_t ntoskrnl = utils::GetKernelModuleAddress("ntoskrnl.exe"); 502 | 503 | PiDDBLockPtr = FindPatternInSectionAtKernel(device_handle, (char*)"PAGE", ntoskrnl, (PUCHAR)"\x81\xFB\x6C\x03\x00\xC0\x0F\x84\x00\x00\x00\x00\x48\x8D\x0D", (char*)"xxxxxxxx????xxx"); // 81 FB 6C 03 00 C0 0F 84 ? ? ? ? 48 8D 0D update for build 21286 etc... 504 | PiDDBCacheTablePtr = FindPatternInSectionAtKernel(device_handle, (char*)"PAGE", ntoskrnl, (PUCHAR)"\x66\x03\xD2\x48\x8D\x0D", (char*)"xxxxxx"); 505 | if (PiDDBLockPtr == NULL || PiDDBCacheTablePtr == NULL) { 506 | std::cout << "[-] Warning no PiDDBCacheTable Found" << std::endl; 507 | return false; 508 | } 509 | 510 | //printf("[+] PiDDBLock Ptr %llx\n", PiDDBLockPtr); 511 | //printf("[+] PiDDBCacheTable Ptr %llx\n", PiDDBCacheTablePtr); 512 | 513 | PVOID PiDDBLock = ResolveRelativeAddress(device_handle, (PVOID)PiDDBLockPtr, 15, 19); 514 | PRTL_AVL_TABLE PiDDBCacheTable = (PRTL_AVL_TABLE)ResolveRelativeAddress(device_handle, (PVOID)PiDDBCacheTablePtr, 6, 10); 515 | 516 | 517 | SetMemory(device_handle, (uintptr_t)PiDDBCacheTable + (offsetof(struct _RTL_AVL_TABLE, TableContext)), 1, sizeof(PVOID)); 518 | 519 | if (!ExAcquireResourceExclusiveLite(device_handle, PiDDBLock, true)) { 520 | std::cout << "[-] Can't lock PiDDBCacheTable" << std::endl; 521 | return false; 522 | } 523 | //std::cout << "[+] PiDDBLock Locked" << std::endl; 524 | 525 | // search our entry in the table 526 | PiDDBCacheEntry* pFoundEntry = (PiDDBCacheEntry*)LookupEntry(device_handle,PiDDBCacheTable, iqvw64e_timestamp); 527 | if (pFoundEntry == nullptr) { 528 | std::cout << "[-] Not found in cache" << std::endl; 529 | ExReleaseResourceLite(device_handle, PiDDBLock); 530 | return false; 531 | } 532 | 533 | // first, unlink from the list 534 | PLIST_ENTRY prev; 535 | if (!ReadMemory(device_handle, (uintptr_t)pFoundEntry + (offsetof(struct _PiDDBCacheEntry, List.Blink)), &prev, sizeof(_LIST_ENTRY*))) { 536 | std::cout << "[-] Can't get prev entry" << std::endl; 537 | ExReleaseResourceLite(device_handle, PiDDBLock); 538 | return false; 539 | } 540 | PLIST_ENTRY next; 541 | if (!ReadMemory(device_handle, (uintptr_t)pFoundEntry + (offsetof(struct _PiDDBCacheEntry, List.Flink)), &next, sizeof(_LIST_ENTRY*))) { 542 | std::cout << "[-] Can't get next entry" << std::endl; 543 | ExReleaseResourceLite(device_handle, PiDDBLock); 544 | return false; 545 | } 546 | 547 | //printf("[+] Found Table Entry = %p\n", pFoundEntry); 548 | 549 | if (!WriteMemory(device_handle, (uintptr_t)prev + (offsetof(struct _LIST_ENTRY, Flink)), &next, sizeof(_LIST_ENTRY*))) { 550 | std::cout << "[-] Can't set next entry" << std::endl; 551 | ExReleaseResourceLite(device_handle, PiDDBLock); 552 | return false; 553 | } 554 | if (!WriteMemory(device_handle, (uintptr_t)next + (offsetof(struct _LIST_ENTRY, Blink)), &prev, sizeof(_LIST_ENTRY*))) { 555 | std::cout << "[-] Can't set prev entry" << std::endl; 556 | ExReleaseResourceLite(device_handle, PiDDBLock); 557 | return false; 558 | } 559 | 560 | // then delete the element from the avl table 561 | if (!RtlDeleteElementGenericTableAvl(device_handle, PiDDBCacheTable, pFoundEntry)) { 562 | std::cout << "[-] Can't delete from PiDDBCacheTable" << std::endl; 563 | ExReleaseResourceLite(device_handle, PiDDBLock); 564 | return false; 565 | } 566 | 567 | // release the ddb resource lock 568 | ExReleaseResourceLite(device_handle, PiDDBLock); 569 | 570 | //std::cout << "[+] PiDDBCacheTable Cleaned" << std::endl; 571 | 572 | return true; 573 | } 574 | 575 | uintptr_t intel_driver::FindPatternAtKernel(HANDLE device_handle, uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, char* szMask) { 576 | if (!dwAddress) { 577 | std::cout << "[-] No module address to find pattern" << std::endl; 578 | return 0; 579 | } 580 | 581 | if (dwLen > 1024 * 1024 * 1024) { //if read is > 1GB 582 | std::cout << "[-] Can't find pattern, Too big section" << std::endl; 583 | return 0; 584 | } 585 | 586 | BYTE* sectionData = new BYTE[dwLen]; 587 | ReadMemory(device_handle, dwAddress, sectionData, dwLen); 588 | 589 | auto result = utils::FindPattern((uintptr_t)sectionData, dwLen, bMask, szMask); 590 | 591 | if (result <= 0) { 592 | std::cout << "[-] Can't find pattern" << std::endl; 593 | delete[] sectionData; 594 | return 0; 595 | } 596 | result = dwAddress + result - (uintptr_t)sectionData; 597 | delete[] sectionData; 598 | return result; 599 | } 600 | 601 | uintptr_t intel_driver::FindSectionAtKernel(HANDLE device_handle, char* sectionName, uintptr_t modulePtr, PULONG size) { 602 | if (!modulePtr) 603 | return 0; 604 | BYTE headers[0x1000]; 605 | if (!ReadMemory(device_handle, modulePtr, headers, 0x1000)) { 606 | std::cout << "[-] Can't read module headers" << std::endl; 607 | return 0; 608 | } 609 | ULONG sectionSize = 0; 610 | uintptr_t section = (uintptr_t)utils::FindSection(sectionName, (uintptr_t)headers, §ionSize); 611 | if (!section || !sectionSize) { 612 | std::cout << "[-] Can't find section" << std::endl; 613 | return false; 614 | } 615 | if (size) 616 | *size = sectionSize; 617 | return section - (uintptr_t)headers + modulePtr; 618 | } 619 | 620 | uintptr_t intel_driver::FindPatternInSectionAtKernel(HANDLE device_handle,char* sectionName, uintptr_t modulePtr, BYTE* bMask, char* szMask) { 621 | ULONG sectionSize = 0; 622 | uintptr_t section = FindSectionAtKernel(device_handle, sectionName, modulePtr, §ionSize); 623 | return FindPatternAtKernel(device_handle, section, sectionSize, bMask, szMask); 624 | } 625 | 626 | bool intel_driver::ClearKernelHashBucketList(HANDLE device_handle) { 627 | std::string dname(driver_name); 628 | std::wstring wdname(dname.begin(), dname.end()); 629 | wdname = L"\\" + wdname; 630 | uint64_t ci = utils::GetKernelModuleAddress("ci.dll"); 631 | 632 | //Thanks @KDIo3 and @Swiftik from UnknownCheats 633 | auto sig = FindPatternInSectionAtKernel(device_handle, (char*)"PAGE", ci, PUCHAR("\x48\x8B\x1D\x00\x00\x00\x00\xEB\x00\xF7\x43\x40\x00\x20\x00\x00"), (char*)"xxx????x?xxxxxxx"); 634 | if (!sig) { 635 | std::cout << "[-] Can't Find g_KernelHashBucketList" << std::endl; 636 | return false; 637 | } 638 | 639 | //auto sig2 = FindPatternAtKernel(device_handle, (uintptr_t)sig - 50, 50, PUCHAR("\x48\x8D\x0D"), (char*)"xxx"); 640 | 641 | auto sig2 = (uintptr_t)sig - 0x13; 642 | 643 | if (!sig2) { 644 | std::cout << "[-] Can't Find g_HashCacheLock" << std::endl; 645 | return false; 646 | } 647 | 648 | //printf("[+] g_KernelHashBucketList ptr: %p\n", sig); 649 | //printf("[+] g_HashCacheLock ptr: %p\n", sig2); 650 | 651 | const auto g_KernelHashBucketList = ResolveRelativeAddress(device_handle, (PVOID)sig, 3, 7); 652 | const auto g_HashCacheLock = ResolveRelativeAddress(device_handle, (PVOID)sig2, 3, 7); 653 | if (!g_KernelHashBucketList || !g_HashCacheLock) 654 | { 655 | std::cout << "[-] Can't Find g_HashCache relative address" << std::endl; 656 | return false; 657 | } 658 | 659 | //printf("[+] g_HashCacheLock RVA: %p\n", g_HashCacheLock); // 1C0036DE0 660 | //std::wcout << L"[+] g_KernelHashBucketList Found 0x" << std::hex << g_KernelHashBucketList << std::endl; 661 | 662 | //// Print KernelHashBucketList 663 | //ULONG_PTR i = NULL; 664 | //ReadMemory(device_handle, (uintptr_t)g_KernelHashBucketList, &i, sizeof(i)); 665 | //while (i) 666 | //{ 667 | // const auto wsNamePtr = PWCH(i + 0x48); 668 | // wchar_t wsName[MAX_PATH]; 669 | // memset(wsName, 0, MAX_PATH * sizeof(wchar_t)); 670 | // ReadMemory(device_handle, (uintptr_t)wsNamePtr, wsName, MAX_PATH * sizeof(wchar_t)); 671 | // std::wcout << wsName << std::endl; 672 | // ReadMemory(device_handle, (uintptr_t)i, &i, sizeof(i)); 673 | //} 674 | 675 | if (!ExAcquireResourceExclusiveLite(device_handle, g_HashCacheLock, true)) { 676 | std::cout << "[-] Can't lock g_HashCacheLock" << std::endl; 677 | return false; 678 | } 679 | //std::cout << "[+] g_HashCacheLock Locked" << std::endl; 680 | 681 | HashBucketEntry* prev = (HashBucketEntry*)g_KernelHashBucketList; 682 | //std::cout << "[+] CertHash: " << (const char*)prev->CertHash << std::endl; 683 | HashBucketEntry* entry = 0; 684 | ReadMemory(device_handle, (uintptr_t)prev, &entry, sizeof(entry)); 685 | if (!entry) { 686 | std::wcout << L"[!] g_KernelHashBucketList looks empty!" << std::endl; 687 | ExReleaseResourceLite(device_handle, g_HashCacheLock); 688 | return true; 689 | } 690 | while (entry) { 691 | wchar_t* wsNamePtr = 0; 692 | USHORT wsNameLen = 0; 693 | ReadMemory(device_handle, (uintptr_t)entry + offsetof(HashBucketEntry, DriverName.Buffer), &wsNamePtr, sizeof(wsNamePtr)); 694 | ReadMemory(device_handle, (uintptr_t)entry + offsetof(HashBucketEntry, DriverName.Length), &wsNameLen, sizeof(wsNameLen)); 695 | 696 | wchar_t* wsName = new wchar_t[wsNameLen]; 697 | memset(wsName, 0, wsNameLen * sizeof(wchar_t)); 698 | ReadMemory(device_handle, (uintptr_t)wsNamePtr, wsName, wsNameLen * sizeof(wchar_t)); 699 | 700 | if (std::wstring(wsName).find(wdname) != std::wstring::npos) { 701 | //std::wcout << L"[+] Found In g_KernelHashBucketList: " << wsName << std::endl; 702 | 703 | HashBucketEntry* Next = 0; 704 | ReadMemory(device_handle, (uintptr_t)entry, &Next, sizeof(Next)); 705 | 706 | WriteMemory(device_handle, (uintptr_t)prev, &Next, sizeof(Next)); 707 | 708 | FreePool(device_handle, (uintptr_t)entry); 709 | //std::wcout << L"[+] g_KernelHashBucketList Cleaned" << std::endl; 710 | ExReleaseResourceLite(device_handle, g_HashCacheLock); 711 | delete[] wsName; 712 | return true; 713 | } 714 | 715 | prev = entry; 716 | delete[] wsName; 717 | //read next 718 | ReadMemory(device_handle, (uintptr_t)entry, &entry, sizeof(entry)); 719 | } 720 | 721 | ExReleaseResourceLite(device_handle, g_HashCacheLock); 722 | return false; 723 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/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 | #include 12 | 13 | #include "xorstr.hpp" 14 | 15 | namespace intel_driver 16 | { 17 | extern char driver_name[100]; //"iqvw64e.sys" 18 | constexpr uint32_t ioctl1 = 0x80862007; 19 | constexpr DWORD iqvw64e_timestamp = 0x5284EAC3; 20 | 21 | typedef struct _COPY_MEMORY_BUFFER_INFO 22 | { 23 | uint64_t case_number; 24 | uint64_t reserved; 25 | uint64_t source; 26 | uint64_t destination; 27 | uint64_t length; 28 | }COPY_MEMORY_BUFFER_INFO, * PCOPY_MEMORY_BUFFER_INFO; 29 | 30 | typedef struct _FILL_MEMORY_BUFFER_INFO 31 | { 32 | uint64_t case_number; 33 | uint64_t reserved1; 34 | uint32_t value; 35 | uint32_t reserved2; 36 | uint64_t destination; 37 | uint64_t length; 38 | }FILL_MEMORY_BUFFER_INFO, * PFILL_MEMORY_BUFFER_INFO; 39 | 40 | typedef struct _GET_PHYS_ADDRESS_BUFFER_INFO 41 | { 42 | uint64_t case_number; 43 | uint64_t reserved; 44 | uint64_t return_physical_address; 45 | uint64_t address_to_translate; 46 | }GET_PHYS_ADDRESS_BUFFER_INFO, * PGET_PHYS_ADDRESS_BUFFER_INFO; 47 | 48 | typedef struct _MAP_IO_SPACE_BUFFER_INFO 49 | { 50 | uint64_t case_number; 51 | uint64_t reserved; 52 | uint64_t return_value; 53 | uint64_t return_virtual_address; 54 | uint64_t physical_address_to_map; 55 | uint32_t size; 56 | }MAP_IO_SPACE_BUFFER_INFO, * PMAP_IO_SPACE_BUFFER_INFO; 57 | 58 | typedef struct _UNMAP_IO_SPACE_BUFFER_INFO 59 | { 60 | uint64_t case_number; 61 | uint64_t reserved1; 62 | uint64_t reserved2; 63 | uint64_t virt_address; 64 | uint64_t reserved3; 65 | uint32_t number_of_bytes; 66 | }UNMAP_IO_SPACE_BUFFER_INFO, * PUNMAP_IO_SPACE_BUFFER_INFO; 67 | 68 | typedef struct _RTL_BALANCED_LINKS { 69 | struct _RTL_BALANCED_LINKS* Parent; 70 | struct _RTL_BALANCED_LINKS* LeftChild; 71 | struct _RTL_BALANCED_LINKS* RightChild; 72 | CHAR Balance; 73 | UCHAR Reserved[3]; 74 | } RTL_BALANCED_LINKS; 75 | typedef RTL_BALANCED_LINKS* PRTL_BALANCED_LINKS; 76 | 77 | typedef struct _RTL_AVL_TABLE { 78 | RTL_BALANCED_LINKS BalancedRoot; 79 | PVOID OrderedPointer; 80 | ULONG WhichOrderedElement; 81 | ULONG NumberGenericTableElements; 82 | ULONG DepthOfTree; 83 | PVOID RestartKey; 84 | ULONG DeleteCount; 85 | PVOID CompareRoutine; 86 | PVOID AllocateRoutine; 87 | PVOID FreeRoutine; 88 | PVOID TableContext; 89 | } RTL_AVL_TABLE; 90 | typedef RTL_AVL_TABLE* PRTL_AVL_TABLE; 91 | 92 | typedef struct _PiDDBCacheEntry 93 | { 94 | LIST_ENTRY List; 95 | UNICODE_STRING DriverName; 96 | ULONG TimeDateStamp; 97 | NTSTATUS LoadStatus; 98 | char _0x0028[16]; // data from the shim engine, or uninitialized memory for custom drivers 99 | } PiDDBCacheEntry, * NPiDDBCacheEntry; 100 | 101 | typedef struct _HashBucketEntry 102 | { 103 | struct _HashBucketEntry* Next; 104 | UNICODE_STRING DriverName; 105 | ULONG CertHash[5]; 106 | } HashBucketEntry, * PHashBucketEntry; 107 | 108 | bool ClearPiDDBCacheTable(HANDLE device_handle); 109 | bool ExAcquireResourceExclusiveLite(HANDLE device_handle, PVOID Resource, BOOLEAN wait); 110 | bool ExReleaseResourceLite(HANDLE device_handle, PVOID Resource); 111 | BOOLEAN RtlDeleteElementGenericTableAvl(HANDLE device_handle, PVOID Table, PVOID Buffer); 112 | PiDDBCacheEntry* LookupEntry(HANDLE device_handle, PRTL_AVL_TABLE PiDDBCacheTable, ULONG timestamp); 113 | PVOID ResolveRelativeAddress(HANDLE device_handle, _In_ PVOID Instruction, _In_ ULONG OffsetOffset, _In_ ULONG InstructionSize); 114 | 115 | uintptr_t FindPatternAtKernel(HANDLE device_handle, uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, char* szMask); 116 | uintptr_t FindSectionAtKernel(HANDLE device_handle, char* sectionName, uintptr_t modulePtr, PULONG size); 117 | uintptr_t FindPatternInSectionAtKernel(HANDLE device_handle, char* sectionName, uintptr_t modulePtr, BYTE* bMask, char* szMask); 118 | 119 | bool ClearKernelHashBucketList(HANDLE device_handle); 120 | 121 | bool IsRunning(); 122 | HANDLE Load(); 123 | void Unload(HANDLE device_handle); 124 | 125 | bool MemCopy(HANDLE device_handle, uint64_t destination, uint64_t source, uint64_t size); 126 | bool SetMemory(HANDLE device_handle, uint64_t address, uint32_t value, uint64_t size); 127 | bool GetPhysicalAddress(HANDLE device_handle, uint64_t address, uint64_t* out_physical_address); 128 | uint64_t MapIoSpace(HANDLE device_handle, uint64_t physical_address, uint32_t size); 129 | bool UnmapIoSpace(HANDLE device_handle, uint64_t address, uint32_t size); 130 | bool ReadMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size); 131 | bool WriteMemory(HANDLE device_handle, uint64_t address, void* buffer, uint64_t size); 132 | bool WriteToReadOnlyMemory(HANDLE device_handle, uint64_t address, void* buffer, uint32_t size); 133 | uint64_t AllocatePool(HANDLE device_handle, nt::POOL_TYPE pool_type, uint64_t size); 134 | bool FreePool(HANDLE device_handle, uint64_t address); 135 | uint64_t GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string& function_name); 136 | bool ClearMmUnloadedDrivers(HANDLE device_handle); 137 | 138 | template 139 | bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments) 140 | { 141 | constexpr auto call_void = std::is_same_v; 142 | 143 | if constexpr (!call_void) 144 | { 145 | if (!out_result) 146 | return false; 147 | } 148 | else 149 | { 150 | UNREFERENCED_PARAMETER(out_result); 151 | } 152 | 153 | if (!kernel_function_address) 154 | return false; 155 | 156 | // Setup function call 157 | HMODULE ntdll = GetModuleHandle("ntdll.dll"); 158 | if (ntdll == 0) { 159 | std::cout << "[-] Failed to load ntdll.dll" << std::endl; //never should happens 160 | return false; 161 | } 162 | 163 | const auto NtQueryInformationAtom = reinterpret_cast(GetProcAddress(ntdll, "NtQueryInformationAtom")); 164 | if (!NtQueryInformationAtom) 165 | { 166 | std::cout << "[-] Failed to get export ntdll.NtQueryInformationAtom" << std::endl; 167 | return false; 168 | } 169 | 170 | uint8_t kernel_injected_jmp[] = { 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0 }; 171 | uint8_t original_kernel_function[sizeof(kernel_injected_jmp)]; 172 | *(uint64_t*)&kernel_injected_jmp[2] = kernel_function_address; 173 | 174 | const uint64_t kernel_NtQueryInformationAtom = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "NtQueryInformationAtom"); 175 | if (!kernel_NtQueryInformationAtom) 176 | { 177 | std::cout << "[-] Failed to get export ntoskrnl.NtQueryInformationAtom" << std::endl; 178 | return false; 179 | } 180 | 181 | if (!ReadMemory(device_handle, kernel_NtQueryInformationAtom, &original_kernel_function, sizeof(kernel_injected_jmp))) 182 | return false; 183 | 184 | // Overwrite the pointer with kernel_function_address 185 | if (!WriteToReadOnlyMemory(device_handle, kernel_NtQueryInformationAtom, &kernel_injected_jmp, sizeof(kernel_injected_jmp))) 186 | return false; 187 | 188 | // Call function 189 | if constexpr (!call_void) 190 | { 191 | using FunctionFn = T(__stdcall*)(A...); 192 | const auto Function = reinterpret_cast(NtQueryInformationAtom); 193 | 194 | *out_result = Function(arguments...); 195 | } 196 | else 197 | { 198 | using FunctionFn = void(__stdcall*)(A...); 199 | const auto Function = reinterpret_cast(NtQueryInformationAtom); 200 | 201 | Function(arguments...); 202 | } 203 | 204 | // Restore the pointer/jmp 205 | WriteToReadOnlyMemory(device_handle, kernel_NtQueryInformationAtom, original_kernel_function, sizeof(kernel_injected_jmp)); 206 | return true; 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /Kernel-DLL-Injector/kdmapper.cpp: -------------------------------------------------------------------------------- 1 | #include "kdmapper.hpp" 2 | #include "driver.hpp" 3 | 4 | uint64_t kdmapper::MapDriver(HANDLE iqvw64e_device_handle) 5 | { 6 | std::vector raw_image(sizeof(driver_byted)); 7 | memcpy(raw_image.data(), driver_byted, sizeof(driver_byted)); 8 | 9 | const PIMAGE_NT_HEADERS64 nt_headers = portable_executable::GetNtHeaders(raw_image.data()); 10 | 11 | if (!nt_headers) 12 | { 13 | std::cout << xor ("[-] Invalid format of PE image") << std::endl; 14 | return 0; 15 | } 16 | 17 | if (nt_headers->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) 18 | { 19 | std::cout << xor ("[-] Image is not 64 bit") << std::endl; 20 | return 0; 21 | } 22 | 23 | const uint32_t image_size = nt_headers->OptionalHeader.SizeOfImage; 24 | 25 | void* local_image_base = VirtualAlloc(nullptr, image_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 26 | if (!local_image_base) 27 | return 0; 28 | 29 | DWORD TotalVirtualHeaderSize = (IMAGE_FIRST_SECTION(nt_headers))->VirtualAddress; 30 | 31 | uint64_t kernel_image_base = intel_driver::AllocatePool(iqvw64e_device_handle, nt::POOL_TYPE::NonPagedPool, image_size - TotalVirtualHeaderSize); 32 | 33 | do 34 | { 35 | if (!kernel_image_base) 36 | { 37 | std::cout << xor ("[-] Failed to allocate remote image in kernel") << std::endl; 38 | break; 39 | } 40 | 41 | //std::cout << xor ("[+] Image base has been allocated at 0x") << reinterpret_cast(kernel_image_base) << std::endl; 42 | 43 | // Copy image headers 44 | 45 | memcpy(local_image_base, raw_image.data(), nt_headers->OptionalHeader.SizeOfHeaders); 46 | 47 | // Copy image sections 48 | 49 | const PIMAGE_SECTION_HEADER current_image_section = IMAGE_FIRST_SECTION(nt_headers); 50 | 51 | for (auto i = 0; i < nt_headers->FileHeader.NumberOfSections; ++i) 52 | { 53 | auto local_section = reinterpret_cast(reinterpret_cast(local_image_base) + current_image_section[i].VirtualAddress); 54 | memcpy(local_section, reinterpret_cast(reinterpret_cast(raw_image.data()) + current_image_section[i].PointerToRawData), current_image_section[i].SizeOfRawData); 55 | } 56 | 57 | uint64_t realBase = kernel_image_base; 58 | kernel_image_base -= TotalVirtualHeaderSize; 59 | 60 | //std::cout << xor ("[+] Skipped 0x") << std::hex << TotalVirtualHeaderSize << xor (" bytes of PE Header") << std::endl; 61 | 62 | // Resolve relocs and imports 63 | 64 | RelocateImageByDelta(portable_executable::GetRelocs(local_image_base), kernel_image_base - nt_headers->OptionalHeader.ImageBase); 65 | 66 | if (!ResolveImports(iqvw64e_device_handle, portable_executable::GetImports(local_image_base))) 67 | { 68 | std::cout << xor ("[-] Failed to resolve imports") << std::endl; 69 | kernel_image_base = realBase; 70 | break; 71 | } 72 | 73 | // Write fixed image to kernel 74 | 75 | if (!intel_driver::WriteMemory(iqvw64e_device_handle, realBase, (PVOID)((uintptr_t)local_image_base + TotalVirtualHeaderSize), image_size - TotalVirtualHeaderSize)) 76 | { 77 | std::cout << xor ("[-] Failed to write local image to remote image") << std::endl; 78 | kernel_image_base = realBase; 79 | break; 80 | } 81 | 82 | // Call driver entry point 83 | 84 | const uint64_t address_of_entry_point = kernel_image_base + nt_headers->OptionalHeader.AddressOfEntryPoint; 85 | 86 | std::cout << xor ("[<] Calling entry point...") << std::endl; 87 | 88 | NTSTATUS status = 0; 89 | 90 | if (!intel_driver::CallKernelFunction(iqvw64e_device_handle, &status, address_of_entry_point)) 91 | { 92 | std::cout << xor ("[-] Failed to call driver entry.") << std::endl; 93 | kernel_image_base = realBase; 94 | break; 95 | } 96 | 97 | if (!NT_SUCCESS(status)) 98 | { 99 | //SetKdRedColor(); 100 | std::cout << xor ("[-] Failed to init driver: Error 0x") << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << status << std::nouppercase << std::dec << std::endl; 101 | kernel_image_base = realBase; 102 | break; 103 | } 104 | 105 | //std::cout << xor ("[+] Driver returned 0x") << std::hex << std::setw(8) << std::setfill('0') << std::uppercase << status << std::nouppercase << std::dec << std::endl; 106 | 107 | VirtualFree(local_image_base, 0, MEM_RELEASE); 108 | return realBase; 109 | 110 | } while (false); 111 | 112 | 113 | VirtualFree(local_image_base, 0, MEM_RELEASE); 114 | 115 | intel_driver::FreePool(iqvw64e_device_handle, kernel_image_base); 116 | 117 | return 0; 118 | } 119 | 120 | void kdmapper::RelocateImageByDelta(portable_executable::vec_relocs relocs, const uint64_t delta) 121 | { 122 | for (const auto& current_reloc : relocs) 123 | { 124 | for (auto i = 0u; i < current_reloc.count; ++i) 125 | { 126 | const uint16_t type = current_reloc.item[i] >> 12; 127 | const uint16_t offset = current_reloc.item[i] & 0xFFF; 128 | 129 | if (type == IMAGE_REL_BASED_DIR64) 130 | * reinterpret_cast(current_reloc.address + offset) += delta; 131 | } 132 | } 133 | } 134 | 135 | bool kdmapper::ResolveImports(HANDLE iqvw64e_device_handle, portable_executable::vec_imports imports) 136 | { 137 | for (const auto& current_import : imports) 138 | { 139 | if (!utils::GetKernelModuleAddress(current_import.module_name)) 140 | { 141 | std::cout << xor ("[-] Dependency ") << current_import.module_name << xor (" wasn't found") << std::endl; 142 | return false; 143 | } 144 | 145 | for (auto& current_function_data : current_import.function_datas) 146 | { 147 | const uint64_t function_address = intel_driver::GetKernelModuleExport(iqvw64e_device_handle, utils::GetKernelModuleAddress(current_import.module_name), current_function_data.name); 148 | 149 | if (!function_address) 150 | { 151 | std::cout << xor ("[-] Failed to resolve import ") << current_function_data.name << " (" << current_import.module_name << ")" << std::endl; 152 | return false; 153 | } 154 | 155 | *current_function_data.address = function_address; 156 | } 157 | } 158 | 159 | return true; 160 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/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 | #include "xorstr.hpp" 15 | 16 | namespace kdmapper 17 | { 18 | uint64_t MapDriver(HANDLE iqvw64e_device_handle); 19 | void RelocateImageByDelta(portable_executable::vec_relocs relocs, const uint64_t delta); 20 | bool ResolveImports(HANDLE iqvw64e_device_handle, portable_executable::vec_imports imports); 21 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/lazy_importer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Justas Masiulis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // documentation is available at https://github.com/JustasMasiulis/lazy_importer 18 | 19 | #ifndef LAZY_IMPORTER_HPP 20 | #define LAZY_IMPORTER_HPP 21 | 22 | #define li(s) LI_FN(s).get() 23 | 24 | #define LI_FN(name) \ 25 | ::li::detail::lazy_function<::li::detail::khash(#name), decltype(&name)>() 26 | 27 | #define LI_FN_DEF(name) ::li::detail::lazy_function<::li::detail::khash(#name), name>() 28 | 29 | #define LI_MODULE(name) ::li::detail::lazy_module<::li::detail::khash(name)>() 30 | 31 | // NOTE only std::forward is used from this header. 32 | // If there is a need to eliminate this dependency the function itself is very small. 33 | #include 34 | #include 35 | #include 36 | 37 | #define JM_XORSTR_DISABLE_AVX_INTRINSICS 38 | 39 | #define _xor_(s) std::string(xorstr_(s)) 40 | 41 | #ifndef LAZY_IMPORTER_NO_FORCEINLINE 42 | #if defined(_MSC_VER) 43 | #define LAZY_IMPORTER_FORCEINLINE __forceinline 44 | #elif defined(__GNUC__) && __GNUC__ > 3 45 | #define LAZY_IMPORTER_FORCEINLINE inline __attribute__((__always_inline__)) 46 | #else 47 | #define LAZY_IMPORTER_FORCEINLINE inline 48 | #endif 49 | #else 50 | #define LAZY_IMPORTER_FORCEINLINE inline 51 | #endif 52 | 53 | #ifdef LAZY_IMPORTER_CASE_INSENSITIVE 54 | #define LAZY_IMPORTER_TOLOWER(c) (c >= 'A' && c <= 'Z' ? (c | (1 << 5)) : c) 55 | #else 56 | #define LAZY_IMPORTER_TOLOWER(c) (c) 57 | #endif 58 | 59 | namespace li { namespace detail { 60 | 61 | template 62 | struct pair { 63 | First first; 64 | Second second; 65 | }; 66 | 67 | namespace win { 68 | 69 | struct LIST_ENTRY_T { 70 | const char* Flink; 71 | const char* Blink; 72 | }; 73 | 74 | struct UNICODE_STRING_T { 75 | unsigned short Length; 76 | unsigned short MaximumLength; 77 | wchar_t* Buffer; 78 | }; 79 | 80 | struct PEB_LDR_DATA_T { 81 | unsigned long Length; 82 | unsigned long Initialized; 83 | const char* SsHandle; 84 | LIST_ENTRY_T InLoadOrderModuleList; 85 | }; 86 | 87 | struct PEB_T { 88 | unsigned char Reserved1[2]; 89 | unsigned char BeingDebugged; 90 | unsigned char Reserved2[1]; 91 | const char* Reserved3[2]; 92 | PEB_LDR_DATA_T* Ldr; 93 | }; 94 | 95 | struct LDR_DATA_TABLE_ENTRY_T { 96 | LIST_ENTRY_T InLoadOrderLinks; 97 | LIST_ENTRY_T InMemoryOrderLinks; 98 | LIST_ENTRY_T InInitializationOrderLinks; 99 | const char* DllBase; 100 | const char* EntryPoint; 101 | union { 102 | unsigned long SizeOfImage; 103 | const char* _dummy; 104 | }; 105 | UNICODE_STRING_T FullDllName; 106 | UNICODE_STRING_T BaseDllName; 107 | 108 | LAZY_IMPORTER_FORCEINLINE const LDR_DATA_TABLE_ENTRY_T* 109 | load_order_next() const noexcept 110 | { 111 | return reinterpret_cast( 112 | InLoadOrderLinks.Flink); 113 | } 114 | }; 115 | 116 | struct IMAGE_DOS_HEADER { // DOS .EXE header 117 | unsigned short e_magic; // Magic number 118 | unsigned short e_cblp; // BYTEs on last page of file 119 | unsigned short e_cp; // Pages in file 120 | unsigned short e_crlc; // Relocations 121 | unsigned short e_cparhdr; // Size of header in paragraphs 122 | unsigned short e_minalloc; // Minimum extra paragraphs needed 123 | unsigned short e_maxalloc; // Maximum extra paragraphs needed 124 | unsigned short e_ss; // Initial (relative) SS value 125 | unsigned short e_sp; // Initial SP value 126 | unsigned short e_csum; // Checksum 127 | unsigned short e_ip; // Initial IP value 128 | unsigned short e_cs; // Initial (relative) CS value 129 | unsigned short e_lfarlc; // File address of relocation table 130 | unsigned short e_ovno; // Overlay number 131 | unsigned short e_res[4]; // Reserved words 132 | unsigned short e_oemid; // OEM identifier (for e_oeminfo) 133 | unsigned short e_oeminfo; // OEM information; e_oemid specific 134 | unsigned short e_res2[10]; // Reserved words 135 | long e_lfanew; // File address of new exe header 136 | }; 137 | 138 | struct IMAGE_FILE_HEADER { 139 | unsigned short Machine; 140 | unsigned short NumberOfSections; 141 | unsigned long TimeDateStamp; 142 | unsigned long PointerToSymbolTable; 143 | unsigned long NumberOfSymbols; 144 | unsigned short SizeOfOptionalHeader; 145 | unsigned short Characteristics; 146 | }; 147 | 148 | struct IMAGE_EXPORT_DIRECTORY { 149 | unsigned long Characteristics; 150 | unsigned long TimeDateStamp; 151 | unsigned short MajorVersion; 152 | unsigned short MinorVersion; 153 | unsigned long Name; 154 | unsigned long Base; 155 | unsigned long NumberOfFunctions; 156 | unsigned long NumberOfNames; 157 | unsigned long AddressOfFunctions; // RVA from base of image 158 | unsigned long AddressOfNames; // RVA from base of image 159 | unsigned long AddressOfNameOrdinals; // RVA from base of image 160 | }; 161 | 162 | struct IMAGE_DATA_DIRECTORY { 163 | unsigned long VirtualAddress; 164 | unsigned long Size; 165 | }; 166 | 167 | struct IMAGE_OPTIONAL_HEADER64 { 168 | unsigned short Magic; 169 | unsigned char MajorLinkerVersion; 170 | unsigned char MinorLinkerVersion; 171 | unsigned long SizeOfCode; 172 | unsigned long SizeOfInitializedData; 173 | unsigned long SizeOfUninitializedData; 174 | unsigned long AddressOfEntryPoint; 175 | unsigned long BaseOfCode; 176 | unsigned long long ImageBase; 177 | unsigned long SectionAlignment; 178 | unsigned long FileAlignment; 179 | unsigned short MajorOperatingSystemVersion; 180 | unsigned short MinorOperatingSystemVersion; 181 | unsigned short MajorImageVersion; 182 | unsigned short MinorImageVersion; 183 | unsigned short MajorSubsystemVersion; 184 | unsigned short MinorSubsystemVersion; 185 | unsigned long Win32VersionValue; 186 | unsigned long SizeOfImage; 187 | unsigned long SizeOfHeaders; 188 | unsigned long CheckSum; 189 | unsigned short Subsystem; 190 | unsigned short DllCharacteristics; 191 | unsigned long long SizeOfStackReserve; 192 | unsigned long long SizeOfStackCommit; 193 | unsigned long long SizeOfHeapReserve; 194 | unsigned long long SizeOfHeapCommit; 195 | unsigned long LoaderFlags; 196 | unsigned long NumberOfRvaAndSizes; 197 | IMAGE_DATA_DIRECTORY DataDirectory[16]; 198 | }; 199 | 200 | struct IMAGE_OPTIONAL_HEADER32 { 201 | unsigned short Magic; 202 | unsigned char MajorLinkerVersion; 203 | unsigned char MinorLinkerVersion; 204 | unsigned long SizeOfCode; 205 | unsigned long SizeOfInitializedData; 206 | unsigned long SizeOfUninitializedData; 207 | unsigned long AddressOfEntryPoint; 208 | unsigned long BaseOfCode; 209 | unsigned long BaseOfData; 210 | unsigned long ImageBase; 211 | unsigned long SectionAlignment; 212 | unsigned long FileAlignment; 213 | unsigned short MajorOperatingSystemVersion; 214 | unsigned short MinorOperatingSystemVersion; 215 | unsigned short MajorImageVersion; 216 | unsigned short MinorImageVersion; 217 | unsigned short MajorSubsystemVersion; 218 | unsigned short MinorSubsystemVersion; 219 | unsigned long Win32VersionValue; 220 | unsigned long SizeOfImage; 221 | unsigned long SizeOfHeaders; 222 | unsigned long CheckSum; 223 | unsigned short Subsystem; 224 | unsigned short DllCharacteristics; 225 | unsigned long SizeOfStackReserve; 226 | unsigned long SizeOfStackCommit; 227 | unsigned long SizeOfHeapReserve; 228 | unsigned long SizeOfHeapCommit; 229 | unsigned long LoaderFlags; 230 | unsigned long NumberOfRvaAndSizes; 231 | IMAGE_DATA_DIRECTORY DataDirectory[16]; 232 | }; 233 | 234 | struct IMAGE_NT_HEADERS { 235 | unsigned long Signature; 236 | IMAGE_FILE_HEADER FileHeader; 237 | #ifdef _WIN64 238 | IMAGE_OPTIONAL_HEADER64 OptionalHeader; 239 | #else 240 | IMAGE_OPTIONAL_HEADER32 OptionalHeader; 241 | #endif 242 | }; 243 | 244 | } // namespace win 245 | 246 | // hashing stuff 247 | struct hash_t { 248 | using value_type = unsigned long; 249 | constexpr static value_type offset = 2166136261; 250 | constexpr static value_type prime = 16777619; 251 | constexpr static unsigned long long prime64 = prime; 252 | 253 | LAZY_IMPORTER_FORCEINLINE constexpr static value_type single(value_type value, 254 | char c) noexcept 255 | { 256 | return static_cast( 257 | (value ^ LAZY_IMPORTER_TOLOWER(c)) * 258 | static_cast(prime)); 259 | } 260 | }; 261 | 262 | template 263 | LAZY_IMPORTER_FORCEINLINE constexpr hash_t::value_type 264 | khash(const CharT* str, hash_t::value_type value = hash_t::offset) noexcept 265 | { 266 | return (*str ? khash(str + 1, hash_t::single(value, *str)) : value); 267 | } 268 | 269 | template 270 | LAZY_IMPORTER_FORCEINLINE hash_t::value_type hash(const CharT* str) noexcept 271 | { 272 | hash_t::value_type value = hash_t::offset; 273 | 274 | for(;;) { 275 | char c = *str++; 276 | if(!c) 277 | return value; 278 | value = hash_t::single(value, c); 279 | } 280 | } 281 | 282 | LAZY_IMPORTER_FORCEINLINE hash_t::value_type hash( 283 | const win::UNICODE_STRING_T& str) noexcept 284 | { 285 | auto first = str.Buffer; 286 | const auto last = first + (str.Length / sizeof(wchar_t)); 287 | auto value = hash_t::offset; 288 | for(; first != last; ++first) 289 | value = hash_t::single(value, static_cast(*first)); 290 | 291 | return value; 292 | } 293 | 294 | LAZY_IMPORTER_FORCEINLINE pair hash_forwarded( 295 | const char* str) noexcept 296 | { 297 | pair module_and_function{ 298 | hash_t::offset, hash_t::offset 299 | }; 300 | 301 | for(; *str != '.'; ++str) 302 | hash_t::single(module_and_function.first, *str); 303 | 304 | ++str; 305 | 306 | for(; *str; ++str) 307 | hash_t::single(module_and_function.second, *str); 308 | 309 | return module_and_function; 310 | } 311 | 312 | 313 | // some helper functions 314 | LAZY_IMPORTER_FORCEINLINE const win::PEB_T* peb() noexcept 315 | { 316 | #if defined(_WIN64) 317 | return reinterpret_cast(__readgsqword(0x60)); 318 | #elif defined(_WIN32) 319 | return reinterpret_cast(__readfsdword(0x30)); 320 | #else 321 | #error Unsupported platform. Open an issue and I'll probably add support. 322 | #endif 323 | } 324 | 325 | LAZY_IMPORTER_FORCEINLINE const win::PEB_LDR_DATA_T* ldr() 326 | { 327 | return reinterpret_cast(peb()->Ldr); 328 | } 329 | 330 | LAZY_IMPORTER_FORCEINLINE const win::IMAGE_NT_HEADERS* nt_headers( 331 | const char* base) noexcept 332 | { 333 | return reinterpret_cast( 334 | base + reinterpret_cast(base)->e_lfanew); 335 | } 336 | 337 | LAZY_IMPORTER_FORCEINLINE const win::IMAGE_EXPORT_DIRECTORY* image_export_dir( 338 | const char* base) noexcept 339 | { 340 | return reinterpret_cast( 341 | base + nt_headers(base)->OptionalHeader.DataDirectory->VirtualAddress); 342 | } 343 | 344 | LAZY_IMPORTER_FORCEINLINE const win::LDR_DATA_TABLE_ENTRY_T* ldr_data_entry() noexcept 345 | { 346 | return reinterpret_cast( 347 | ldr()->InLoadOrderModuleList.Flink); 348 | } 349 | 350 | struct exports_directory { 351 | const char* _base; 352 | const win::IMAGE_EXPORT_DIRECTORY* _ied; 353 | unsigned long _ied_size; 354 | 355 | public: 356 | using size_type = unsigned long; 357 | 358 | LAZY_IMPORTER_FORCEINLINE 359 | exports_directory(const char* base) noexcept : _base(base) 360 | { 361 | const auto ied_data_dir = nt_headers(base)->OptionalHeader.DataDirectory[0]; 362 | _ied = reinterpret_cast( 363 | base + ied_data_dir.VirtualAddress); 364 | _ied_size = ied_data_dir.Size; 365 | } 366 | 367 | LAZY_IMPORTER_FORCEINLINE explicit operator bool() const noexcept 368 | { 369 | return reinterpret_cast(_ied) != _base; 370 | } 371 | 372 | LAZY_IMPORTER_FORCEINLINE size_type size() const noexcept 373 | { 374 | return _ied->NumberOfNames; 375 | } 376 | 377 | LAZY_IMPORTER_FORCEINLINE const char* base() const noexcept { return _base; } 378 | LAZY_IMPORTER_FORCEINLINE const win::IMAGE_EXPORT_DIRECTORY* ied() const noexcept 379 | { 380 | return _ied; 381 | } 382 | 383 | LAZY_IMPORTER_FORCEINLINE const char* name(size_type index) const noexcept 384 | { 385 | return reinterpret_cast( 386 | _base + reinterpret_cast( 387 | _base + _ied->AddressOfNames)[index]); 388 | } 389 | 390 | LAZY_IMPORTER_FORCEINLINE const char* address(size_type index) const noexcept 391 | { 392 | const auto* const rva_table = 393 | reinterpret_cast(_base + _ied->AddressOfFunctions); 394 | 395 | const auto* const ord_table = reinterpret_cast( 396 | _base + _ied->AddressOfNameOrdinals); 397 | 398 | return _base + rva_table[ord_table[index]]; 399 | } 400 | 401 | LAZY_IMPORTER_FORCEINLINE bool is_forwarded(const char* export_address) const 402 | noexcept 403 | { 404 | const auto ui_ied = reinterpret_cast(_ied); 405 | return (export_address > ui_ied && export_address < ui_ied + _ied_size); 406 | } 407 | }; 408 | 409 | struct safe_module_enumerator { 410 | using value_type = const detail::win::LDR_DATA_TABLE_ENTRY_T; 411 | value_type* value; 412 | value_type* const head; 413 | 414 | LAZY_IMPORTER_FORCEINLINE safe_module_enumerator() noexcept 415 | : value(ldr_data_entry()), head(value) 416 | {} 417 | 418 | LAZY_IMPORTER_FORCEINLINE void reset() noexcept { value = head; } 419 | 420 | LAZY_IMPORTER_FORCEINLINE bool next() noexcept 421 | { 422 | value = value->load_order_next(); 423 | return value != head; 424 | } 425 | }; 426 | 427 | struct unsafe_module_enumerator { 428 | using value_type = const detail::win::LDR_DATA_TABLE_ENTRY_T*; 429 | value_type value; 430 | 431 | LAZY_IMPORTER_FORCEINLINE unsafe_module_enumerator() noexcept 432 | : value(ldr_data_entry()) 433 | {} 434 | 435 | LAZY_IMPORTER_FORCEINLINE void reset() noexcept { value = ldr_data_entry(); } 436 | 437 | LAZY_IMPORTER_FORCEINLINE bool next() noexcept 438 | { 439 | value = value->load_order_next(); 440 | return true; 441 | } 442 | }; 443 | 444 | // provides the cached functions which use Derive classes methods 445 | template 446 | class lazy_base { 447 | protected: 448 | // This function is needed because every templated function 449 | // with different args has its own static buffer 450 | LAZY_IMPORTER_FORCEINLINE static void*& _cache() noexcept 451 | { 452 | static void* value = nullptr; 453 | return value; 454 | } 455 | 456 | public: 457 | template 458 | LAZY_IMPORTER_FORCEINLINE static T safe() noexcept 459 | { 460 | return Derived::template get(); 461 | } 462 | 463 | template 464 | LAZY_IMPORTER_FORCEINLINE static T cached() noexcept 465 | { 466 | auto& cached = _cache(); 467 | if(!cached) 468 | cached = Derived::template get(); 469 | 470 | return (T)(cached); 471 | } 472 | 473 | template 474 | LAZY_IMPORTER_FORCEINLINE static T safe_cached() noexcept 475 | { 476 | return cached(); 477 | } 478 | }; 479 | 480 | template 481 | struct lazy_module : lazy_base> { 482 | template 483 | LAZY_IMPORTER_FORCEINLINE static T get() noexcept 484 | { 485 | Enum e; 486 | do { 487 | if(hash(e.value->BaseDllName) == Hash) 488 | return (T)(e.value->DllBase); 489 | } while(e.next()); 490 | return {}; 491 | } 492 | }; 493 | 494 | template 495 | struct lazy_function : lazy_base, T> { 496 | using base_type = lazy_base, T>; 497 | 498 | template 499 | LAZY_IMPORTER_FORCEINLINE decltype(auto) operator()(Args&&... args) const 500 | { 501 | #ifndef LAZY_IMPORTER_CACHE_OPERATOR_PARENS 502 | return get()(std::forward(args)...); 503 | #else 504 | return this->cached()(std::forward(args)...); 505 | #endif 506 | } 507 | 508 | template 509 | LAZY_IMPORTER_FORCEINLINE static F get() noexcept 510 | { 511 | // for backwards compatability. 512 | // Before 2.0 it was only possible to resolve forwarded exports when 513 | // this macro was enabled 514 | #ifdef LAZY_IMPORTER_RESOLVE_FORWARDED_EXPORTS 515 | return forwarded(); 516 | #else 517 | Enum e; 518 | do { 519 | const exports_directory exports(e.value->DllBase); 520 | 521 | if(exports) { 522 | auto export_index = exports.size(); 523 | while(export_index--) 524 | if(hash(exports.name(export_index)) == Hash) 525 | return (F)(exports.address(export_index)); 526 | } 527 | } while(e.next()); 528 | return {}; 529 | #endif 530 | } 531 | 532 | template 533 | LAZY_IMPORTER_FORCEINLINE static F forwarded() noexcept 534 | { 535 | detail::win::UNICODE_STRING_T name; 536 | hash_t::value_type module_hash = 0; 537 | auto function_hash = Hash; 538 | 539 | Enum e; 540 | do { 541 | name = e.value->BaseDllName; 542 | name.Length -= 8; // get rid of .dll extension 543 | 544 | if(!module_hash || hash(name) == module_hash) { 545 | const exports_directory exports(e.value->DllBase); 546 | 547 | if(exports) { 548 | auto export_index = exports.size(); 549 | while(export_index--) 550 | if(hash(exports.name(export_index)) == function_hash) { 551 | const auto addr = exports.address(export_index); 552 | 553 | if(exports.is_forwarded(addr)) { 554 | auto hashes = hash_forwarded( 555 | reinterpret_cast(addr)); 556 | 557 | function_hash = hashes.second; 558 | module_hash = hashes.first; 559 | 560 | e.reset(); 561 | break; 562 | } 563 | return (F)(addr); 564 | } 565 | } 566 | } 567 | } while(e.next()); 568 | return {}; 569 | } 570 | 571 | template 572 | LAZY_IMPORTER_FORCEINLINE static F forwarded_safe() noexcept 573 | { 574 | return forwarded(); 575 | } 576 | 577 | template 578 | LAZY_IMPORTER_FORCEINLINE static F forwarded_cached() noexcept 579 | { 580 | auto& value = base_type::_cache(); 581 | if(!value) 582 | value = forwarded(); 583 | return (F)(value); 584 | } 585 | 586 | template 587 | LAZY_IMPORTER_FORCEINLINE static F forwarded_safe_cached() noexcept 588 | { 589 | return forwarded_cached(); 590 | } 591 | 592 | template 593 | LAZY_IMPORTER_FORCEINLINE static F in(Module m) noexcept 594 | { 595 | if(IsSafe && !m) 596 | return {}; 597 | 598 | const exports_directory exports((const char*)(m)); 599 | if(IsSafe && !exports) 600 | return {}; 601 | 602 | for(unsigned long i{};; ++i) { 603 | if(IsSafe && i == exports.size()) 604 | break; 605 | 606 | if(hash(exports.name(i)) == Hash) 607 | return (F)(exports.address(i)); 608 | } 609 | return {}; 610 | } 611 | 612 | template 613 | LAZY_IMPORTER_FORCEINLINE static F in_safe(Module m) noexcept 614 | { 615 | return in(m); 616 | } 617 | 618 | template 619 | LAZY_IMPORTER_FORCEINLINE static F in_cached(Module m) noexcept 620 | { 621 | auto& value = base_type::_cache(); 622 | if(!value) 623 | value = in(m); 624 | return (F)(value); 625 | } 626 | 627 | template 628 | LAZY_IMPORTER_FORCEINLINE static F in_safe_cached(Module m) noexcept 629 | { 630 | return in_cached(m); 631 | } 632 | 633 | template 634 | LAZY_IMPORTER_FORCEINLINE static F nt() noexcept 635 | { 636 | return in(ldr_data_entry()->load_order_next()->DllBase); 637 | } 638 | 639 | template 640 | LAZY_IMPORTER_FORCEINLINE static F nt_safe() noexcept 641 | { 642 | return in_safe(ldr_data_entry()->load_order_next()->DllBase); 643 | } 644 | 645 | template 646 | LAZY_IMPORTER_FORCEINLINE static F nt_cached() noexcept 647 | { 648 | return in_cached(ldr_data_entry()->load_order_next()->DllBase); 649 | } 650 | 651 | template 652 | LAZY_IMPORTER_FORCEINLINE static F nt_safe_cached() noexcept 653 | { 654 | return in_safe_cached(ldr_data_entry()->load_order_next()->DllBase); 655 | } 656 | }; 657 | 658 | }} // namespace li::detail 659 | 660 | #endif // include guard 661 | -------------------------------------------------------------------------------- /Kernel-DLL-Injector/nt.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #pragma comment(lib, "ntdll.lib") 5 | 6 | namespace nt 7 | { 8 | constexpr auto PAGE_SIZE = 0x1000; 9 | constexpr auto STATUS_INFO_LENGTH_MISMATCH = 0xC0000004; 10 | 11 | constexpr auto SystemModuleInformation = 11; 12 | constexpr auto SystemHandleInformation = 16; 13 | constexpr auto SystemExtendedHandleInformation = 64; 14 | 15 | typedef NTSTATUS(*NtLoadDriver)(PUNICODE_STRING DriverServiceName); 16 | typedef NTSTATUS(*NtUnloadDriver)(PUNICODE_STRING DriverServiceName); 17 | typedef NTSTATUS(*RtlAdjustPrivilege)(_In_ ULONG Privilege, _In_ BOOLEAN Enable, _In_ BOOLEAN Client, _Out_ PBOOLEAN WasEnabled); 18 | 19 | typedef struct _SYSTEM_HANDLE 20 | { 21 | PVOID Object; 22 | HANDLE UniqueProcessId; 23 | HANDLE HandleValue; 24 | ULONG GrantedAccess; 25 | USHORT CreatorBackTraceIndex; 26 | USHORT ObjectTypeIndex; 27 | ULONG HandleAttributes; 28 | ULONG Reserved; 29 | } SYSTEM_HANDLE, *PSYSTEM_HANDLE; 30 | 31 | typedef struct _SYSTEM_HANDLE_INFORMATION_EX 32 | { 33 | ULONG_PTR HandleCount; 34 | ULONG_PTR Reserved; 35 | SYSTEM_HANDLE Handles[1]; 36 | } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; 37 | 38 | typedef enum class _POOL_TYPE { 39 | NonPagedPool, 40 | NonPagedPoolExecute, 41 | PagedPool, 42 | NonPagedPoolMustSucceed, 43 | DontUseThisType, 44 | NonPagedPoolCacheAligned, 45 | PagedPoolCacheAligned, 46 | NonPagedPoolCacheAlignedMustS, 47 | MaxPoolType, 48 | NonPagedPoolBase, 49 | NonPagedPoolBaseMustSucceed, 50 | NonPagedPoolBaseCacheAligned, 51 | NonPagedPoolBaseCacheAlignedMustS, 52 | NonPagedPoolSession, 53 | PagedPoolSession, 54 | NonPagedPoolMustSucceedSession, 55 | DontUseThisTypeSession, 56 | NonPagedPoolCacheAlignedSession, 57 | PagedPoolCacheAlignedSession, 58 | NonPagedPoolCacheAlignedMustSSession, 59 | NonPagedPoolNx, 60 | NonPagedPoolNxCacheAligned, 61 | NonPagedPoolSessionNx 62 | } POOL_TYPE; 63 | 64 | typedef struct _RTL_PROCESS_MODULE_INFORMATION 65 | { 66 | HANDLE Section; 67 | PVOID MappedBase; 68 | PVOID ImageBase; 69 | ULONG ImageSize; 70 | ULONG Flags; 71 | USHORT LoadOrderIndex; 72 | USHORT InitOrderIndex; 73 | USHORT LoadCount; 74 | USHORT OffsetToFileName; 75 | UCHAR FullPathName[256]; 76 | } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; 77 | 78 | typedef struct _RTL_PROCESS_MODULES 79 | { 80 | ULONG NumberOfModules; 81 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 82 | } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; 83 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/portable_executable.cpp: -------------------------------------------------------------------------------- 1 | #include "portable_executable.hpp" 2 | 3 | PIMAGE_NT_HEADERS64 portable_executable::GetNtHeaders(void* image_base) 4 | { 5 | const auto dos_header = reinterpret_cast(image_base); 6 | 7 | if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) 8 | return nullptr; 9 | 10 | const auto nt_headers = reinterpret_cast(reinterpret_cast(image_base) + dos_header->e_lfanew); 11 | 12 | if (nt_headers->Signature != IMAGE_NT_SIGNATURE) 13 | return nullptr; 14 | 15 | return nt_headers; 16 | } 17 | 18 | portable_executable::vec_relocs portable_executable::GetRelocs(void* image_base) 19 | { 20 | const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base); 21 | 22 | if (!nt_headers) 23 | return {}; 24 | 25 | vec_relocs relocs; 26 | DWORD reloc_va = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; 27 | 28 | if (!reloc_va) 29 | return {}; 30 | 31 | auto current_base_relocation = reinterpret_cast(reinterpret_cast(image_base) + reloc_va); 32 | const auto reloc_end = reinterpret_cast(current_base_relocation) + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 33 | 34 | while (current_base_relocation->VirtualAddress && current_base_relocation->VirtualAddress < reloc_end && current_base_relocation->SizeOfBlock) 35 | { 36 | RelocInfo reloc_info; 37 | 38 | reloc_info.address = reinterpret_cast(image_base) + current_base_relocation->VirtualAddress; 39 | reloc_info.item = reinterpret_cast(reinterpret_cast(current_base_relocation) + sizeof(IMAGE_BASE_RELOCATION)); 40 | reloc_info.count = (current_base_relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(uint16_t); 41 | 42 | relocs.push_back(reloc_info); 43 | 44 | current_base_relocation = reinterpret_cast(reinterpret_cast(current_base_relocation) + current_base_relocation->SizeOfBlock); 45 | } 46 | 47 | return relocs; 48 | } 49 | 50 | portable_executable::vec_imports portable_executable::GetImports(void* image_base) 51 | { 52 | const PIMAGE_NT_HEADERS64 nt_headers = GetNtHeaders(image_base); 53 | 54 | if (!nt_headers) 55 | return {}; 56 | 57 | DWORD import_va = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 58 | 59 | if (!import_va) 60 | return {}; 61 | 62 | vec_imports imports; 63 | 64 | auto current_import_descriptor = reinterpret_cast(reinterpret_cast(image_base) + import_va); 65 | 66 | while (current_import_descriptor->FirstThunk) 67 | { 68 | ImportInfo import_info; 69 | 70 | import_info.module_name = std::string(reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->Name)); 71 | 72 | auto current_first_thunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->FirstThunk); 73 | auto current_originalFirstThunk = reinterpret_cast(reinterpret_cast(image_base) + current_import_descriptor->OriginalFirstThunk); 74 | 75 | while (current_originalFirstThunk->u1.Function) 76 | { 77 | ImportFunctionInfo import_function_data; 78 | 79 | auto thunk_data = reinterpret_cast(reinterpret_cast(image_base) + current_originalFirstThunk->u1.AddressOfData); 80 | 81 | import_function_data.name = thunk_data->Name; 82 | import_function_data.address = ¤t_first_thunk->u1.Function; 83 | 84 | import_info.function_datas.push_back(import_function_data); 85 | 86 | ++current_originalFirstThunk; 87 | ++current_first_thunk; 88 | } 89 | 90 | imports.push_back(import_info); 91 | ++current_import_descriptor; 92 | } 93 | 94 | return imports; 95 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/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 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/service.cpp: -------------------------------------------------------------------------------- 1 | #include "service.hpp" 2 | #include "xorstr.hpp" 3 | 4 | bool service::RegisterAndStart(const std::string& driver_path) 5 | { 6 | const static DWORD ServiceTypeKernel = 1; 7 | const std::string driver_name = std::filesystem::path(driver_path).filename().string(); 8 | const std::string servicesPath = "SYSTEM\\CurrentControlSet\\Services\\" + driver_name; 9 | const std::string nPath = "\\??\\" + driver_path; 10 | 11 | HKEY dservice; 12 | LSTATUS status = RegCreateKey(HKEY_LOCAL_MACHINE, servicesPath.c_str(), &dservice); 13 | if (status != ERROR_SUCCESS) 14 | { 15 | printf(xor ("[-] Can't create service key\n")); 16 | return false; 17 | } 18 | 19 | status = RegSetKeyValue(dservice, NULL, "ImagePath", REG_EXPAND_SZ, nPath.c_str(), (DWORD)nPath.size()); 20 | if (status != ERROR_SUCCESS) 21 | { 22 | RegCloseKey(dservice); 23 | printf(xor ("[-] Can't create 'ImagePath' registry value\n")); 24 | return false; 25 | } 26 | 27 | status = RegSetKeyValue(dservice, NULL, "Type", REG_DWORD, &ServiceTypeKernel, sizeof(DWORD)); 28 | if (status != ERROR_SUCCESS) 29 | { 30 | RegCloseKey(dservice); 31 | printf(xor ("[-] Can't create 'Type' registry value\n")); 32 | return false; 33 | } 34 | 35 | RegCloseKey(dservice); 36 | 37 | HMODULE ntdll = GetModuleHandle("ntdll.dll"); 38 | if (ntdll == NULL) { 39 | return false; 40 | } 41 | 42 | auto RtlAdjustPrivilege = (nt::RtlAdjustPrivilege)GetProcAddress(ntdll, "RtlAdjustPrivilege"); 43 | auto NtLoadDriver = (nt::NtLoadDriver)GetProcAddress(ntdll, "NtLoadDriver"); 44 | 45 | ULONG SE_LOAD_DRIVER_PRIVILEGE = 10UL; 46 | BOOLEAN SeLoadDriverWasEnabled; 47 | NTSTATUS Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &SeLoadDriverWasEnabled); 48 | if (!NT_SUCCESS(Status)) 49 | { 50 | printf(xor ("Fatal error: failed to acquire SE_LOAD_DRIVER_PRIVILEGE. Make sure you are running as administrator.\n")); 51 | return false; 52 | } 53 | 54 | std::wstring wdriver_name(driver_name.begin(), driver_name.end()); 55 | wdriver_name = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + wdriver_name; 56 | UNICODE_STRING serviceStr; 57 | RtlInitUnicodeString(&serviceStr, wdriver_name.c_str()); 58 | 59 | Status = NtLoadDriver(&serviceStr); 60 | printf(xor ("[+] NtLoadDriver Status 0x%lx\n"), Status); 61 | return NT_SUCCESS(Status); 62 | } 63 | 64 | bool service::StopAndRemove(const std::string& driver_name) 65 | { 66 | HMODULE ntdll = GetModuleHandleA("ntdll.dll"); 67 | if (ntdll == NULL) 68 | return false; 69 | 70 | std::wstring wdriver_name(driver_name.begin(), driver_name.end()); 71 | wdriver_name = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + wdriver_name; 72 | UNICODE_STRING serviceStr; 73 | RtlInitUnicodeString(&serviceStr, wdriver_name.c_str()); 74 | 75 | HKEY driver_service; 76 | std::string servicesPath = "SYSTEM\\CurrentControlSet\\Services\\" + driver_name; 77 | LSTATUS status = RegOpenKey(HKEY_LOCAL_MACHINE, servicesPath.c_str(), &driver_service); 78 | if (status != ERROR_SUCCESS) 79 | { 80 | if (status == ERROR_FILE_NOT_FOUND) { 81 | return true; 82 | } 83 | return false; 84 | } 85 | RegCloseKey(driver_service); 86 | 87 | auto NtUnloadDriver = (nt::NtUnloadDriver)GetProcAddress(ntdll, "NtUnloadDriver"); 88 | NTSTATUS st = NtUnloadDriver(&serviceStr); 89 | printf(xor ("[+] NtUnloadDriver Status 0x%lx\n"), st); 90 | if (st != 0x0) { 91 | printf(xor ("[-] Driver Unload Failed!!\n")); 92 | } 93 | 94 | 95 | status = RegDeleteKey(HKEY_LOCAL_MACHINE, servicesPath.c_str()); 96 | if (status != ERROR_SUCCESS) 97 | { 98 | return false; 99 | } 100 | return true; 101 | } 102 | -------------------------------------------------------------------------------- /Kernel-DLL-Injector/service.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "intel_driver.hpp" 6 | 7 | namespace service 8 | { 9 | bool RegisterAndStart(const std::string& driver_path); 10 | bool StopAndRemove(const std::string& driver_name); 11 | }; -------------------------------------------------------------------------------- /Kernel-DLL-Injector/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 | } 69 | 70 | BOOLEAN utils::bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask) { 71 | for (; *szMask; ++szMask, ++pData, ++bMask) 72 | if (*szMask == 'x' && *pData != *bMask) 73 | return 0; 74 | return (*szMask) == 0; 75 | } 76 | 77 | uintptr_t utils::FindPattern(uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, char* szMask) { 78 | size_t max_len = dwLen - strlen(szMask); 79 | for (uintptr_t i = 0; i < max_len; i++) 80 | if (bDataCompare((BYTE*)(dwAddress + i), bMask, szMask)) 81 | return (uintptr_t)(dwAddress + i); 82 | return 0; 83 | } 84 | 85 | PVOID utils::FindSection(char* sectionName, uintptr_t modulePtr, PULONG size) { 86 | size_t namelength = strlen(sectionName); 87 | PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)(modulePtr + ((PIMAGE_DOS_HEADER)modulePtr)->e_lfanew); 88 | PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(headers); 89 | for (DWORD i = 0; i < headers->FileHeader.NumberOfSections; ++i) { 90 | PIMAGE_SECTION_HEADER section = §ions[i]; 91 | if (memcmp(section->Name, sectionName, namelength) == 0 && 92 | namelength == strlen((char*)section->Name)) { 93 | if (size) { 94 | *size = section->Misc.VirtualSize; 95 | } 96 | return (PVOID)(modulePtr + section->VirtualAddress); 97 | } 98 | } 99 | return 0; 100 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/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 | BOOLEAN bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask); 18 | uintptr_t FindPattern(uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, char* szMask); 19 | PVOID FindSection(char* sectionName, uintptr_t modulePtr, PULONG size); 20 | } -------------------------------------------------------------------------------- /Kernel-DLL-Injector/xorstr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2018 Justas Masiulis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef JM_XORSTR_HPP 18 | #define JM_XORSTR_HPP 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define xorstr(str) \ 26 | ::jm::make_xorstr( \ 27 | []() { return str; }, \ 28 | std::make_index_sequence{}, \ 29 | std::make_index_sequence<::jm::detail::_buffer_size()>{}) 30 | #define xor(str) xorstr(str).crypt_get() 31 | 32 | #ifdef _MSC_VER 33 | #define XORSTR_FORCEINLINE __forceinline 34 | #else 35 | #define XORSTR_FORCEINLINE __attribute__((always_inline)) 36 | #endif 37 | 38 | // you can define this macro to get possibly faster code on gcc/clang 39 | // at the expense of constants being put into data section. 40 | #if !defined(XORSTR_ALLOW_DATA) 41 | // MSVC - no volatile 42 | // GCC and clang - volatile everywhere 43 | #if defined(__clang__) || defined(__GNUC__) 44 | #define XORSTR_VOLATILE volatile 45 | #endif 46 | 47 | #endif 48 | #ifndef XORSTR_VOLATILE 49 | #define XORSTR_VOLATILE 50 | #endif 51 | 52 | namespace jm { 53 | 54 | namespace detail { 55 | 56 | template 57 | struct unsigned_; 58 | 59 | template<> 60 | struct unsigned_<1> { 61 | using type = std::uint8_t; 62 | }; 63 | template<> 64 | struct unsigned_<2> { 65 | using type = std::uint16_t; 66 | }; 67 | template<> 68 | struct unsigned_<4> { 69 | using type = std::uint32_t; 70 | }; 71 | 72 | template 73 | struct pack_value_type { 74 | using type = decltype(C); 75 | }; 76 | 77 | template 78 | constexpr std::size_t _buffer_size() 79 | { 80 | return ((Size / 16) + (Size % 16 != 0)) * 2; 81 | } 82 | 83 | template 84 | struct tstring_ { 85 | using value_type = typename pack_value_type::type; 86 | constexpr static std::size_t size = sizeof...(Cs); 87 | constexpr static value_type str[size] = { Cs... }; 88 | 89 | constexpr static std::size_t buffer_size = _buffer_size(); 90 | constexpr static std::size_t buffer_align = 91 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS 92 | ((sizeof(str) > 16) ? 32 : 16); 93 | #else 94 | 16; 95 | #endif 96 | }; 97 | 98 | template 99 | struct _ki { 100 | constexpr static std::size_t idx = I; 101 | constexpr static std::uint64_t key = K; 102 | }; 103 | 104 | template 105 | constexpr std::uint32_t key4() noexcept 106 | { 107 | std::uint32_t value = Seed; 108 | for (char c : __TIME__) 109 | value = static_cast((value ^ c) * 16777619ull); 110 | return value; 111 | } 112 | 113 | template 114 | constexpr std::uint64_t key8() 115 | { 116 | constexpr auto first_part = key4<2166136261 + S>(); 117 | constexpr auto second_part = key4(); 118 | return (static_cast(first_part) << 32) | second_part; 119 | } 120 | 121 | // clang and gcc try really hard to place the constants in data 122 | // sections. to counter that there was a need to create an intermediate 123 | // constexpr string and then copy it into a non constexpr container with 124 | // volatile storage so that the constants would be placed directly into 125 | // code. 126 | template 127 | struct string_storage { 128 | std::uint64_t storage[T::buffer_size]; 129 | 130 | XORSTR_FORCEINLINE constexpr string_storage() noexcept : storage{ Keys... } 131 | { 132 | using cast_type = 133 | typename unsigned_::type; 134 | constexpr auto value_size = sizeof(typename T::value_type); 135 | // puts the string into 64 bit integer blocks in a constexpr 136 | // fashion 137 | for (std::size_t i = 0; i < T::size; ++i) 138 | storage[i / (8 / value_size)] ^= 139 | (std::uint64_t{ static_cast(T::str[i]) } 140 | << ((i % (8 / value_size)) * 8 * value_size)); 141 | } 142 | }; 143 | 144 | } // namespace detail 145 | 146 | template 147 | class xor_string { 148 | alignas(T::buffer_align) std::uint64_t _storage[T::buffer_size]; 149 | 150 | // _single functions needed because MSVC crashes without them 151 | XORSTR_FORCEINLINE void _crypt_256_single(const std::uint64_t* keys, 152 | std::uint64_t* storage) noexcept 153 | 154 | { 155 | _mm256_store_si256( 156 | reinterpret_cast<__m256i*>(storage), 157 | _mm256_xor_si256( 158 | _mm256_load_si256(reinterpret_cast(storage)), 159 | _mm256_load_si256(reinterpret_cast(keys)))); 160 | } 161 | 162 | template 163 | XORSTR_FORCEINLINE void _crypt_256(const std::uint64_t* keys, 164 | std::index_sequence) noexcept 165 | { 166 | (_crypt_256_single(keys + Idxs * 4, _storage + Idxs * 4), ...); 167 | } 168 | 169 | XORSTR_FORCEINLINE void _crypt_128_single(const std::uint64_t* keys, 170 | std::uint64_t* storage) noexcept 171 | { 172 | _mm_store_si128( 173 | reinterpret_cast<__m128i*>(storage), 174 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(storage)), 175 | _mm_load_si128(reinterpret_cast(keys)))); 176 | } 177 | 178 | template 179 | XORSTR_FORCEINLINE void _crypt_128(const std::uint64_t* keys, 180 | std::index_sequence) noexcept 181 | { 182 | (_crypt_128_single(keys + Idxs * 2, _storage + Idxs * 2), ...); 183 | } 184 | 185 | // loop generates vectorized code which places constants in data dir 186 | XORSTR_FORCEINLINE constexpr void _copy() noexcept 187 | { 188 | constexpr detail::string_storage storage; 189 | static_cast(std::initializer_list{ 190 | (const_cast(_storage))[Keys::idx] = 191 | storage.storage[Keys::idx]... }); 192 | } 193 | 194 | public: 195 | using value_type = typename T::value_type; 196 | using size_type = std::size_t; 197 | using pointer = value_type*; 198 | using const_pointer = const pointer; 199 | 200 | XORSTR_FORCEINLINE xor_string() noexcept { _copy(); } 201 | 202 | XORSTR_FORCEINLINE constexpr size_type size() const noexcept 203 | { 204 | return T::size - 1; 205 | } 206 | 207 | XORSTR_FORCEINLINE void crypt() noexcept 208 | { 209 | alignas(T::buffer_align) std::uint64_t keys[T::buffer_size]; 210 | static_cast(std::initializer_list{ 211 | (const_cast(keys))[Keys::idx] = 212 | Keys::key... }); 213 | 214 | _copy(); 215 | 216 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS 217 | _crypt_256(keys, std::make_index_sequence{}); 218 | if constexpr (T::buffer_size % 4 != 0) 219 | _crypt_128(keys, std::index_sequence{}); 220 | #else 221 | _crypt_128(keys, std::make_index_sequence{}); 222 | #endif 223 | } 224 | 225 | XORSTR_FORCEINLINE const_pointer get() const noexcept 226 | { 227 | return reinterpret_cast(_storage); 228 | } 229 | 230 | XORSTR_FORCEINLINE const_pointer crypt_get() noexcept 231 | { 232 | crypt(); 233 | return reinterpret_cast(_storage); 234 | } 235 | }; 236 | 237 | template 238 | XORSTR_FORCEINLINE constexpr auto 239 | make_xorstr(Tstr str_lambda, 240 | std::index_sequence, 241 | std::index_sequence) noexcept 242 | { 243 | return xor_string, 244 | detail::_ki()>...>{}; 245 | } 246 | 247 | } // namespace jm 248 | 249 | #endif // include guard -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kernelmode Manual mapping DLL INJECTOR 2 | 3 | * It uses Socket as the communication method. 4 | * It uses the Manual mapping for dll. (Without Threads) 5 | 6 | **Showcase:** ![](example.gif) 7 | 8 | **Do not use this project directly in EAC or BE games, you will most likely be banned if you do.** 9 | **You can use it to learn** 10 | 11 | **Credits:** 12 | - [mactec0](https://github.com/mactec0/Kernelmode-manual-mapping-through-IAT "mactec0") 13 | - [MrKouhx](https://github.com/MrKouhx "MrKouhx") 14 | -------------------------------------------------------------------------------- /example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouNeverKnow00/Kernelmode-DLL-Injector/b251e8734054b798329c1eef795cbb2cd7116b3e/example.gif -------------------------------------------------------------------------------- /test.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YouNeverKnow00/Kernelmode-DLL-Injector/b251e8734054b798329c1eef795cbb2cd7116b3e/test.dll --------------------------------------------------------------------------------