I've wrote a kernel driver recently and it does multiple things, but I wanted to add a IAT hook for a certain driver.
I want to hook the IAT of another driver from my driver if that makes sense.
So I understand your typical IAT hook is done via DLL injection so you're within the same address space as said module.
The main question I'm having is can someone give an example of IAT hooking a kernel driver via a kernel driver? I can't figure it out.
I've been using multiple examples of regular IAT hooking via dll injection but applying it to the Kernel driver instead.
Expected outcome: Driver1.sys (does the IAT hook) parses the import table of Driver2.sys and replaces the function "DbgPrintEx" import with a function located in Driver1.sys aka accomplishing an IAT hook.
Here is what I wrote / referenced:
NTSTATUS _HOOKS_::HookFn(PVOID ModuleBase, const char* FunctionName, uintptr_t HookFunc, uintptr_t* OrigFunc) {
IMAGE_DOS_HEADER DosHeader{ 0 };
memcpy(&DosHeader, ModuleBase, sizeof(IMAGE_DOS_HEADER));
IMAGE_NT_HEADERS NtHeaders{ 0 };
memcpy(&NtHeaders, (PVOID)((uintptr_t)ModuleBase + DosHeader.e_lfanew), sizeof(IMAGE_NT_HEADERS));
IMAGE_IMPORT_DESCRIPTOR ImportDescriptor{ 0 };
IMAGE_DATA_DIRECTORY ImportsDirectory = NtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
memcpy(&ImportDescriptor, (PVOID)((uintptr_t)ModuleBase + ImportsDirectory.VirtualAddress), sizeof(ImportDescriptor));
LPCSTR LibraryName = NULL;
PVOID Library = NULL;
IMAGE_IMPORT_BY_NAME FunctionNamee{ 0 };
while (ImportDescriptor.Name != NULL) {
memcpy(&LibraryName, &ImportDescriptor.Name + (uintptr_t)ModuleBase, sizeof(LibraryName));
IMAGE_THUNK_DATA OriginalFirstThunk{ 0 }, firstThunk{ 0 };
memcpy(&OriginalFirstThunk, (PVOID)(ImportDescriptor.OriginalFirstThunk + (uintptr_t)ModuleBase), sizeof(IMAGE_THUNK_DATA));
memcpy(&firstThunk, (PVOID)(ImportDescriptor.FirstThunk + (uintptr_t)ModuleBase), sizeof(IMAGE_THUNK_DATA));
while (OriginalFirstThunk.u1.AddressOfData != NULL) {
memcpy(&FunctionNamee, (PVOID)(OriginalFirstThunk.u1.AddressOfData + (uintptr_t)ModuleBase), sizeof(IMAGE_IMPORT_BY_NAME));
Log::Debug("First function name -> %s\n", FunctionNamee);
if (!strcmp(FunctionNamee.Name, FunctionName)) {
Log::Debug("FOUND FUNCTION!!! Address -> %p\n", firstThunk.u1.Function);
}
}
}
return STATUS_SUCCESS;
This code BSOD's on: memcpy(&ImportDescriptor, (PVOID)((uintptr_t)ModuleBase + ImportsDirectory.VirtualAddress), sizeof(ImportDescriptor));
Correct me if I'm wrong but since kernel drivers share the same address space I can just simply use memcpy or RtlCopyMemory to obtain the structs needed for this hook, does anyone have any references or some sort of documentation I can read?
Thanks to all in advance!
extra info:
- Windows 10
- Using VMWare for testing
- I'm testing the hook on my own driver
EDIT: Posted the faulting source line that causes BSOD.
Upon debugging via WinDbg(x64), the driver obtains all the addresses correctly comparing them to memory view. Except ImportDescriptor
gets an RVA of 0x6000, when inspecting ModuleBase + 0x6000
for the RVA it shows that this memory region is invalid, so I believe that the 0x6000 RVA is incorrect and I'm not sure why
BUG CHECK CODES:
- BSOD Error Code: PAGE_FAULT_IN_NONPAGED_AREA
- BUG Check Code: 50
memcpy
look correct? You should be able to check it in the debugger before stepping inside the call.IMAGE_DATA_DIRECTORY ImportsDirectory = NtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
seems to be returning an invalid virtual address, it returns 0x6000 so ImportDescriptor should beDriverBase + 0x6000
, and viewing this memory region in WINDBG shows that this memory region is invalid. Do you know why I'm getting these logical errors? I believe I'm getting everything correctly?