如何使用 Windbg 从程序开始进行调试?

Posted

技术标签:

【中文标题】如何使用 Windbg 从程序开始进行调试?【英文标题】:How can I debug from the start of a program with Windbg? 【发布时间】:2021-11-30 08:51:07 【问题描述】:

我正在通过windbg在主机PC上的vmware中调试windows7。 (内核版本 7601)

现在一切顺利,我想调试内核中运行程序的部分。 换句话说,我想在我双击桌面上的任何程序运行它的那一刻调试内核中的交互。

许多指南告诉我如何附加到正在运行的进程。但是,在实际内核中创建进程之前,我找不到调试方法。

有人知道怎么做吗?或者,如果您有任何相关文件,请告诉我。

【问题讨论】:

【参考方案1】:

先决条件 2) 对进程创建的基本了解(如果不是数十亿,至少有数百万次的操作,从双击到 GUI 的出现,只有极少部分发生在内核中)

    vmware 或任何虚拟环境作为目标已正确设置,带有用于内核调试的串行或网络调试 正确安装了windbg的主机 以管理员身份在主机中运行windbg

--------例如,如果你有一个管道作为串行连接,它应该看起来像这样

windbg 应该像这样启动并等待连接

Microsoft (R) Windows Debugger Version 10.0.17763.132 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

Waiting for pipe \\.\pipe\vmwpipe
Waiting to reconnect...

启动你的虚拟环境并选择调试配置截图是串口配置

虚拟机应该启动并在windbg中产生一个初始断点 需要用 g->enter 或 f5 确认

在此之后离开几分钟以完成登录到 vm 在 windbg 中按 alt+delete 或 ctrl+break 打破f5 或 g->enter 多次放弃对 vm 的控制

现在您已准备好检查您的流程创建 正如我在先决条件中提到的,您需要对流程创建有一个通用的基本概念 你应该知道双击是由 shell (explorer.exe) 处理的 它处理双击并通过调用 CreateProcess() 启动进程创建 CreateProcess 以前是 kernel32 中的一个完整的 api,现在它是一个将调用转发给 kernelbase.dll 的存根,后者将其转发给 ntdll 及其内核对应物 ntexecutive (ntoskrnl,ntkrnlmp)。

do !process 0 0 explorer.exe tofetch the _EPROCESS of explorer.exe

do .process /p /P /r _EPROCESS fetched earlier 

.reload /f explorer.exe

在 explorer.exe 中的 CreateProcess Import 上设置一个特定于进程的断点,如下所示,然后双击您的 vm 中的 calc.exe 以获得如下中断

0: kd> bp /p ffff9509`0b03b300 poi(Explorer!_imp_CreateProcessW)
0: kd> g
Breakpoint 4 hit
KERNEL32!CreateProcessWStub:
0033:00007ffb`21dfc020 4c8bdc          mov     r11,rsp
1: kd> k
 # Child-SP          RetAddr           Call Site
00 00000000`1732e8f8 00007ffb`2103ec10 KERNEL32!CreateProcessWStub
01 00000000`1732e900 00007ffb`20fed0ee windows_storage!CInvokeCreateProcessVerb::CallCreateProcess+0x124
02 00000000`1732ebb0 00007ffb`20f8fde8 windows_storage!CInvokeCreateProcessVerb::_PrepareAndCallCreateProcess+0x1c2
03 00000000`1732ec30 00007ffb`20f8fbc7 windows_storage!CInvokeCreateProcessVerb::_TryCreateProcess+0x84
04 00000000`1732ec60 00007ffb`20f8f82d windows_storage!CInvokeCreateProcessVerb::Launch+0xfb
05 00000000`1732ed00 00007ffb`20feb31d windows_storage!CInvokeCreateProcessVerb::Execute+0x5d
06 00000000`1732ed40 00007ffb`20fe6014 windows_storage!CBindAndInvokeStaticVerb::InitAndCallExecute+0x169
07 00000000`1732edc0 00007ffb`20fe7eea windows_storage!CBindAndInvokeStaticVerb::TryCreateProcessDdeHandler+0x68
08 00000000`1732ee40 00007ffb`20fe459d windows_storage!CBindAndInvokeStaticVerb::Execute+0x1ba
09 00000000`1732f150 00007ffb`20fe4495 windows_storage!RegDataDrivenCommand::_TryInvokeAssociation+0xb5
0a 00000000`1732f1c0 00007ffb`22c7880f windows_storage!RegDataDrivenCommand::_Invoke+0x145
0b 00000000`1732f230 00007ffb`22c786ca SHELL32!CRegistryVerbsContextMenu::_Execute+0xcb
0c 00000000`1732f2a0 00007ffb`22c184e7 SHELL32!CRegistryVerbsContextMenu::InvokeCommand+0xaa
0d 00000000`1732f5a0 00007ffb`22c22549 SHELL32!HDXA_LetHandlerProcessCommandEx+0x117
0e 00000000`1732f6b0 00007ffb`22df9a29 SHELL32!CDefFolderMenu::InvokeCommand+0x139
0f 00000000`1732fa10 00007ffb`230b4409 SHELL32!SHInvokeCommandOnContextMenu2+0x1f5
10 00000000`1732fc50 00007ffb`2244c315 SHELL32!s_DoInvokeVerb+0xc9
11 00000000`1732fcc0 00007ffb`21df81f4 shcore!_WrapperThreadProc+0xf5
12 00000000`1732fda0 00007ffb`2461a251 KERNEL32!BaseThreadInitThunk+0x14
13 00000000`1732fdd0 00000000`00000000 ntdll!RtlUserThreadStart+0x21

你可以看到使用类似这样的东西传递的参数

1: kd> .printf "lpApplicationName = %mu\nlpCommandLine = %mu\nlpProcessAttributes %p\nlpThreadAttributes %p\nbInheritHandles = %x\ndwCreationFlags %x\nlpEnvironment=%p\nlpCurrentDirectory=%mu\nlpStartupInfo=%p\nlpProcessInformation=%p\n" , @rcx,@rdx,@r8,@r9,dwo(@rsp+28),dwo(@rsp+30),dwo(@rsp+38),dwo(@rsp+40),dwo(@rsp+48),dwo(@rsp+50)
lpApplicationName = C:\Windows\System32\calc.exe
lpCommandLine = "C:\Windows\System32\calc.exe" 
lpProcessAttributes 0000000000000000
lpThreadAttributes 0000000000000000
bInheritHandles = 0
dwCreationFlags 4080414
lpEnvironment=0000000000000000
lpCurrentDirectory=C:\Windows\System32
lpStartupInfo=0000000012576758
lpProcessInformation=00000000125767f0

这只是冰山一角 正如您从调用堆栈中看到的那样,双击被 shell32.dll 捕获和处理,并且经过了很长时间才能到达这一点,现在它必须在用户模式下运行更长的时间,直到它到达 ntdll 中的 Syscall()

系统调用 ntdll!ZwCreateProcessEx 是将控制从用户模式转移到内核模式的地方

【讨论】:

以上是关于如何使用 Windbg 从程序开始进行调试?的主要内容,如果未能解决你的问题,请参考以下文章

如何设断点????-----使用WinDbg调试SQL Server查询

开始学习 Windbg [关闭]

如何使用WinDbg调试进程信息

如何使用WinDBG跟踪调试ASL/ACPI

如何使用WinDBG跟踪调试ASL/ACPI

如何手工抓取dump文件