小编byt*_*ptr的帖子

如何进行混合用户模式/内核模式调试?

基本上,我有一个用户模式程序调用kernel32.CreateProcessA(),它在内部调用kernel32.CreateProcessInternalW().在这个函数中,我对ntdll.NtCreateSection()中发生的事情感兴趣,它试图在虚拟内存中映射可执行文件.进入此函数后,程序会快速将内核调用设置为EAX = 0x32并执行SYSENTER指令.

显然,我无法在用户模式调试器中看到超出调用门.我有一点调试内核模式驱动程序的经验,所以我在VMWare窗口中加载了一个XP SP3副本,并使用VirtualKD将管道连接到WinDbg(我碰巧在IDA中运行).连接内核调试器后,我将用户模式EXE程序和PDB复制到虚拟机上,但我对如何在用户模式程序中正确设置初始断点感到茫然.我不想拦截对等效ntdll.ZwCreateSection()的所有调用,我认为这些调用是在调用门的另一端.理想情况下,我想进入用户模式代码并逐步通过该调用门,因为我正在使用内核调试器,但我不知道第一步是什么.

我做了一些谷歌搜索,我已经接近设置一个"ntsd -d"值

HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\myprocess.exe
Run Code Online (Sandbox Code Playgroud)

当我启动进程时,这会导致内核调试器中断,但我似乎无法在.breakin命令之后设置任何断点我需要向IDA发出以进入WinDbg提示符.我一直在关注这个指南,在那里我找到我的进程!进程然后切换到上下文,并重新加载符号,但我在设置我的进程中的断点或超过由"ntsd -d"设置的初始断点时遇到问题.在收到无法解析断点并添加延迟断点的消息之后,如果没有任何意义,我似乎无法在不清除断点的情况下"进入"流程.这是我在初次突破时看起来所处的堆栈:

ChildEBP RetAddr  
b2b55ccc 8060e302 nt!RtlpBreakWithStatusInstruction
b2b55d44 8053d638 nt!NtSystemDebugControl+0x128
b2b55d44 7c90e4f4 nt!KiFastCallEntry+0xf8
0007b270 7c90de3c ntdll!KiFastSystemCallRet
0007b274 6d5f5ca6 ntdll!ZwSystemDebugControl+0xc
0007bd48 6d5f6102 dbgeng!DotCommand+0xd0d
0007de8c 6d5f7077 dbgeng!ProcessCommands+0x318
0007dec4 6d5bec6c dbgeng!ProcessCommandsAndCatch+0x1a
0007eedc 6d5bed4d dbgeng!Execute+0x113
0007ef0c 010052ce dbgeng!DebugClient::Execute+0x63
0007ff3c 010069fb ntsd!MainLoop+0x1ec
0007ff44 01006b31 ntsd!main+0x10e
0007ffc0 7c817067 ntsd!mainCRTStartup+0x125
0007fff0 00000000 kernel32!BaseProcessStart+0x23
Run Code Online (Sandbox Code Playgroud)

说实话,我不确定我的PDB是否正在加载,但我怀疑它可能不是我的直接问题; 我的模块窗格仅显示内核驱动程序模块,而不是用户模式模块.当我过去做过驱动程序调试时,我可以在这个窗格中看到我的驱动程序图像以及符号是否已加载,所以我不确定用户模式图像会发生什么.没有图像,我真的不希望调试器解决任何断点.

我意识到我可能会完全错误,但我没有运气寻找如何进行用户模式/内核模式混合调试.有没有人可以指出我正确的方向,所以我可以从特定的用户模式进程进入这个内核模式功能?或者,至少设置一个适当的内核模式断点,以便仅在我的特定用户模式进程中触发它?

更新:我在调试的操作系统上的用户模式调试器中加载了我的模块(恰好名为runlist.exe)(我碰巧使用了OllyDbg).一旦我在用户模式断点处暂停了SYSENTER的几条指令,我就使用内核调试器暂停了操作系统.然后我设置了流程上下文.WinDbg命令窗口内容如下:

WINDBG>!process 0 0 runlist.exe

PROCESS 820645a8  SessionId: 0  Cid: 01b4    Peb: 7ffd7000  ParentCid: 02b0
    DirBase: …
Run Code Online (Sandbox Code Playgroud)

windbg ida

10
推荐指数
1
解决办法
2815
查看次数

当你可以使用RET时,为什么在Win32下需要ExitProcess?

我注意到许多使用直接Win32调用构建的汇编语言示例(没有C运行时依赖性)说明了使用对ExitProcess()的显式调用来在入口点代码的末尾结束程序.我不是在谈论使用ExitProcess()在程序中的某个嵌套位置退出.令人惊讶的是,入口点代码只是通过RET指令退出的示例较少.想到的一个例子是着名的TinyPE,其中程序变量以RET指令退出,因为RET指令是单字节.使用ExitProcess()或RET似乎都可以完成这项工作.

来自可执行文件入口点的RET将EAX的值返回给KERNEL32中的Windows加载程序,最终将退出代码传播回NtTerminateProcess(),至少在Windows 7上.在Windows XP上,我想我记得看过ExitProcess ()甚至直接在线程清理链的末尾调用.

由于汇编语言中有很多受人尊敬的优化,纯粹是在生成较小的代码时选择的,我想知道为什么更多的代码浮动更喜欢显式调用ExitProcess()而不是RET.这个习惯还是有其他原因吗?

从最纯粹的意义上讲,RET指令不会优于直接调用ExitProcess()吗?直接调用ExitProcess()似乎类似于通过从任务管理器中删除它来退出程序,因为这会使返回到Windows加载程序称为入口点的正常流程短路,从而跳过各种线程清理操作?

我似乎找不到任何特定于这个问题的信息,所以我希望有人可以对这个话题有所了解.

assembly winapi

5
推荐指数
1
解决办法
837
查看次数

标签 统计

assembly ×1

ida ×1

winapi ×1

windbg ×1