调试器
带MFC界面的简易调试器;
能实现常用基本调试功能;
功能
软件断点
硬件断点
内存访问断点
条件断点
API断点
汇编/反汇编
寄存器信息
堆栈信息
模块信息
单步步入/步过/运行
导入导出表信息
dump文件
symbol符号解析
打开/拖入
附加/脱离
命令行执行
快捷键操作
#编译环境
Win10 VS2015;
GitHub
https://github.com/dkni0/AE86_dbg
截图
主界面
模块信息
菜单信息
#程序操作
##快捷键
普通断点 F2
单步步入 F7
单步步过 F8
运行 F9
##命令行格式
备注:
命令参考自windbg
所有命令不区分大小写;
地址不足八位必须前面补0;
命令和参数中间以一个空格隔开;
###普通指令
-
g 运行
程序直接运行;
遇到断点暂停;
如无断点则不能再控制; -
t 单步步入
单步运行;
遇有函数则会进入运行; -
p 单步步过
遇到call指令直接运行下一行指令;
其他指令与单步步入模式相同; -
s 脱离程序
取消调试程序;
被调试程序可正常运行; -
q 结束被调试程序
取消调试并结束被调试程序; -
u 显示指定地址反汇编信息
格式:u [address]
示例:u 000a1005
功能:在指定地址处设置int3普通断点 -
ml 显示模块列表
格式:ml
功能:显示模块列表 -
db 显示指定地址内存信息
格式:db [address]
示例:db 000a1050
功能:显示指定位置内存信息; -
dl Dll注入
格式:dl [pid] [DllPath]
示例:dl 12345 D:\TerminateProcess.dll
功能:注入指定进程dll文件;
此处pid为十进制; -
df 卸载dll
格式:dl
功能:卸载已注入的dll文件;
注入dll后才可使用该命令; -
dump
格式:dump [path]
示例:dump d:\123.exe
功能:dump文件至指定位置;
###修改程序
-
r 修改寄存器
格式:r [erx] [value]
示例:r eax 12345678
功能:修改指定寄存器的值;
仅供修改eax,ecx,edx,ebx; -
eip 修改eip
格式:eip [address]
示例:eip 000a1050
功能:修改eip为指定地址,
下一行命令从所改位置处运行; -
ao 修改OPCode
格式:ao [address] [OPCode]
示例:ao 000a1050 12 34 56 78
功能:修改反汇编窗口中可见的OPCode指令;
地址应为反汇编窗口中的地址;
指令不超过该位置原有指令长度; -
ai 修改汇编指令
格式:ai [address] [Instruction]
示例:ai 000a1050 nop
功能:修改反汇编窗口中可见的汇编指令;
地址应为反汇编窗口中的地址;
###断点设置
-
bp 普通断点
格式:bp [address]
示例:bp 000a1005
功能:在指定地址处设置int3普通断点 -
bm 内存断点
格式:bm [address] [type]
示例:bm 000a1005 a
示例:bm 000a1005 w
功能:在指定地址处设置内存断点,类型可选访问(a)或写入(w); -
bh 硬件断点
格式:bh [address] [type] [length]
示例:bh 000a1005 a b
示例:bh 000a1005 w d
功能:在指定地址处设置硬件断点,
类型可选访问(a)或写入(w)或执行(e);
长度可选字节(b),字(w),双字(d);
执行断点只支持字节; -
bi 条件断点
格式:bi [address] [value]
示例:bi eax 10
示例:bi 000a1005 12345678
功能:在指定地址处设置条件断点,符合条件断下,不符合条件则略过;
地址可选寄存器(eax,ecx),或内存地址;
值需输入十六进制数; -
ap API断点
格式:ap [FunName]
示例:ap MessageBoxW
功能:在指定地址处设置API断点;函数名称正确下断点,否则返回错误;
API名称区分大小写;
#调试原理
吐槽:
这编辑器居然没有自动保存草稿功能吗????
保存还会出错啊啊啊啊啊???
出错还直接崩溃关闭!!
白忙活了半天。。。。
-
异常分发流程
-
调试器交互流程
调试器建立调试事件,主动产生异常,
根据异常分发机制,来实现调试程序
##断点原理
-
软件断点
保存指定地址原有字节;
替换为0xCC
(int 3指令),
CPU运行到这里产生异常断下,
再恢复原有字节; -
硬件断点
设置调试寄存器,
断点地址写入DR0~DR3寄存器,
断点类型写入DR7寄存器的RW0~RW3中,
断点有效标志写入DR7寄存器L0~L3中,
断点长度写入DR7寄存器的LEN0~LEN3中,
硬件执行断点只能为单字节;
硬件读写短的为2、4时地址需要对齐; -
内存断点
更改指定地址所在内存分页的访问页属性,
出发异常后,恢复页属性,
执行单步到断点地址处; -
条件断点
指定地址位置写入软件断点,
断下后再根据条件判断是否继续;
不符合条件则略过; -
API断点
通过调试符号服务器获取API地址,
在地址位置下断; -
单步断点
修改CPU标志寄存器的TF标志位,
置为1即可实现单步断点; -
单步步过
判断当前指令是否为call或rep重复指令,
是的话在下一条指令位置下软件断点,
运行程序,断到下一条指令位置;
否则执行单步断点
项目设计
反汇编使用BeaEngine引擎;
汇编使用XEDParse引擎,
程序运行需要XEDParse.dll
文件;
需要管理员权限;
获取context
信息,显示寄存器信息,
根据寄存器信息,读取远程内存,
实现反汇编信息显示,
内存信息显示,堆栈信息显示,
遍历目标模块,显示模块信息
dump文件,
根据PE信息,
读取相应区段,
再写入到文件;
项目难点,
界面与工作线程分离,
不能产生冲突,
通过enent
事件同步,
工作线程完成任务发送消息,
界面再刷新;
符号有点麻烦,
也可能环境的问题,
本机符号信息显示不太完整;
相关参考:
《一个调试器的实现》系列
http://www.cnblogs.com/zplutor/archive/2011/03/20/1989783.html
#End