本文转自: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的支持、添加服务、内核等监控接口,读者若需要可自行添加。