Page 1 of 1
Calling NtQuerydirectoryFile from a Kernel Hook Crashes the
PostPosted:Mon Feb 29, 2016 4:12 am
by fifo_thekid
I'm using the latest version of EasyHook to hook some kernel functions. I did setup a debugging important successfully on a Windows 8.1 64-bit based virtual machine, and I tested hooking both of NtQuerydirectoryFile and NtQuerySystemInformation in user mode and NtQuerySystemInformation in kernel mode without any problem.
My current problem is hooking NtQuerydirectoryFile using the same code that I used for the user mode hook, but it fails when I call the original function giving me an access violation error. I'm using the following code for the kernel mode hook:
Code: Select allNTSTATUS NtQueryDirectoryFile_Hook(
__in HANDLE FileHandle,
__in_opt HANDLE Event,
__in_opt PIO_APC_ROUTINE ApcRoutine,
__in_opt PVOID ApcContext,
__out PIO_STATUS_BLOCK IoStatusBlock,
__out_bcount(Length) PVOID FileInformation,
__in ULONG Length,
__in FILE_INFORMATION_CLASS FileInformationClass,
__in BOOLEAN ReturnSingleEntry,
__in PUNICODE_STRING FileName OPTIONAL,
__in BOOLEAN RestartScan
)
{
NTSTATUS status;
status = NtQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, FileInformation, Length, FileInformationClass, ReturnSingleEntry, FileName, RestartScan);
return status;
}
Re: Calling NtQuerydirectoryFile from a Kernel Hook Crashes
PostPosted:Mon Feb 29, 2016 7:43 pm
by fifo_thekid
And here's the dump:
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except,
it must be protected by a Probe. Typically the address is just plain bad or it
is pointing at freed memory.
Arguments:
Arg1: ffffffff8d49d4d7, memory referenced.
Arg2: 0000000000000001, value 0 = read operation, 1 = write operation.
Arg3: fffff800c62e9d2a, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 0000000000000002, (reserved)
Debugging Details:
------------------
WRITE_ADDRESS: unable to get nt!MmNonPagedPoolStart
unable to get nt!MmSizeOfNonPagedPoolInBytes
ffffffff8d49d4d7
FAULTING_IP:
nt!NtQueryDirectoryFile+e
fffff800`c62e9d2a 018943c8498d add dword ptr [rcx-72B637BDh],ecx
MM_INTERNAL_CODE: 2
DEFAULT_BUCKET_ID: CODE_CORRUPTION
BUGCHECK_STR: AV
PROCESS_NAME: svchost.exe
CURRENT_IRQL: 2
ANALYSIS_VERSION: 6.3.9600.17336 (debuggers(dbg).150226-1500) amd64fre
TRAP_FRAME: ffffd001a8f6e7c0 -- (.trap 0xffffd001a8f6e7c0)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=fffff800c62e9d2a rbx=0000000000000000 rcx=0000000000000c94
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff800c62e9d2a rsp=ffffd001a8f6e950 rbp=ffffd001a8f6eb80
r8=0000000000000000 r9=0000000000000000 r10=fffff800c62e9d1c
r11=ffffd001a8f6ea08 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei ng nz na po nc
nt!NtQueryDirectoryFile+0xe:
fffff800`c62e9d2a 018943c8498d add dword ptr [rcx-72B637BDh],ecx ds:ffffffff`8d49d4d7=????????
Resetting default scope
MISALIGNED_IP:
nt!NtQueryDirectoryFile+e
fffff800`c62e9d2a 018943c8498d add dword ptr [rcx-72B637BDh],ecx
LAST_CONTROL_TRANSFER: from fffff800c6058ab6 to fffff800c5fcff90
STACK_TEXT:
ffffd001`a8f6d358 fffff800`c6058ab6 : fffff6fb`7dbf0018 fffff6fb`7dbedf80 00000000`00000000 fffff800`c605942a : nt!DbgBreakPointWithStatus
ffffd001`a8f6d360 fffff800`c6058789 : fffff800`00000004 fffff800`c6155de0 00000000`0000000a 00000000`00000001 : nt!KiBugCheckDebugBreak+0x12
ffffd001`a8f6d3c0 fffff800`c5fc94a4 : 00000700`00000000 fffff800`c5ee0ac1 00000000`00000000 ffffe001`414f7140 : nt!KeBugCheck2+0xc6d
ffffd001`a8f6dad0 fffff800`c5fd4ee9 : 00000000`0000000a fffff6fb`7fffe350 00000000`00000002 00000000`00000000 : nt!KeBugCheckEx+0x104
ffffd001`a8f6db10 fffff800`c5fd373a : 00000000`00000000 00000700`00000000 ffffe001`3f6edb00 ffffe001`3e877ac0 : nt!KiBugCheckDispatch+0x69
ffffd001`a8f6dc50 fffff800`c5eee930 : 00000000`00000060 00000000`00000001 ffffd001`a8f6e7c0 00000000`00000000 : nt!KiPageFault+0x23a
ffffd001`a8f6dde0 fffff800`c6057ff4 : 00000700`00000000 ffffd001`a8f6df10 ffffffff`8d49d4d7 0000007f`ffffffff : nt!MmIsSpecialPoolAddress+0x54
ffffd001`a8f6de10 fffff800`c5fc94a4 : 00000000`00000000 ffffe001`3e6ac1b0 00000000`00000001 00000000`00000001 : nt!KeBugCheck2+0x4d8
ffffd001`a8f6e520 fffff800`c5ffcc73 : 00000000`00000050 ffffffff`8d49d4d7 00000000`00000001 ffffd001`a8f6e7c0 : nt!KeBugCheckEx+0x104
ffffd001`a8f6e560 fffff800`c5ec0e99 : 00000000`00000001 ffffe001`40d6a4c0 ffffd001`a8f6e7c0 ffffd001`a8f6e730 : nt! ?? ::FNODOBFM::`string'+0x233b3
ffffd001`a8f6e600 fffff800`c5fd362f : 00000000`00000001 ffffe001`40ffd080 00000000`00000000 00000000`00000000 : nt!MmAccessFault+0x769
ffffd001`a8f6e7c0 fffff800`c62e9d2a : ffffe001`41720b01 00000001`00000000 ffffe001`00000001 ffffe001`3e874400 : nt!KiPageFault+0x12f
ffffd001`a8f6e950 fffff800`63e9c172 : fffff800`c5fd4bb3 ffffd001`a8f6ea88 00000000`00000000 00000000`00000000 : nt!NtQueryDirectoryFile+0xe
ffffd001`a8f6ea10 ffffe001`3e853341 : 00000000`00000c94 00000000`00000000 00000000`00000000 00000000`00000000 : TestDriver+0x1172
ffffd001`a8f6ea90 00000000`00000c94 : 00000000`00000000 00000000`00000000 00000000`00000000 000000b1`3913c868 : 0xffffe001`3e853341
ffffd001`a8f6ea98 00000000`00000000 : 00000000`00000000 00000000`00000000 000000b1`3913c868 000000b1`3913c880 : 0xc94
STACK_COMMAND: kb
CHKIMG_EXTENSION: !chkimg -lo 50 -d !nt
fffff800c62e9d1c-fffff800c62e9d27 12 bytes - nt!NtQueryDirectoryFile
[ 4c 8b dc 48 81 ec b8 00:48 b8 98 32 85 3e 01 e0 ]
fffff800c62e9d2a - nt!NtQueryDirectoryFile+e (+0x0e)
[ 49:01 ]
13 errors : !nt (fffff800c62e9d1c-fffff800c62e9d2a)
MODULE_NAME: memory_corruption
IMAGE_NAME: memory_corruption
FOLLOWUP_NAME: memory_corruption
DEBUG_FLR_IMAGE_TIMESTAMP: 0
MEMORY_CORRUPTOR: LARGE
FAILURE_BUCKET_ID: MEMORY_CORRUPTION_LARGE
BUCKET_ID: MEMORY_CORRUPTION_LARGE
ANALYSIS_SOURCE: KM
FAILURE_ID_HASH_STRING: km:memory_corruption_large
FAILURE_ID_HASH: {e29154ac-69a4-0eb8-172a-a860f73c0a3c}
Followup: memory_corruption
---------
Re: Calling NtQuerydirectoryFile from a Kernel Hook Crashes
PostPosted:Mon Feb 29, 2016 9:43 pm
by Brock
Kernel Patch Protection (KPP) / Patch Guard (PG) doesn't like kernel hooks on these Nt/Zw services within 64-bit versions of Windows. Are you disabling it? If not, it will cause a bugcheck.
Re: Calling NtQuerydirectoryFile from a Kernel Hook Crashes
PostPosted:Mon Feb 29, 2016 9:52 pm
by Vrtule
Which method do you use to hook the routine?
Well, the bugcheck code is not 0x109 so it is not KPP for now. But Brock is right; KPP will not be very happy when it detect such modifications.
Re: Calling NtQuerydirectoryFile from a Kernel Hook Crashes
PostPosted:Tue Mar 01, 2016 12:49 am
by fifo_thekid
Brock wrote:Kernel Patch Protection (KPP) / Patch Guard (PG) doesn't like kernel hooks on these Nt/Zw services within 64-bit versions of Windows. Are you disabling it? If not, it will cause a bugcheck.
I'm not disabling it. EasyHook can deal with it without any problem. I've already done 2 user mode hooks and 1 kernel mode hook and they are working like a charm.
Re: Calling NtQuerydirectoryFile from a Kernel Hook Crashes
PostPosted:Tue Mar 01, 2016 12:50 am
by fifo_thekid
Vrtule wrote:Which method do you use to hook the routine?
Well, the bugcheck code is not 0x109 so it is not KPP for now. But Brock is right; KPP will not be very happy when it detect such modifications.
Inline hooking.
Please check out the answer above.
Re: Calling NtQuerydirectoryFile from a Kernel Hook Crashes
PostPosted:Tue Mar 01, 2016 5:54 am
by fifo_thekid
I could track the problem to the way trampoline jumps are made: they are trashing the RAX register. This specific function utilizes the RAX register, which creates access violation errors. I'm currently working on replacing the trampoline code....
Re: Calling NtQuerydirectoryFile from a Kernel Hook Crashes
PostPosted:Tue Mar 01, 2016 4:05 pm
by fifo_thekid
It looks like the BuildQueryDirectoryIrp function expects some kind of parameter
in the RAX register, and due to the way the trampoline jump was implemented, the
RAX register data is lost!
So I'm replacing this:
Code: Select all48 b8 00 00 00 00 00 00 00 00 mov rax, 0x0
ff e0 jmp rax
with this:
Code: Select all50 push rax
48 b8 00 00 00 00 00 00 00 00 mov rax, 0x0
48 87 04 24 xchg QWORD PTR [rsp],rax
c3 ret
Re: Calling NtQuerydirectoryFile from a Kernel Hook Crashes
PostPosted:Tue Mar 01, 2016 6:42 pm
by fifo_thekid
I changed the code for both the trampoline jump and the jump to original function jump, and now it's working flowlessly....
I'll make a pull request to the author today.
Thanks guys for your help
Re: Calling NtQuerydirectoryFile from a Kernel Hook Crashes
PostPosted:Wed Mar 02, 2016 4:34 am
by EP_X0FF
As far as I remember Easyhook comes from this guy
http://www.codeproject.com/Articles/283 ... PatchGuard. I would not recommend using it as it will make your software nice BSOD generator. Not to mention splicing is in general idiotic way from lolkits of 200x. Closed.