Calling NtQuerydirectoryFile from a Kernel Hook Crashes the Kernel

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:

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

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:
fffff800c62e9d2a 018943c8498d add dword ptr [rcx-72B637BDh],ecx ds:ffffffff8d49d4d7=???
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:
ffffd001a8f6d358 fffff800c6058ab6 : fffff6fb7dbf0018 fffff6fb7dbedf80 0000000000000000 fffff800c605942a : nt!DbgBreakPointWithStatus
ffffd001a8f6d360 fffff800c6058789 : fffff80000000004 fffff800c6155de0 000000000000000a 0000000000000001 : nt!KiBugCheckDebugBreak+0x12
ffffd001a8f6d3c0 fffff800c5fc94a4 : 0000070000000000 fffff800c5ee0ac1 0000000000000000 ffffe001414f7140 : nt!KeBugCheck2+0xc6d
ffffd001a8f6dad0 fffff800c5fd4ee9 : 000000000000000a fffff6fb7fffe350 0000000000000002 0000000000000000 : nt!KeBugCheckEx+0x104
ffffd001a8f6db10 fffff800c5fd373a : 0000000000000000 0000070000000000 ffffe0013f6edb00 ffffe0013e877ac0 : nt!KiBugCheckDispatch+0x69
ffffd001a8f6dc50 fffff800c5eee930 : 0000000000000060 0000000000000001 ffffd001a8f6e7c0 0000000000000000 : nt!KiPageFault+0x23a
ffffd001a8f6dde0 fffff800c6057ff4 : 0000070000000000 ffffd001a8f6df10 ffffffff8d49d4d7 0000007fffffffff : nt!MmIsSpecialPoolAddress+0x54
ffffd001a8f6de10 fffff800c5fc94a4 : 0000000000000000 ffffe0013e6ac1b0 0000000000000001 0000000000000001 : nt!KeBugCheck2+0x4d8
ffffd001a8f6e520 fffff800c5ffcc73 : 0000000000000050 ffffffff8d49d4d7 0000000000000001 ffffd001a8f6e7c0 : nt!KeBugCheckEx+0x104
ffffd001a8f6e560 fffff800c5ec0e99 : 0000000000000001 ffffe00140d6a4c0 ffffd001a8f6e7c0 ffffd001a8f6e730 : nt! ?? ::FNODOBFM::string'+0x233b3 ffffd001a8f6e600 fffff800c5fd362f : 0000000000000001 ffffe00140ffd080 0000000000000000 0000000000000000 : nt!MmAccessFault+0x769 ffffd001a8f6e7c0 fffff800c62e9d2a : ffffe00141720b01 0000000100000000 ffffe00100000001 ffffe0013e874400 : nt!KiPageFault+0x12f ffffd001a8f6e950 fffff80063e9c172 : fffff800c5fd4bb3 ffffd001a8f6ea88 0000000000000000 0000000000000000 : nt!NtQueryDirectoryFile+0xe ffffd001a8f6ea10 ffffe0013e853341 : 0000000000000c94 0000000000000000 0000000000000000 0000000000000000 : TestDriver+0x1172 ffffd001a8f6ea90 0000000000000c94 : 0000000000000000 0000000000000000 0000000000000000 000000b13913c868 : 0xffffe0013e853341
ffffd001a8f6ea98 0000000000000000 : 0000000000000000 0000000000000000 000000b13913c868 000000b13913c880 : 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

>I’m using the latest version of EasyHook to hook some kernel functions.

Unfortunately, I am not in a position to provide any “funny” quotations (I will be accused of trolling if I do), so that I leave it for the usual suspects to voice their opinion. In any case, I am holding my breath in anticipation of the “exciting” thread…

Anton Bassov

It’s not illegal, and I’m not a script kiddie.
Regardless of whether it is a hook or not, I’m having some inexplicable crashing calling this particular function.
Even some debugging tips would be enough for me…

So, kernel-mode function hooking is stupid and won’t work on 64-bit Windows.

Does EasyHook *really* support hooking stuff in Kernel-Mode? I was aware it could do DLL injection, but I was not aware that it could hook kernel-mode functions. Stuff like ReadFile BEFORE it got to kernel-mode, yes. NtReadFile in kernel-mode, though?

Anyhow, Mr. Bassov’s allusions are correct: You’re not going to get any love here. Or any help, really.

Why do people insist on doing stupid shit like this?

Peter
OSR
@OSRDrivers

> So, kernel-mode function hooking is stupid and won’t work on 64-bit Windows. <
It’s not stupid and it does work on 64-bit Windows.
EasyHook supports managed and unmanaged hooks, DLL injection, both user- and kernel-land hooking via a dll, library, or a driver. It can deal with Patchguard 3 and works on all Windows versions.
Why do we do stupid shit? the answer is money, maybe?

xxxxx@yahoo.com wrote:

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:

How is that supposed to work? When a driver calls NtQueryDirectoryFile,
it vectors to you. So how can YOU call NtQueryDirectoryFile without
causing an infinite loop?

nt!NtQueryDirectoryFile+0xe:
fffff800c62e9d2a 018943c8498d add dword ptr [rcx-72B637BDh],ecx ds:ffffffff8d49d4d7=???
Resetting default scope
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)

The first bytes of the function have been altered and not changed back.
Someone in the hooking process is not doing their job properly.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> How is that supposed to work? When a driver calls NtQueryDirectoryFile,
it vectors to you. So how can YOU call NtQueryDirectoryFile without
causing an infinite loop?

The hooking process points the function to the EasyHook library rather than to my hook function. The EasyHook library would then check whether the caller is a hook itself, or whether it is included in the ACL lists and make the decision of whether it would redirect to the hook or to the original function.

The first bytes of the function have been altered and not changed back.
Someone in the hooking process is not doing their job properly.

I’m debugging this part right now

Except when you get a blue screen, I guess.

Hmmm… Have you considered performance art in the subway/tube/metro?

Hooking is stupid. Please do us the kind favor of taking this particular question to a different forum. We’ll help you in another of your kernel-mode endeavors at some time in the future. See how nice and respectful I’m being? And a member here recently nicknamed me “The Hanging Judge”… I don’t think that was very nice, do you?

Peter
OSR
@OSRDrivers

On Mon, Feb 29, 2016 at 09:29:07PM -0500, xxxxx@yahoo.com wrote:

> How is that supposed to work? When a driver calls NtQueryDirectoryFile,
it vectors to you. So how can YOU call NtQueryDirectoryFile without
causing an infinite loop?

The hooking process points the function to the EasyHook library rather than to my hook function. The EasyHook library would then check whether the caller is a hook itself, or whether it is included in the ACL lists and make the decision of whether it would redirect to the hook or to the original function.

> The first bytes of the function have been altered and not changed back.
Someone in the hooking process is not doing their job properly.

I’m debugging this part right now

Sounds like this discussion should be moved to the “EasyHook” forum.

-ml


NTDEV is sponsored by OSR

Visit the list online at: http:
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>

i don’t know if this is gmail or ntdev bug, but i did’t get any of OP’s
messages.
in the same time i have got all messages from other members.
i checked spam folder - nothing there too

On Tue, Mar 1, 2016 at 9:58 AM, Mike Larkin wrote:

> On Mon, Feb 29, 2016 at 09:29:07PM -0500, xxxxx@yahoo.com wrote:
> > > How is that supposed to work? When a driver calls
> NtQueryDirectoryFile,
> > it vectors to you. So how can YOU call NtQueryDirectoryFile without
> > causing an infinite loop?
> >
> > The hooking process points the function to the EasyHook library rather
> than to my hook function. The EasyHook library would then check whether the
> caller is a hook itself, or whether it is included in the ACL lists and
> make the decision of whether it would redirect to the hook or to the
> original function.
> >
> > > The first bytes of the function have been altered and not changed back.
> > Someone in the hooking process is not doing their job properly.
> >
> > I’m debugging this part right now
>
> Sounds like this discussion should be moved to the “EasyHook” forum.
>
> -ml
>
> >
> > —
> > NTDEV is sponsored by OSR
> >
> > Visit the list online at: <
> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
> >
> > MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> > Details at http:
> >
> > To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: <
> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:></http:>

the posts from yahoo do not come to gmail via osronline it is some
sort of dmarc whatever crap policy

ie gmail rejected the mail from yahoo because it was resent via
osronline and not directly by yahoo

<– 550-5.7.1 Unauthenticated email from yahoo.com is not accepted due
to domain’s
<– 550-5.7.1 DMARC policy. Please contact administrator of yahoo.com domain if
<– 550-5.7.1 this was a legitimate mail. Please visit
<– 550-5.7.1 http://support.google.com/mail/answer/2451690 to learn about DMARC
<– 550 5.7.1 initiative. ea3si1007061obb.81 - gsmtp

On 3/1/16, Sergey Pisarev wrote:
> i don’t know if this is gmail or ntdev bug, but i did’t get any of OP’s
> messages.
> in the same time i have got all messages from other members.
> i checked spam folder - nothing there too
>
> On Tue, Mar 1, 2016 at 9:58 AM, Mike Larkin wrote:
>
>> On Mon, Feb 29, 2016 at 09:29:07PM -0500, xxxxx@yahoo.com wrote:
>> > > How is that supposed to work? When a driver calls
>> NtQueryDirectoryFile,
>> > it vectors to you. So how can YOU call NtQueryDirectoryFile without
>> > causing an infinite loop?
>> >
>> > The hooking process points the function to the EasyHook library rather
>> than to my hook function. The EasyHook library would then check whether
>> the
>> caller is a hook itself, or whether it is included in the ACL lists and
>> make the decision of whether it would redirect to the hook or to the
>> original function.
>> >
>> > > The first bytes of the function have been altered and not changed
>> > > back.
>> > Someone in the hooking process is not doing their job properly.
>> >
>> > I’m debugging this part right now
>>
>> Sounds like this discussion should be moved to the “EasyHook” forum.
>>
>> -ml
>>
>> >
>> > —
>> > NTDEV is sponsored by OSR
>> >
>> > Visit the list online at: <
>> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>> >
>> > MONTHLY seminars on crash dump analysis, WDF, Windows internals and
>> software drivers!
>> > Details at http:
>> >
>> > To unsubscribe, visit the List Server section of OSR Online at <
>> http://www.osronline.com/page.cfm?name=ListServer&gt;
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> Visit the list online at: <
>> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>>
>> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
>> software drivers!
>> Details at http:
>>
>> To unsubscribe, visit the List Server section of OSR Online at <
>> http://www.osronline.com/page.cfm?name=ListServer&gt;
>>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at:
> http:
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and software
> drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at
> http:</http:></http:></http:></http:></http:>

thx for info Raj

On Tue, Mar 1, 2016 at 10:33 AM, raj r wrote:

> the posts from yahoo do not come to gmail via osronline it is some
> sort of dmarc whatever crap policy
>
> ie gmail rejected the mail from yahoo because it was resent via
> osronline and not directly by yahoo
>
> <– 550-5.7.1 Unauthenticated email from yahoo.com is not accepted due
> to domain’s
> <– 550-5.7.1 DMARC policy. Please contact administrator of yahoo.com
> domain if
> <– 550-5.7.1 this was a legitimate mail. Please visit
> <– 550-5.7.1 http://support.google.com/mail/answer/2451690 to learn
> about DMARC
> <– 550 5.7.1 initiative. ea3si1007061obb.81 - gsmtp
>
>
> On 3/1/16, Sergey Pisarev wrote:
> > i don’t know if this is gmail or ntdev bug, but i did’t get any of OP’s
> > messages.
> > in the same time i have got all messages from other members.
> > i checked spam folder - nothing there too
> >
> > On Tue, Mar 1, 2016 at 9:58 AM, Mike Larkin
> wrote:
> >
> >> On Mon, Feb 29, 2016 at 09:29:07PM -0500, xxxxx@yahoo.com wrote:
> >> > > How is that supposed to work? When a driver calls
> >> NtQueryDirectoryFile,
> >> > it vectors to you. So how can YOU call NtQueryDirectoryFile without
> >> > causing an infinite loop?
> >> >
> >> > The hooking process points the function to the EasyHook library rather
> >> than to my hook function. The EasyHook library would then check whether
> >> the
> >> caller is a hook itself, or whether it is included in the ACL lists and
> >> make the decision of whether it would redirect to the hook or to the
> >> original function.
> >> >
> >> > > The first bytes of the function have been altered and not changed
> >> > > back.
> >> > Someone in the hooking process is not doing their job properly.
> >> >
> >> > I’m debugging this part right now
> >>
> >> Sounds like this discussion should be moved to the “EasyHook” forum.
> >>
> >> -ml
> >>
> >> >
> >> > —
> >> > NTDEV is sponsored by OSR
> >> >
> >> > Visit the list online at: <
> >> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
> >> >
> >> > MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> >> software drivers!
> >> > Details at http:
> >> >
> >> > To unsubscribe, visit the List Server section of OSR Online at <
> >> http://www.osronline.com/page.cfm?name=ListServer&gt;
> >>
> >> —
> >> NTDEV is sponsored by OSR
> >>
> >> Visit the list online at: <
> >> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
> >>
> >> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> >> software drivers!
> >> Details at http:
> >>
> >> To unsubscribe, visit the List Server section of OSR Online at <
> >> http://www.osronline.com/page.cfm?name=ListServer&gt;
> >>
> >
> > —
> > NTDEV is sponsored by OSR
> >
> > Visit the list online at:
> > http:
> >
> > MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software
> > drivers!
> > Details at http:
> >
> > To unsubscribe, visit the List Server section of OSR Online at
> > http:
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: <
> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:></http:></http:></http:></http:></http:>

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:
48 b8 00 00 00 00 00 00 00 00 mov rax, 0x0
ff e0 jmp rax

with this:
50 push rax AHMED
48 b8 00 00 00 00 00 00 00 00 mov rax, 0x0
48 87 04 24 xchg QWORD PTR [rsp],rax
c3 ret

So, you’re writing the code which will be killed by Device Guard in Srv2016, and will probably be flagged as malware (together with the hooking library) by anti-virus vendors.

And, anyway, you will get lots of support issues from this code, with some of them being unresolvable even theoretically.

The proper way of doing directory name lists filtering is the minifilter+name provider. This is guaranteed to work, and I don’t think FltMgr is much more complex then your hooking library.

So, please go the correct way.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntdev…
> 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:
> 48 b8 00 00 00 00 00 00 00 00 mov rax, 0x0
> ff e0 jmp rax
>
> with this:
> 50 push rax AHMED
> 48 b8 00 00 00 00 00 00 00 00 mov rax, 0x0
> 48 87 04 24 xchg QWORD PTR [rsp],rax
> c3 ret
>

The requirements call for implementing it this way.
Besides, there will always be a workaround for any software protection.
My boss doesn’t mind upgrading/altering the code every month or two…

Mr. Yarub: You must have missed my nice, polite, request for you to take this topic elsewhere?

I mean, you MUST have missed it, right? Because you wouldn’t be disrespecting me here in my own house by intentionally ignoring something I asked of you concerning this forum. Right?

Peter
OSR
@OSRDrivers

OK
I hope that you can delete this thread
Goodbye

Maxim S. Shatskih wrote:

So, you’re writing the code which will be killed by Device
Guard in Srv2016, and will probably be flagged as malware
(together with the hooking library) by anti-virus vendors.

I don’t understand. How is this guy doing what he’s doing, even now, on 64-bit (as he claims)?

c.f.

https://msdn.microsoft.com/en-us/library/windows/hardware/Dn613955(v=vs.85).aspx

I have no idea. And I’m in no position to argue with the OP.

I’d like to understand that as well. But I’m not motivated enough to dig-into the sources of EasyHook to get the answer.

I DO see that the EasyHook tutorial (dated 2008) that purports to reflect V2.6 (current version is 2.7) says:

Soooo… Mayhaps the OP is misinformed? Frankly, that would be MY guess. PatchGuard is not easy to bypass, in my experience. PLUS, if there WERE a free, simple, open-source, method of hooking kernel-mode APIs on 64-bit Windows I can only imagine that MSFT would close whatever hole it exploited ASAFP.

Peter
OSR
@OSRDrivers