WinDbg 调试实战入门 - 调试第三方程序(记事本)

   专栏   ┇ 『Debug』『Debug』

 上一篇  ┇ 《WinDbg 源码级调试 C++ 程序》

WinDbg 源码级调试 C++ 程序_c++ windbg调试经典项目解析-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_41863029/article/details/138963604


        在上一篇 《WinDbg 源码级调试 C++ 程序》文章中,我们讲到了 WinDbg 的安装和配置方法,并以一个自己写的程序为例进项源码级的调试,对 WinDbg 的功能和使用有了一个初步感性认识。这一篇中,我们将调试没有源码的第三方程序。这是大多数真实调试情境。

        很多时候,我们需要去调试的程序并没有源码,或者源码不匹配。另外,例如 Windows 自身的程序或者第三方库、程序,我们是没有源码的。但需要了解它们的运行逻辑或查找卡死、崩溃原因,这个时候 WinDbg 就可以帮助我们。

        下面我们以记事本为例,实战一次真实的调试流程。

🚩 调试目标

        通过本次调试实战练习,我们掌握以下三点技能:

  • 加载调试符号
  • 设置断点
  • 查看线程堆栈

        流程很简单,用到的命令也不多。跟随本篇文章逐步操作,再自己独立完成几次,就掌握了最基本的调试方法。

▶ 加载调试程序符号

        启动 Windbg.exe CTRL+E,或点击菜单 File/OpenExecutable 打开选择系统目录下的 notepad.exe         

        此时记事本进程已启动,但还看不到窗口,因为 Windbg 会暂停到程序入口处。

         Windbg 进入等待命令状态。

        首先,加载符号,分别输入如下两条命令:

.sympath srv*
.reload

        通过 lm 命令查看下当前加载的模块和符号情况

        如上图, notepad 后显示的是 deferred ,说明符号并没有加载上,我们需要输入以下两条命令强制符号重新加载:

!sym noisy
.reload /f

        再次使用 lm 命令检查模块及符号信息

        或者通过 !chksym 命令检查 notepad 模块的符号信息:

        显示出了详细的符号信息,说明模块的符号都已经正确加载。

        我们用 x 命令查看模块内部的符号信息。 

x moduleName!symbolName

        这将显示模块 moduleName 中名为 symbolName 的符号详细信息。如果  symbolName 为 *,则显示moduleName模块下的全部符号。

x notepad!*
notepad 中的所有符号信息

     符号信息很多,我们可以只查找关心的部分函数,比如我们想查看记事本的 main 函数,由于它是窗口程序,那么main函数的名称应该是 wWinMain,所以我们使用 x notepad!wWin* 以模糊匹配的方式搜索以 wWin 开头的函数列表:

        其中 wWinMain 即为记事本程序的 main 函数。

▶ 设置断点

        如果我们希望记事本进入 main 函数的时候可以被终端下来,则用 bu 命令下断点

bu notepad!wWinMain

        检查断点是否成功

bl

        确认成功后,按下 g 让程序跑起来,等待记事本运行到 WinMain 函数,它会被 windbg 终端暂停下来。

▶  查看线程堆栈

        此时,我们就可以用 k 命令查看堆栈信息:

        或者 Alt + 6 调出堆栈窗口,以窗口形式显示出了同样的信息。

        继续 g 让记事本运行,此时记事本窗口才正常显示出来。

        刚才的操作验证了断点确实生效了,我们不妨再做个断点的试验,断下程序对 Windows API 的调用,例如写文件操作最终会调用到 ntdll中的ZwWriteFile函数,我们就在 ntdll 模块中下个断点,同样下断后用 bl 命令检查断点:

bu ntdll!ZwWriteFile

bl


 

        我们看到 ntdll中的ZwWriteFile 断点生效了,同时之前的 wWinMain 断点也在断点列表中。用 g 命令 或 F5,让程序继续跑。

        为了让程序触发文件写操作,在记事本窗口中,输入一些文本。 在“文件”菜单中,选择“保存”。 运行代码在 ZwCreateFile 处中断。

        中断后,除了用前面提到的 k 命令可以查看堆栈,还可以使用 ~ 命令查看所有线程的列表。

        或者通过 ALT+9  调出进程线程窗口,一样可以方便的查看线程列表,这里共显示了11个线程,线程的序号作为索引,从0开始。

        每个线程有自己的堆栈,用 ~0s 命令切换线程, 如要查看线程 0 的堆栈,则输入

~0s

k

        因为有了足够的符号,显示出了非常详细的堆栈信息 ,降低了调试难度。

💡

        在以上命令输入后,有可能 windbg 会下载本地缺失的符号,处于忙的状态,等待下载完毕即可。

        最后,输入 qd ,即可退出调试。

💬 总结

        调试信息的丰富度和易读性主要依赖于符号文件,调试器需要符号文件来获取有关代码模块的信息,例如函数名称和变量名称。如果有符号文件,则后续的工作难度会大大降低。

        本篇的调试流程简单,但覆盖了符号配置、断点设置、线程切换、查看堆栈这些基本的操作。Windbg 的命令十分强大,参数也很丰富,我们将在后续逐步学习掌握。

  • 74
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0x0007

可不可奖励我吃只毛嘴鸡 馋😋

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值