开源一个自己 正在写的调试器,希望可以给你看到不一样的烟火

2019-01-11  本文已影响51人  看雪学院


0x00 前言

几年前,刚接触逆向的时候,自己就萌生一个要单独写一个调试器的想法(当时就觉得自己动手做一个项目,是学习最快的途径)。但彼时的我没有那么多时间去折腾。今年意外地得到一份比较长的病假,遂想着把当时的初衷给完成了。经过一段时间的学习和探索,虽然还不能完全实现自己理想中的调试器,但也已经初具雏形了。

那我为啥选择这个时候发出来,而不是等到完成之后再发呢?因为随着项目的推进,自己也开始觉得个人能力和精力的有限。仅凭我个人的努力绝非一朝一夕就能完成它的,况且自己做了这段时间以来,也隐约看到了自己的瓶颈。遂有了把它开源出来的想法,一则可以找些志同道合的朋友完成它,也提升自己的能力;二来,也是趁着这个月自己的病假结束了,希望可以转行找一份逆向相关的工作(研发或者安全相关的工作最好)。

0x01 整体框架

在动手做之前,我就对要实现什么样功能的调试器这点上思考了很久。最后决定要做就做逼格高点的,确定了硬件虚拟化支持+闪瞎眼的界面+动态脚本支持为发展方向。

硬件虚拟化

自己在参照intel手册做硬件虚拟化驱动时,在填充VMCS区域时碰到了问题,让我一点头绪也找不到,所以这部分就暂且没做。已完成的相关源码也包含在工程vt_driver 里面了,因为64位不支持内联汇编,所以就设定了vt_lib_32和vt_lib_64两个工程为其提供统一接口的的静态函数库(vs虽然为大部分指令提供了相应的函数,但当时自己为了更深入的学习以及了解各个指令的实现细节,就坚持自己写了相关指令对应的C调用函数)。

界面库

我并不喜欢OD的界面,感觉窗口切换太繁琐了。WinDBG的窗口还好点,可以浮动也可以固定,在数据对比的时候很方便。后面我在思考界面的形式的时候就萌发了新的一种交互方式:可分离式界面(反正也是学习过程,多探索总没坏处)。所谓的可分离式界面就是调试器外观的各个可视化组件都可以由用户自己去配置组合。但是怎么去配置组合,开始我也不是很确定。直至接触到了DuiLib的时候,思路就渐渐明晰了。就像DuiLib的界面一样,用户可以自己去通过XML去调节配置自己需要的外观,那剩下的分离和显示,就只需要程序内部绑定好相应的元素就行了。因此我就选择了DuiLib作为界面开发库。

动态脚本

python那么火,不用它才怪,再说我也只会这种动态脚本(。。。逃)。当然,选这个还有其他理由:更快的脚本开发速度以及更多的扩展支持。当然后续自己如果想学机器学习的话,也还能在这上面折腾下。

调试器

因为自己写这个调试器的初衷就是为了学习,所以对于关键的基础设施,我都是参考资料来自己动手写。目前做的汇编引擎和反汇编引擎都是参考 intel手册来做的。调试引擎还没怎么做,因为这部分涉及到一些系统知识,自己相关的经验不足,还没想好怎么下手。

0x02 功能和工作进度介绍

调试器-反汇编引擎

反汇编引擎的编写主要参考了intel手册 2517页以及后续页的One-byte Opcode Map、Two-byte Opcode Map、Three-byte Opcode Map。通过将这几张表的内容整理成一个静态的结构(详见DbgEngine目录下的Disasm_one.h Disasm_two.h Disasm_three_3a.hDisasm_three_38.h),在反汇编的时候通过检索相应的字节码按图索骥就可以了。

比如在处理0x01234567 的时候会先从Disasm_one.h中的 检索出 0x01 对应的处理函数,然后使用该处理函数处理后续的字节。多个字节的操作码也是一样比如 0x0f3812345678 ,会先从 Disasm_one.h 检索出 0x0f 的处理函数,该函数继续调用Disasm_two.h中的 0x38 对应处理函数,0x38处理函数继续调用Disasm_three_38.h 中的 0x12 处理函数来处理后续的字节。

在反汇编文件的时候,目前只做了一遍扫描。从程序入口点进行解析,碰到call,jmp 等跳转指令就会将相应的地址加入待解析记录中,遇到retn 结束当前函数的解析然后循环取下一个函数地址去解析。

目前完成了32位下的一部分X86指令,还没有做64位的区分处理。

调试器-汇编引擎

汇编引擎使用类似反汇编引擎中的表,不过汇编引擎的表是通过python脚本采集intel手册 第二卷 相关的指令介绍来整合起来的(详见DbgEngine下的asm_struct.h)。

汇编引擎在初始化的时候会按照之前采集表格中的助记符在内存中来建立一个前缀树索引表。在汇编的时候,根据助记符找到对应的指令详细记录(可能会有很多条),然后匹配每一条记录的操作数个数和操作数宽度,最后会将所有符合的汇编结果(结果可能有多条)返回给调用者。

界面库

DuiLib 的版本众多,我选用的版本来源于:

https://github.com/redrains/DuiLib_Redrain

这个版本的代码修复一些bug。

由于DuiLib的界面是基于 XML 配置的,所以通过修改XML就很容易修改程序的外观。而我在原来的基础上加上四条规则:

1、按钮的 name 属性为 command 的话,点击按钮就可以执行一个本地程序。

通过这条规则,你就可以方便建立自己的工具箱了,把自己的常用的工具都整合在一起,你甚至都不用切换程序就能打开了。

2、按钮的 name 属性为 sub_window 的话,用户可以打开一个基于XML 配置的自定义的窗口。

通过这条规则,你可以把调试时寄存器的显示和堆栈的显示内容放在一个窗口内;如果不喜欢,你也可以加入或者删除其它内容。总之,完全取决于你。

3、按钮的 name 属性为 function 的话,就可以执行一些程序内建的指令

初步的构思的是把 单步、步过、暂停、开始等一些可以控制调试器的行为称为内建指令。通过把按钮绑定这些指令,你就可以在任意窗口上进行控制了。

4、按钮的 name 属性为 py_console 的话,就可以启动一个python 控制台。

目前是通过调用 allocconsole 函数开启控制台的,着实难看。以后再想下怎么修改。

通过以上几条规则的配合,你就可以进行混搭,打造自己的“家庭影院”了。

至于前面说的可分离式界面,举个栗子:下图的反汇编列表是分别定义在两个不同的窗口,一个定义在MainWnd.xml内,另一个定义在DisasmWnd.xml内。除此之外,没有其他的代码会对他们进行分开描述。但是他们显示的内容都是一样的,操作也一样。你也可以像这样把反汇编列表放在其他窗口上,只需要修改对应的xml就行了。通过对不同可视化元素的组合,你就可以根据个人习惯打造自己的专属交互页面了。

动态脚本引擎

python是以静态库的方式编译进程序的。启动一个python控制台之后,就可以像官方控制台那样进行操作了,目前集成调试器的读取PE功能,汇编功能。第三库需要添加至 Lib 目录。暂时还不能执行单独的脚本文件。后续考虑把它扩展成类似的winDBG的控制台。

0x03 后记

项目开源地址:

https://github.com/a12098718/NiujiaoDebugger

调试器的名字为 牛角,我不喜欢那些自己都看不懂的E文名字,土一点挺好的。来源嘛,就是那句 钻牛角尖 的俗语,虽然原意有点贬义,但我觉得做技术的就是要碰到问题死钻下去,直至解决为止。

原文作者:蓝色橘子

原文链接:https://bbs.pediy.com/thread-248877.htm

转载请注明:转自看雪学院

更多阅读:

[原创]dex vmp虚拟化

[原创]看雪CTF.TSRC 2018 团队赛 第十四题

upx原理分析

使用模拟器对x64程序进行分析

加载内存对话框数据

上一篇 下一篇

猜你喜欢

热点阅读