• 本文作者: sys_cc
  • |
  • 2015年11月24日
  • |
  • 原创工具
  • |

AlphaFuzzer内存fuzz框架即将发布

背景:

按照fuzz形式而言,传统的fuzzer工具分为二种,一种是文件格式的fuzz测试, 一种是网络协议的fuzz测试。Alphafuzzer已经同时支持了这2种形式的fuzz。但是在有些时候,传统的fuzz是应用效率并不是很高。比如:
当程序对输入次数有限制(比如输入错误3次程序就自动关闭)。我们无法对程序持续的进行fuzz测试的时候。
当程序运行需要解压,载入很多很庞大的库文件,我们无法高效的进行fuzz测试时候。
当程序(如网络协议)传输过程有数据加密,而我们并不知道加密方式。无法构造有效的数据包进行fuzz测试的时候。
当目标程序有非常多的函数,我们只关注某一个函数,而又不想在其他函数上浪费时间的时候。
当。。。。。。
越来越多的特殊情况,导致传统的fuzz测试无法有效进行,所以,alphafuzzer在1.5版本开始,增加了内存fuzz框架。

内存fuzz优点:

1 适用面广:无论是文件格式的fuzz还是网络协议的fuzz,最终都是在内存内处理,只要我们控制了内存,就可以控制所有。
2 方便快捷,容易深入:如今各种文件格式,网络协议越来越复杂,各种校验越来越多。传统的fuzz很多数据都没有通过校验,造成了资源和时间的浪费。内存fuzz测试可以躲避这些校验,直接深入系统函数的最内层进行fuzz。更精确,更深入,更快捷。
3 完美的控制程序:去fuzz自己喜欢的函数,放弃自己不感兴趣的函数,完美的控制程序。用自己写的内存控制代码,做自己要做的事情。

内存fuzz缺点:

对使用者要求较高:想使用内存fuzz,必须对调试器,软件逆向等有一定的了解,因此门槛较高,对使用者有一定的要求。
对CPU要求较高:跟踪测试时候需要较高的cpu资源,因此使用者应该有一个强大的CPU。

界面介绍:

内存fuzz模块仍在持续开发中, 预计在12月底发布测试版,2月初发布稳定版。如图所示,
用户需要输入的有如下5个。分别为:
畸形数据构造模块:该模块位于左上角的编辑框中,用户用alpha语言输入构造畸形数据的构造模块,程序对alpha代码进行解析与变异,最终生成畸形的数据,供后面的fuzz使用。
内存fuzz控制指令模块:用于编写控制内存操作的模块,具体参考手册将于程序共同发布。
command指令模块:具体参考手册将于程序共同发布。
程序:选择要测试的程序。
样本:选择要fuzz的样本。程序在该样本基础上进行变异,生成变异数据。
程序输出的窗口同样也是5个。分别为:
Cpu寄存器信息输出窗口。
执行状态输出窗口(最右面)
LOG日志输出窗口(左下角)
内存信息输出窗口(中下)
调试状态窗口(右下角)

1

图片1


对使用者的要求:

内存fuzz框架具有强大的软件调试功能。只有准确的使用内存控制指令才能高效的对程序进行内存fuzz。因此该框架的使用人员应该对软件调试以及逆向分析具有一定的基础方可。

测试例子:用内存fuzz模块来破解小程序

测试用例介绍:

我们编写一个小例子    ,来演示内存fuzz测试。
例子代码:

#include “stdafx.h”
int sn=0;
int cal(int k);
int _tmain(int argc, _TCHAR* argv[])
{
printf(“AlphaFuzzer内存fuzz演示例子\r\n”);
printf(“请输入密码:”);
scanf(“%d”,&sn);
printf(“您输入的密码是%d,\r\n”,sn);
if(cal(sn)==1) printf(“恭喜,密码正确\r\n”);
else printf(“密码错误,程序退出\r\n”);
return 0;
}
int cal(int k)
{
if(k==58) return 1;
else return 0;
}

例1简要说明:程序打开后,需要用户输入密码。该密码为2位数字。输入结束后,程序显示密码成功或者失败,然后退出。
Cal()函数为密码的计算过程,可以视为本地计算过程,也可以视为远程计算过程。为了简单明了,这里直接和58做对比返回。
正常文件fuzz情况下,程序运行一次就退出,无法持续fuzz。如下图2:
2
图片2
这个程序的反汇编代码如下(附加简单分析图3):
3
图片3

解决方案

Alpha代码构造指令
_RangeNum,0,100,0,32;
该指令目的是生成一个0-100的随机数。

内存控制指令
GetRegs,,eip,==,00401032;
SetFixedMemOfAlpha,00403370,eip,==,00401078,4;
SetRegs,,eip,==,0040107A;
MemShow,00403370;
Stop,eip,00401065,==,1;

第一条指令[GetRegs,,eip,==,00401032;]目的是当eip==00401032时,保存所有寄存器的值,配合第三条指令[SetRegs,,eip,==,0040107A;]一起使用。第三条指令的目的是当EIP==0040107A时候,恢复所有寄存器的值。这时候寄存器的值恢复至00401032.这样就可以保证程序能在00401032-0040107A处不间断循环。第二条指令[SetFixedMemOfAlpha,00403370,eip,==,00401078,4;]的目的是内存fuzz,当EIP==00401078的时候,对内存进行fuzz。具体fuzz过程是将alpha生成的畸形数据填充至内存00403370处。大小限制不超过4字节。第四条指令[MemShow,00403370;]是显示00403370处的数据,方便用户知道测试时的实时信息。第五条指令[Stop,eip,00401065,==,1;]的意思是当eip值第一次等于00401065的时候,程序暂停。(00401065就是说明用户输入的密码正确)。

开始测试

我们需要做的是
1 填写内存控制代码(右上方的编辑框)
2 填写alpha数据生成代码(左上方的编辑框)
3 填写command代码(中间的编辑框)

4
图片4

点击开始测试:
此时弹出来控制台的窗口,但是并没有其他信息。
输入控制指令trace,点击执行指令。
5
图片5

过几秒钟后,程序执行了。
这时候我们随便输入一个密码,比如12.然后程序fuzzing起来了。
6
图片6

 

一段时间以后,程序停止。我们fuzz到了正确密码,是58.
7
图片7

这只是一个最简单的例子,内存fuzz用到的地方有很多,等待大家去学习挖掘。

 

 

Written by sys_cc