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;
|
std::cout << "[<] Unloading vulnerable driver" << std::endl;
|
||||||
|
|
||||||
ClearMmUnloadedDrivers(device_handle);
|
ClearMmUnloadedDrivers(device_handle);
|
||||||
|
ClearPiDDBCacheTable(device_handle);
|
||||||
CloseHandle(device_handle);
|
CloseHandle(device_handle);
|
||||||
|
|
||||||
service::StopAndRemove(driver_name);
|
service::StopAndRemove(driver_name);
|
||||||
@@ -368,3 +369,176 @@ bool intel_driver::ClearMmUnloadedDrivers(HANDLE device_handle)
|
|||||||
|
|
||||||
return true;
|
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);
|
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 GetNtGdiDdDDIReclaimAllocations2KernelInfo(HANDLE device_handle, uint64_t* out_kernel_function_ptr, uint64_t* out_kernel_original_function_address);
|
||||||
bool ClearMmUnloadedDrivers(HANDLE device_handle);
|
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>
|
template<typename T, typename ...A>
|
||||||
bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments)
|
bool CallKernelFunction(HANDLE device_handle, T* out_result, uint64_t kernel_function_address, const A ...arguments)
|
||||||
|
|||||||
@@ -76,4 +76,21 @@ namespace nt
|
|||||||
ULONG NumberOfModules;
|
ULONG NumberOfModules;
|
||||||
RTL_PROCESS_MODULE_INFORMATION Modules[1];
|
RTL_PROCESS_MODULE_INFORMATION Modules[1];
|
||||||
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
|
} 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
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@@ -66,3 +66,31 @@ uint64_t utils::GetKernelModuleAddress(const std::string& module_name)
|
|||||||
VirtualFree(buffer, 0, MEM_RELEASE);
|
VirtualFree(buffer, 0, MEM_RELEASE);
|
||||||
return 0;
|
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 <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "nt.hpp"
|
#include "nt.hpp"
|
||||||
|
|
||||||
@@ -14,4 +15,5 @@ namespace utils
|
|||||||
bool ReadFileToMemory(const std::string& file_path, std::vector<uint8_t>* out_buffer);
|
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);
|
bool CreateFileFromMemory(const std::string& desired_file_path, const char* address, size_t size);
|
||||||
uint64_t GetKernelModuleAddress(const std::string& module_name);
|
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