Windows 系统调用后如何进行反汇编

How to get disassembly after syscall in Windows

我想获取 NtDelayExecution() 的汇编程序源代码,以了解什么是 Sleep() 及其内部工作原理。 但只有我在 Visual Studio 2017 调试器中得到的是:

NtDelayExecution:
    mov         r10,rcx  
    mov         eax,34h  
    test        byte ptr [........],1  
    jne         NtDelayExecution+15h 
    syscall  
    ret 
NtDelayExecution+15h:
    int         2Eh  
    ret  

它通过 syscall 指令就像它是常规的 mov 而不是 call (即使我按 F11)。结果只是 "magically" 出现,没有提供它的可见代码,也没有办法找到它在哪里的痕迹或提示。似乎它的工作方式类似于旧 DOS 操作系统时代的 int 21h 中断。而它放入eax的是一个函数号。

进一步拆解正在发生的事情的最简单方法是什么? 也许可以阅读有关该主题的一些文献? (我的 OS 是 Windows 10 x64,IDE 是 Visual Studio 2017 社区)

不确定,是否确实需要内核调试会话本身。如果你只需要反汇编,没有内核调试经验,你可以选择更简单的方法。

Mark Russinovich 的 Process Explorer 是一个简单易用的工具,可以帮助获得线索并调查正在发生的事情。例如,它可以显示线程调用堆栈,并以人类可读的名称公开堆栈的内核部分:

ntoskrnl.exe!KeSynchronizeExecution+0x3f26
ntoskrnl.exe!KeWaitForMultipleObjects+0x109c
ntoskrnl.exe!KeWaitForMultipleObjects+0xb3f
ntoskrnl.exe!KeWaitForMutexObject+0x377
ntoskrnl.exe!KeUnstackDetachProcess+0x2230
ntoskrnl.exe!ObDereferenceObjectDeferDelete+0x28a
ntoskrnl.exe!KeWaitForMultipleObjects+0x1283
ntoskrnl.exe!KeWaitForMultipleObjects+0xb3f
ntoskrnl.exe!KeDelayExecutionThread+0x106
ntoskrnl.exe!CcUnpinData+0xfe
ntoskrnl.exe!setjmpex+0x3aa3
ntdll.dll!NtDelayExecution+0x14
test.exe!main+0x1f
test.exe!__scrt_common_main_seh+0x11d
KERNEL32.DLL!BaseThreadInitThunk+0x14
ntdll.dll!RtlUserThreadStart+0x21

下一步可能只是用一些反汇编程序反汇编 ntoskrnl.exe,例如 x64dbg, or IDA Pro,您会收到反汇编请求,然后从 KeDelayExecutionThread() 条目开始调查。

关于文学,我可以向您推荐 Mark Russinovich 的书,Windows Internals

祝你好运!

例程正在执行系统调用。

mov eax, 34h  

上面的部分是将系统调用索引(又名。标识符)放入 EAX 寄存器,这是 Windows 内核稍后将依赖其内部 table 系统进行查找的内容服务程序。换句话说,这就是让 Windows 内核知道系统调用是针对 NtDelayExecution 的。

syscall

上面的部分实际上是让系统调用发生,这是从用户模式到内核模式的转换。 SYSCALL 指令是 x86 指令集的一部分。

然后 Windows 内核将获取 NtDelayExecution 的地址,该地址将出现在 NTOSKRNL(内核模式内存)下,调用它,然后将 return 状态传回给用户-模式版本的 NtDelayExecution 由 NTDLL 导出(除了系统调用让内核执行操作什么都不做)。

通俗地说,在用户模式下是查不到你要找的信息的; NtDelayExecution (NTDLL) 通过系统调用向内核发出信号,以便内核执行操作。您需要研究内核模式调试或在 NTOSKRNL 上进行静态逆向工程。

如果您可以研究一下内核模式调试,请在 NtDelayExecution (NTOSKRNL) 上设置一个断点,以便在它被用户模式调用者(通过系统调用)或内核模式调用者(不需要系统调用——因为在这种情况下,调用者已经处于内核模式)。