打造简单的调试器

Posted 千羽;

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了打造简单的调试器相关的知识,希望对你有一定的参考价值。

本文转自:http://www.freebuf.com/sectool/92279.html

0×1 概述

在Fuzzing过程中,必须要监控程序的执行状态,若程序发生异常,立即保存测试用例,以便将来对其进行重现。监控器的作用就是监控程序的执行,如果程序有异常时通知给Fuzzing主线程。

目前Fuzzing工具各种各样,监控器也有很多种,但大多都是以调试器的方式实现。一个简单的监控器是这样实现的:

(一)以调试模式启动进程,为目标进程开启调试端口,可使用参数DEBUG_ONLY_THIS_PROCESS,意为只调试本进程,更多说明请参照MSDN。

技术分享图片

(二)等待调试事件,当进程内部发生调试事件时,通过调试端口向调试器发送事件。调试事件不仅仅指异常事件,创建进程、线程、加载库这些都是调试事件,异常事件是EXCEPTION_DEBUG_EVENT。

技术分享图片

(三)处理调试事件,对应不同的调试事件,可作不同处理,若不感兴趣,可通过ContinueDebugEvent来忽略。调试器可对目标进程的操作具有较高的权限,可自由读取、修改目标进程的寄存器、内存信息,我们所使用最多的调试器,像Windbg、VCDebugger、OllyDbg等,也是从这些简单的函数实现而成的。

技术分享图片

一个简单的HelloWorld例子位于codeproject,对这方面不太了解的朋友可以下载看看。

0×2 不同的调试器接口

当然,在实际工程中,我们没必要都从hello world开始写起,有很多的调试器接口已经被完善,方便我们直接调用,接下来随便举几个常见调试器的例子。

(1)ImmLib

一个集成在Immunity Debugger的Python库,但仅能在Immunity Debugger中调用。若写Immunity Debugger的插件时,将是不错的选择。

(2)vtrace

Vtrace是一款支持不同平台的调试器,同样也是使用Python编写而成。

(3)OllyPython

OllyPython使用Python编写而成,是OllyDbg的插件,也仅能在OD内使用。

(4)PyDbg

大家对PyDbg应该都很熟悉,在python灰帽子里有大幅的介绍与应用,但仅能用兼容Python2.4和2.5。

(5)PyDbgEng

PyDbgEng与Windbg集成实现而成,且支持强大的内核调试功能。

(6)WinAppDbg

功能比较强大的调试器,与PydbgEng相似,但采用纯原生Win32 API实现而成,不依赖于任何调试器。

(7)PyDbgExt

与PyDbgEng相反,PyDbgEng是通过Python实例化调试器引擎,而它是在调试器中添加Python解释器,在Windbg中使用。

(8)pygdb

Pygdb是一个简单的GNU调试器的封装,提供GTK的接口,可在Linux与OSX下运行。

(9)PyKd

PyKd有点像将PyDbgEng与PyDbgExt混合到一起,可在调试器中调用,也可独立使用,有较大潜力的调试器。

(10)PyMem

PyMem是使用Python编写的Windows上的一个内存插装库。

(11)python-ptrace

python-ptrace调用ptrace实现而成,仅能在POSIX系统上运行,如BSD、Linux。

(12)PythonGdb

PythonGdb 是一个嵌入到GDB中的一个Python解释器。

(13)Radare

Radare是一个控制台程序,支持多平台的反汇编、调试框架。

(14)Universal Hooker (uhooker)

Uhooker实现了函数Hook的Python库,但较长时间未更新。

0×3、实现自己的调试监控器

介绍了这么多的调试器接口,有轻量级的、有支持内核调试的、有支持Linux的、有内嵌到调试器中的,总有一款适合你的实际需要。使用它们也非常简单,只需要基本的编程知识即可。一般实现过程都是实例化一个调试器,然后启动目标进程,并开启事件来监听,如果发生异常,事件被激活,处理调试事件即可。

给我印象比较深刻的是Peach的监控器,它通过Pit的配置后,启动一个本地或远程的Agent的,然后由Agent来监控目标进程的异常情况。当发生异常后,除了保存样本操作外,还会生成StackTrace,记录寄存器、调用栈,调用MSEC生成可利用性的报告,并根据exploitable提供的信息命名、分类、去重。基本上对后期分析有点价值的信息都被记录了,是一种比较好的方案。理所当然,重用它的代码就行。

Peach的结构很简单,通过Peach.py调用engine.run,在run中进行一系列初始化后,调用_runTest开始测试。创建了一个agent的实例用来监控目标程序,创建了一个watcher的实例用来记录异常信息。

Debugger.py中包含了两个调试器接口类,一个是WindowsDebugEngine,用来与Windbg交互,支持Windows操作系统,另一个是UnixDebugger,使用Vtrace实现而成,支持POSIX系统。POSIX系统暂时不感兴趣,把这部分代码先删除掉。

WindowsDebugEngine的构造函数中,首先对从pit文件中传进来的参数进行解析,这部分代码也不需要,删除修改。然后调用_StartDebugger来启动调试器,开启WindowsDebugEngineProcess_run的线程,调用PyDbgEng.ProcessCreator或PyDbgEng.ProcessAttacher来启动或附着到目标进程上,并注册调试事件处理器_DbgEventHandler,当异常事件发生后,在_DbgEventHandler中输出寄存器、调用栈、exploitable信息。

对这个流程理解后,修改它就只是简单的工程了,添加了一个新类DebuggerMonitor作为代理,来处理用户的参数与DebugEngine之间的交互。

使用起来很简单,这是一个简单例子:

技术分享图片

运行结果如下,看到了很舒服的命名方式:

技术分享图片

技术分享图片

StackTrace中保存的内容如下:

技术分享图片

技术分享图片

DebuggerMonitor类的构造函数接受两个参数,分别是启动程序的命令行,及保存异常信息的目录。通过调用getLogDir来得到当前异常信息保存的目录,方便用户保存测试用例。

在使用前需要四个依赖模块,分别是psutils、comtypes、pywin32、pydbgengine。

下一步工作:还需要添加PageHeap的支持、添加服务、内核等监控接口,读者若需要可自行添加。

以上是关于打造简单的调试器的主要内容,如果未能解决你的问题,请参考以下文章

cpp学习使用VS进行简单调试

网易视频云技术分享:UML调试Linux内核

ROS小车打造--Jetson TX2安装与调试

工具 | 字节跳动开源的 Flutter 应用内调试工具

用Tkinter打造自己的Python IDE开发工具建立一个简单的代码编辑器

用Tkinter打造自己的Python IDE开发工具建立一个简单的代码编辑器