nt!KeWaitForSingleObject without Args

我的梦境 提交于 2019-12-05 14:04:26

You're debugging a 64-bit process.

Remember the x64 calling convention, which is explained here. The first 4 arguments are passed in registers. After that, arguments are pushed onto the stack.

Unfortunately, kv blindly displays the stack arguments. In fact, it would be quite difficult (and sometimes impossible) for it to determine what the first 4 arguments actually were at the time of the call since they may not have been stored anywhere that can ever be recovered.

So, you are looking at the 5th argument to nt!NtWaitForSingleObject, where a nullptr is a pretty typical argument for a Timeout.

Luckily for us debugging types, all is not lost! There is a windbg extension which does its best to reconstruct the arguments when the function was called. The extension is called CMKD. You can place the extension DLL in your winext folder and call it like so:

0:000> !cmkd.stack -p
Call Stack : 7 frames
## Stack-Pointer    Return-Address   Call-Site       
00 000000a408c7fb28 00007ffda95b1148 ntdll!NtWaitForSingleObject+a 
    Parameter[0] = 0000000000000034
    Parameter[1] = 0000000000000000
    Parameter[2] = 0000000000000000
    Parameter[3] = (unknown)       
01 000000a408c7fb30 00007ff7e44c13f1 KERNELBASE!WaitForSingleObjectEx+98 
    Parameter[0] = 0000000000000034
    Parameter[1] = 00000000ffffffff
    Parameter[2] = 0000000000000000
    Parameter[3] = 00007ff7e44cba28
02 000000a408c7fbd0 00007ff7e44c3fed ConsoleApplication2!main+41 
    Parameter[0] = (unknown)       
    Parameter[1] = (unknown)       
    Parameter[2] = (unknown)       
    Parameter[3] = (unknown)       

Notice that it does not always succeed at finding the argument, as some of them are (unknown). But, it does a pretty good job and can be an invaluable tool when debugging 64-bit code.

This looks like a 64-bit OS, and therefore the calling convention is not to pass all the parameters on the stack. Rather, the first four parameters get passed in RCX, RDX, R8, and R9, with the remaining parameters on the stack. So if you catch the call to KeWaitForSingleObject it's easy to see what's in RCX and go from there. Once you are a few stack frames beyond that, it's much hard to tell since something will have been loaded into that register. The original value is probably stored somewhere, but it will be difficult to find.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!