Calling NtQuerydirectoryFile from a Kernel Hook Crashes the Kernel #78

Closed
fifothekid opened this Issue Feb 29, 2016 · 10 comments

Comments

Projects
None yet
3 participants
@fifothekid

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

@fifothekid

This comment has been minimized.

Show comment
Hide comment
@fifothekid

fifothekid Mar 1, 2016

I could track the problem to trashing the RAX register in the trampoline code. I'm currently replacing it with a safer version...

I could track the problem to trashing the RAX register in the trampoline code. I'm currently replacing it with a safer version...

@spazzarama

This comment has been minimized.

Show comment
Hide comment
@spazzarama

spazzarama Mar 1, 2016

Member
Member

spazzarama commented Mar 1, 2016

@fifothekid

This comment has been minimized.

Show comment
Hide comment
@fifothekid

fifothekid Mar 1, 2016

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
48 b8 00 00 00 00 00 00 00 00  mov rax, 0x0
48 87 04 24                    xchg   QWORD PTR [rsp],rax
c3                             ret

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
48 b8 00 00 00 00 00 00 00 00  mov rax, 0x0
48 87 04 24                    xchg   QWORD PTR [rsp],rax
c3                             ret
@fifothekid

This comment has been minimized.

Show comment
Hide comment
@fifothekid

fifothekid Mar 1, 2016

It worked
I had to make many changes in the code because the size of the trampoline was hard-coded
I'll make a pull-request today

It worked
I had to make many changes in the code because the size of the trampoline was hard-coded
I'll make a pull-request today

@spazzarama

This comment has been minimized.

Show comment
Hide comment
@spazzarama

spazzarama Mar 2, 2016

Member

@fifothekid great news. Can I ask are you doing anything for patchguard etc.. Or just enabled kernel debugging?

Member

spazzarama commented Mar 2, 2016

@fifothekid great news. Can I ask are you doing anything for patchguard etc.. Or just enabled kernel debugging?

@fifothekid

This comment has been minimized.

Show comment
Hide comment
@fifothekid

fifothekid Mar 2, 2016

I'm sure that I've enabled kernel debugging, but I don't think that I've done anything to Patchguard, although I remember tinkering with many Windows options

I'm sure that I've enabled kernel debugging, but I don't think that I've done anything to Patchguard, although I remember tinkering with many Windows options

@spazzarama

This comment has been minimized.

Show comment
Hide comment
@spazzarama

spazzarama Mar 6, 2016

Member

@fifothekid in that case there will be various parts of the kernel that are protected by Patch Guard, so just keep that in mind when it comes to deploying. I believe that some hooks are still possible (e.g. perhaps other kernel driver callbacks). Please let me know when you have your pull ready.

Member

spazzarama commented Mar 6, 2016

@fifothekid in that case there will be various parts of the kernel that are protected by Patch Guard, so just keep that in mind when it comes to deploying. I believe that some hooks are still possible (e.g. perhaps other kernel driver callbacks). Please let me know when you have your pull ready.

@spazzarama

This comment has been minimized.

Show comment
Hide comment
@spazzarama

spazzarama Mar 25, 2016

Member

@fifothekid do you happen to have that pull request ready?

Member

spazzarama commented Mar 25, 2016

@fifothekid do you happen to have that pull request ready?

@spazzarama spazzarama added the bug label Mar 25, 2016

@spazzarama spazzarama added this to the 2.7 Stable milestone Mar 25, 2016

@alvin-nt

This comment has been minimized.

Show comment
Hide comment
@alvin-nt

alvin-nt Jun 23, 2016

I'm currently working on a program that uses hooks at the same function (via user-mode). Any updates about this bug?

alvin-nt commented Jun 23, 2016

I'm currently working on a program that uses hooks at the same function (via user-mode). Any updates about this bug?

@spazzarama

This comment has been minimized.

Show comment
Hide comment
@spazzarama

spazzarama Jul 5, 2016

Member

@alvin-nt committed a fix in develop branch

Member

spazzarama commented Jul 5, 2016

@alvin-nt committed a fix in develop branch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment