WinDbg. From A to Z! 笔记(下)
原文链接: WinDbg. From A to Z!
文章目录
- 使用WinDbg
- 临界区相关命令
- 示例 -- 查看临界区
- 其他有用的命令
- WinDbg中的伪寄存器
- 自动伪寄存器
- WinDbg中的表达式
- 其他操作
- 默认的表达式计算方式
- WinDbg中的重命名
- 调试器命令语言编程
- 控制流
- 命令程序执行
- WinDbg 远程调试
- 事件监控
- WinDbg 事件过滤器
- 事件过滤器对话框
- 事件参数
- 全局标志 (Global Flags)
- Flags? GFlags? Global Flags!
- Global Flags
- 应用程序验证器
- 启用应用程序验证器
- 应用验证器的实体
- 应用验证器的调试符号
- `!avrf`的常用参数
- 示例 -- 使用 `!avrf`
- 进程转储 (Process Dumps)
- Dumps的类型
- 确定Dump文件的类型
- 示例 -- 使用`.dump`命令
使用WinDbg
临界区相关命令
** !avrf
是Application Verifier 的内容
示例 – 查看临界区
这里有一个简单的死锁例子
暂时跳过
其他有用的命令
命令 | 描述 |
---|---|
dt | 显示某些数据的信息如,局部变量,函数参数,全局变量,数据类型 |
dt 模块名!类或命名空间或函数 | 列举模块里的类型的定义 |
dt 模块名!类::函数或变量 地址 | 显示具体实例的值 |
dt ntdll!_PEB 7efde000 | 显示7efde000处_PEB实例的信息 |
dv | 显示局部变量 |
dv /i /t /V | /i 指区分是参数还是变量, /t 显示类型信息 , /V 显示详细信息 |
WinDbg中的伪寄存器
- 用在调试器里面的虚拟寄存器,像变量一样
- 以
$
符号开头
-
自动伪寄存器(内置的伪寄存器)
- 调试器本身设置的
- 如: $ra , $peb , $teb
-
自定义伪寄存器
- 有20个预设的自定义寄存器:
$0
~~$19
- 可用于存储中间数据的整数变量
- 可以额外保存类型信息
- r 命令用来赋值
- ?? 命令用来输出
- 有20个预设的自定义寄存器:
自动伪寄存器
命令 | 描述 |
---|---|
$ra | 当前的堆栈地址 |
$ip | 指令指针 |
$exentry | 进程入口 |
$retreg | 返回值寄存器 |
$csp | 调用栈地址 |
$peb | PEB |
$teb | TEB |
$tpid | 进程ID |
$tid | 线程ID |
$ptrsize | 指针大小 |
$pagesize | 分页大小 |
WinDbg中的表达式
-
宏汇编(MASM) 表达式
- 使用
?
来计算 - 每个符号都被视为一个地址
- 可以使用源码行表达式, 如
myfile.c:43
- 寄存器的
@
符号不是必须要写的 - 数值默认是16进制的,
0n
是10进制,0t
8进制,0y
2进制
- 使用
-
C++ 表达式
- 使用
??
来计算 - 符号被理解为某个类的对象
- 不能使用源码行表达式
- 寄存器前必须有
@
符号 - 数值默认是10进制的, 16进制以
0x
开头
- 使用
其他操作
默认的表达式计算方式
WinDbg中的重命名
例子:
调试器命令语言编程
- 两大部分
- 调试器命令
- 控制流,如(.if, .for, .while )
- 变量
- 重命名当作局部变量
- 伪寄存器作变量
$$
作为行注释开头- 一对大括号是一个作用空间
控制流
- 用来循环和条件分支
命令程序执行
- 方法一: 将所有语句当作单个字符串输入到命令窗口
- 方法二: 编译到文件中,使用命令
$$><
来执行文件
WinDbg 远程调试
事件监控
- 调试器引擎提供了用于监视与响应目标应用程序事件的工具
- 事件分为两类:
- 异常事件
- 断点、访问违规、堆栈溢出、除零等。
- 非异常事件
- Create Process, Create Thread, Load Module, Unload Module.
- 异常事件
- 调试器会话可访问时,会有一个lastevent
- 命令:
.lastevent
- 命令:
WinDbg 事件过滤器
-
提供了简单的事件过滤
-
目标应用的事件发生后的响应
-
使用
sx
命令来列举所有事件 -
中断或执行状态:
- 可能会中断目标
- sxe : first-chance break (原文里这个不太明白) , 启用 enable
- sxd: second-chance break , 不启用 disenable
- sxn:事件发生后输出日志 , note
- sxi:忽略事件, ignore
- 可能会中断目标
-
处理或继续状态:
- 确定在目标中是否应将异常事件视为已处理(gH)或未处理(gN)
事件过滤器对话框
事件参数
- 一些过滤器采用参数来限制它们要处理的事件
- 无参数就是无限制
全局标志 (Global Flags)
Flags? GFlags? Global Flags!
- GFlags通过编辑Windows注册表来启用和禁用功能
- GFlags设置系统或映象
- 映象的设置在
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ImageFileName\GlobalFlag
- 操作系统读取这些设置并相应地采用其功能
- GFlags可以从命令行或使用对话框运行
- 可以在WinDbg 中使用
!gflags
命令来操作Global Flags - 用GFlags可以实现:
- 堆检查
- 堆标记
- Loader snaps
- 调试映象
- 应用验证
- 等等等等
Global Flags
安装了Windows SDK的话会在这里找到Global Flags
应用程序验证器
启用应用程序验证器
- 应用验证
- 是Windows应用程序的运行时验证工具
- 正在监视应用程序与操作系统的交互
- 概览与轨迹跟踪:
- 内核对象
- 寄存器
- 文件
- 异常
- Win32 API
- 使用
!avrf
来得到跟踪信息
应用验证器的实体
-
GFlags Application Verifier
- 只有verifier.dll被注入到目标进程中
- verifier.dll随被Windows预装
- 提供了少量选项子集
-
Application Verifier
- 从微软官网免费下载
- 另外安装vrfcore.dll、vfbasics.dll、vfcompat.dll等进入Windows\System32
- 功能强大
应用验证器的调试符号
- 应用程序验证器与PDB一起安装,具有完整的符号信息
- 在disassembly窗口里标记源码信息
- 这些是我见过的唯一一个带有完整符号的微软模块信息
- 事实上,WinDbg必须使用这些符号,而不是服务器上的公共符号。否则
!avrf
扩展无法工作
.reload /f @"C:\Windows\System32\verifier.pdb
!avrf
的常用参数
示例 – 使用 !avrf
如果已经安装了Windows SDK,那么可以在系统中找到Application Verifier
,打开Application Verifier,添加应用,在右边的Tests框中选择需要测试的项目。
点击Save后,重启应用,完事之后用WinDbg来调试目标应用。
在Modules 里面Reload Application Verifier
这样就会执行.reload /f @"C:\WINDOWS\SysWOW64\verifier.dll"
先看一下Heap相关的操作日志
查看线程
进程转储 (Process Dumps)
- 进程转储文件
- 与非侵入性附着非常相似
- 表示给定时间进程的快照
- 大小不同,取决于它包含的内容和信息
- 利用转储文件
- 我们可以检查内存以及进程的其他内部结构
- 我们无法设置断点或逐步执行程序
- Dump 一个转储文件
- 我们总是可以将包含更多信息的转储“缩小”为包含更少信息的转储
- 像处理实时进程一样使用.dump命令
Dumps的类型
-
Kernel-mode Dumps
变体:完整内存转储、内核内存转储、小内存转储 -
Full User-mode Dumps
- WinDbg中用
.dump /f
生成 - 包括进程的整个内存空间、程序的可执行映像本身、句柄表
- 过去被广泛使用的微软正在慢慢放弃对它的支持
- WinDbg中用
-
Minidumps
.dump /m??
- 现代化dumps格式
- 对转储中包含的内容进行细粒度控制(请参阅MSDN:MINIDUMP_TYPE)
- 尽管有它们的名字有迷你的字眼,但最大的迷你转储文件实际上包含的信息比完整的用户模式转储更多。如
.dump /mf
或.dump /ma
得到的文件比.dump /f
得到的更大更完整。
确定Dump文件的类型
用WinDbg 加载Dump文件,加载成功后会输出dump文件的类型