2.1 OllyDbg
关于操作部分均略过,因为现在已经没啥必要用ollydbg了
请使用x64dbg的32位版本(即x32dbg,但是你要搜索x64dbg下载)
2.1.4 断点
常见断点:
-
INT 3断点(软件断点)
- 快捷键:在所在行按F2
- 原理:调试器维护一组软件断点,并把断点位置的内存写为INT 3(也叫CC指令,因为内存中是0xCC)。如此一来,程序执行到断点时会执行INT 3,也就是触发INT 3异常,从而系统开始执行异常处理的过程。由于调试器存在,因此系统把异常交给调试器处理。调试器再通过当前地址判断是哪个断点,并写回原始内存。
- 优点:数目不限
- 缺点:通过检测内存是否被修改可以查出来
-
硬件断点
- 原理:使用DRx调试寄存器,具体用DR0~DR3设定地址,DR7设定状态。当触发时抛出单步调试异常(INT )
- DRx作用:DR0~DR3保存需要监视的地址,DR4-DR5未公开,DR6调试寄存器组状态寄存器,DR7调试寄存器组控制寄存器
- 优点:速度快,躲开软件断点的检测
- 缺点:少,只有4个,可删除硬件断点反调试
-
内存断点
- 原理:将所设地址所在的页设为不可写入或不可读取,从而在访问时触发单步调试异常。调试器取得并判断访问的地址是否为断点,若不是则继续运行,若是则交给我们调试。
- 优点:避开检测内存修改反调试
- 缺点:降低速度(每次访问断点所在的页都会中断,然后判断要不要给我们调试。访问次数可能很多,判断次数因此很多,则速度变慢)
(一些时候,内存断点和硬件断点可以互用。但如果硬件断点也失效,内存断点也可能还有用)
-
内存访问一次性断点
- 快捷键:ALT+M进入内存布局,然后选中需要下断点的段,按F2
- 功能:在读取或执行段的时候中断。
-
消息断点
- 本质:条件断点(见后文)
- 差别:INT 3启动前就能设置,消息断点只有在窗口被创建后才能设置
- 方法:点击句柄窗口,刷新后可得到句柄,选中句柄右键设置消息断点,适当设置即可
- 补充:
- 断点停在系统代码中,ALT+F9与CTRL+F9无法回到程序代码领空
- 对程序代码所在区块设置内存访问一次性断点即可
-
条件断点
- 快捷键:SHIFT+F2或者命令行
- 本质:带有条件表达式的INT 3断点
- 类型
- 按寄存器条件中断
SHIFT+F2:eax == 0x400000
命令行:不会((
表示当eax == 0x400000时停下
2. 按存储器条件中断
SHIFT+F2:streq(utf8(0x401232), "1234")
命令行:不会((
表示当0x401232处的指针指向的数据以utf-8解释所得字符串和“1234”相等时停下
7. 条件记录断点
1. 快捷键:SHIFT+F2
2. 语法:与前面一样,写好日志后,在日志条件窗口输入条件即可
8. 条件命令断点
1. 快捷键:SHIFT+F2
2. 语法:与前面一样,写好命令后,在命令条件窗口输入条件即可
2.1.5 插件
2.1.6 RUN跟踪
作用:记录运行时我们的每一次操作,从而后续分析可以参考这些操作
方法:进入跟踪页面,右键选择启动运行跟踪,然后选择保存目录
2.1.7 HIT跟踪
作用:划定大块代码,若通过则标记,从而方便判断执行流
方法:不会((,至今也没用过这个
2.1.8 调试符号
指为支持调试而摘录的调试信息
调试文件格式
1. CodeView格式
2. PDB格式(常见)
3. DBG格式(常见)
4. MAP格式(常见)
使用符号文件
掌握IDA导入即可,利用sync插件可以很轻松的实现IDA和x64dbg的同步调试,源代码看IDA的比x64dbg爽
2.1.9 加载程序
创建进程
程序拖进来或者F3选择文件打开
附加进程
意思是调试一个正在运行的进程
方法:ALT+A或者“文件>附加”
2.2 x64dbg
前文已经简介,仅补充部分
F2下断点,F9运行,CTRL+G跳转
dump rdx表示在内存窗口中跳转到rdx表示的地址
2.3 MDebug
从未用过或者听说,功能似乎不显眼,此处略去
2.4 Windbg
特点:可以分析内核和dump文件
2.4.1 安装与配置
版本
一般选x64即可
工作空间
可以保存窗口布局
调试符号
PDB符号文件:每个都有唯一的33位特征签名,靠这区分同模块不同版本的符号文件
地址:_NT_SYMBOL_PATH
符号加载:调试前,一般默认加载了调试符号,如果没有的话使用ld命令加载,再用lm检查符号文件加载情况
符号分类:由于调试的内核版本可能不同,因此建议将符号文件分类以便于管理
表示:”模块名!符号名“,内核统一用”nt“模块名
例子:
ntdll!NtOpenProcess表示ntdll.dll中的NtOpenProcess函数
nt!NtOpenProcess表示内核中的NtOpenProcess函数(两者不同)
检索方法:
格式:x [Options] Module!Symbol
支持特殊字符以模糊匹配
源代码调试:Ctrl+P
2.4.2 调试过程
开始调试
创建进程:Ctrl+E
附加调试:F6
转到入口:Alt+1或g @$exentry
调试命令
t | F8/ F11 | 步入 |
---|---|---|
p | F10 | 步过 |
g | F5 | 运行 |
ta addr | 步入到addr | |
pa addr | 步过到addr | |
tc [count] | 步入到调用第count个call前 | |
pc [count] | 步过到调用第count个call前 | |
tt | 步入到返回下次call前 | |
pt | 步过到返回下次call前 | |
th | 步入到下次分支前 | |
ph | 步过到下次分支前 | |
tb [count] | 步入到第count次分支指令,只适用内核 | |
wt | 自动追踪函数执行过程 |
pa @$ra:走出当前函数
2.4.3 断点命令
- 软件断点
- bp:跟地址或符号(功能复杂,此处略去)
- bu:跟符号(bu kernel32!GetVersion)
- bm:跟符号通配符(bm msvcr80d!print*)
- 硬件断点
- ba(与bp类似,功能复杂,此处略去)
- 条件断点
- bp/ba等后面可跟命令,用""括起
- 功能强大复杂,此处略去
- 管理断点
- bl:列出断点
- bc:删除断点
- bd:禁止断点
- be:启用断点
- 可用 * 匹配
- 例:bd 1-3,4 表示 禁止1-3,4号断点
2.4.4 栈窗口
查看栈回溯(k系列命令)
- k:显示基地址、返回地址和函数名地址
- kb:补充3个传参
- kp:将参数和参数值以函数原型形式显示(必须符号完整)
- kv:补充3个传参且增加FPO(栈指针省略信息)和调用约定
- kd:列出栈中数据
2.4.5 内存命令
- 查看内存
- 格式:以d开头,查看指定地址的内存数据
- 整型:如byte,word等取首字母,有db,dw等
- 浮点型:float对应df,double对应dD
- 指针:dp
- 字符串:ASCII:da;Unicode:du;ANSI:ds
- 数据结构:dt [模块名!]类型名(便于学习系统结构体)
- 搜索内存
- 格式:s -[type] range pattern
- type表示类型,如”b,w,d,a,u“
- range表示地址范围,包含起始地址和终止地址或者起始地址和长度(长度大于256MB要用L?length)
- pattern表示搜索内容
- 格式:s -[type] range pattern
- 修改内存
- 字符串:
- 格式:e{a|u|za|zu} address "String",za表示以\0结尾的ASCII字符串
- 例:eza 298438 "pediy" 表示在298438h处写入"pediy"
- 数值
- 格式:e{a|b|d|D|f|q|u|w} address [values]
- 例:eb 298438 70 65 64 69 79 表示在298438h处写入70 65 64 69 79,即"pediy"
- 字符串:
- 观察内存属性
- !address表示显示指定地址的内存属性
2.4.6 脚本
性质:一种语言
伪寄存器
包含下述几种:
- $exentry:进程入口地址
- $ip:指令指针寄存器
- $ra:函数返回地址
- $retreg:函数返回值
- $csp:栈顶
- $tpid:进程标识(PID)
- $tid:线程标识
- $ea:最后一条被执行指令的有效地址
- $p:最后一条被d命令打印的值
- $bpNumber:对应断点地址
- $t0~$t19:自定义伪寄存器
别名
分为固定别名和自定义别名
- 固定别名
- $u0~$u9,用r定义
- 例
r $.u0 = "Hello" // 不要遗漏“.”符号!在u0前面
- 自定义别名
- 命令:as,ad,al
- as:定义别名
- 例:as /选项 别名 位置
- 选项
- /ma:ASCII字符串
- /mu:Unicode字符串
- /msa:ANSI_STRING字符串
- /msu:UNICODE_STRING字符串
- /e:指定的环境变量
- /f:指定的文件内容
- ad:删除别名
- al:列出别名
- as:定义别名
- 例
- 命令:as,ad,al
0:000> da 04040dc // 查看ASCII字符串
004040dc "runtime error" // 回显
0:000> as /ma errorstring 04040dc // 定义别名
0:000> al // 列出别名
Alias Value // 回显
------- -------
errorstring runtime error
表达式
- 支持MASM和C++表达式(默认MASM)
- 求MASM用?符号,求C++用??符号
- 鉴于水平不足,待后续学习时补充完成
流程控制语句
.if .else .elif // 分支和判断
.do .while .for .continue .break // 循环
.block // 代码块
2.4.7 调试功能扩展
基本功能扩展
- 扩展模块在windbg安装目录,启动时默认加载
- !peb观察peb
加载自定义调试扩展
- 可以自行加载扩展模块DLL
// 指定路径
_NT_DEBUGGER_EXTENSION_PATH // 环境变量
.extpath ExtensionPath // 搜索扩展模块DLL
// 扩展管理
.load DLL模块 // 加载扩展
.unload DLL模块 // 卸载扩展
.chain // 显式已加载的扩展及搜索顺序
// 扩展执行
000:00>!xxx.yyy // xxx标识模块名,yyy表示命令
// 查看帮助
000:00>!help // 查看首个模块的help
000:00>!xxx.help // 查看xxx模块的help
自行编写扩展模块
- 开发接口位于sdk目录