windows - 如何使用 Windbg 从程序开始进行调试?
问题描述
我正在通过windbg在主机PC上的vmware中调试windows7。(内核版本 7601)
现在一切顺利,我想调试内核中运行程序的部分。换句话说,我想在我双击桌面上的任何程序运行它的那一刻调试内核中的交互。
许多指南告诉我如何附加到正在运行的进程。但是,我找不到在实际内核中创建进程之前进行调试的方法。
有谁知道如何做到这一点?或者,如果您有任何相关文件,请告诉我。
解决方案
先决条件 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...
启动您的虚拟环境并选择调试配置屏幕截图是串行配置
vm 应该启动并在 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 捕获和处理,并且经过很多时间才能到达这一点,现在它必须在用户模式下旅行更长的时间才能到达 Syscall () 在 ntdll
系统调用 ntdll!ZwCreateProcessEx 是将控制从用户模式转移到内核模式的地方
推荐阅读
- tfs - Mac 上的 tee-clc - 抛出 IllegalArgumentException: update.isFullyPopulated(setFileTimeToCheckin)
- apache - OrientDB 的 DocumentRoot 是什么?或者,OrientDB 的网络文件在哪里?
- java - 有效载荷类型的弹簧卡夫卡模糊方法
- windows - 为什么提交大小有时小于工作集(Windows 内存)
- java - 如何使表格组件中的所有行都拉伸到相同的高度?
- f# - 带有 Azure SQL Server / Azure Active Directory 的 FSharp 类型提供程序
- flask - 如何在 WTForms 中输入列表?
- mysql - mysqlcheck 返回错误信息 mysqlcheck: Got error: 1045: Access denied for user 'root'@'localhost' (using password: NO) 尝试连接时
- ios - 更改右栏项目上的标签文本swift 4
- javascript - Video.js 删除 HTML 跨度