今天具体学习一下双机调试。

前言

肯定主要就是这个调试器怎么去用了,这里我贴一下 VirtualKD 的项目地址——(https://github.com/4d61726b/VirtualKD-Redux)。也由衷地感谢这些开发者给我们开发了这么好用的工具,让我们环境搭建这一步走了很大的捷径,上一篇博客中遇到的问题,当时因为比较急直接去提了 issue,而作者也给出了很耐心的解释,应该是照顾我这个萌新吧。

真的是非常感谢。

Windbg的使用

我是实在用不来那个纯命令行的调试器,因为根本不知道跑起来之后怎么加断点,所以我使用了 Windbg preview,这个据说是要在微软商店下载的,如果停用了 windows 更新的话,好像就直接用不了了,为了这个我重新打开了我 windows 的更新。

初始布局大概是这样:

当提示 Debuggee is running 的时候,是没办法在 KD 命令行输入指令的,断点也打不了。

最开始的情况应该是:这里根本就不知道在哪的,左边的反汇编窗口应该也不是指向了自己想要的位置,此时不知道在哪里断就可以先放着,然后点 break 暂停,这个暂停是无条件的,可以立刻暂停虚拟机的运行,此时KD 命令行可以输入指令了,我们需要找到一个断点使得能在我们想要的地方暂停,这里我们可以直接使用 bp 命令下断点:

比如我们驱动是 xxxxxxx.sys,那么我们想要在这个驱动加载的时候断在 DriverEntry 这个函数就可以输入 bp xxxxxxx!DriverEntry 下断点,或者直接在搜索框输入 xxxxxxx!DriverEntry 然后下断点。

这里可能在加载驱动的时候会蹦出来源码,但是源码调试还是比较坑的,只有汇编是比较精准的结果,所以源码参照就行了,调试主要还是看汇编。

比如之前的 blog 中也有些问题,就是在打印的时候,那个变量总是不对,总是打印出 0xFF 开头的值,于是我就可以找到那个地方,使用 KMDFDriver2!MyProtect 去下断点,然后看看发生了啥。

于是在这里调试的时候,发现问题了,因为 ACCESS_MASK 是定义为 ULONG 的,我以为是 64 位结果就只有 32 位,可能因为这个就输出的一直不对吧,所以后面我选择使用 %x 去打印这个值,看起来也舒服一点。

后面就抄一下网上的其他师傅写的 blog 吧,来介绍下 windbg 的具体操作。

  • 步进指令(step in):t 或者 .step
  • 步过指令(step over):p 或者 .stepover
  • 跳出指令(step out):gu 或者 .stepout
  • 继续运行(continue):g
  • 打印寄存器状态:r
  • 打印单个寄存器:r <%eax>
  • 打印所有寄存器:r*
  • 查看内存:d <memory address> <len>,如果要字,双字,四字的形式显示,把 d 改成 dbdwdddu 可以查看unicode字符串。参数 len 好像要在前面加上 l 作为修饰符。
  • 设置断点:bp <address>
  • 设置条件断点:bu <address> <addtion> 其中第三个参数可以设置寄存器状态的判断。
  • 列出断点列表:bl
  • 删除断点:bd,可以跟一个编号删除指定断点,也可以使用通配符 * 删除所有断点。
  • 禁用断点: be
  • 启用断点:bc
  • 设置硬件断点:ba <type> <address> [len],这里的type可以是以下三种之一:
    • r:读取断点,当指定地址上的数据被读取时触发断点。
    • w:写入断点,当指定地址上的数据被写入时触发断点。
    • e:执行断点,当程序执行到指定地址时触发断点
  • 列出当前模块:lm
  • 列出当前模块详细信息:lml
  • 加载模块:ld <dll-path>

剩余的命令再摸索吧。。