【文章作者】: condor
【作者邮箱】: cracker@vip.qq.com
【作者主页】: http://hi.baidu.com/linshifei
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
第一篇,顺便做下科普, Fuzz 由来(忘了哪里看到了): 在1980到1990之间,三个研究者—Barton Miller,Lars Fredriksen和Bryan So—致力于研究UNIX命令行程序的完整性。
在一个暴风雨过后的夜晚,其中的一位研究者通过拔号线路连到远程服务器,在准备运行某个Unix程序时,由于线路噪音,一些随机数据代替了他的输入被发送到Unix程序里,在程序执行时,因为这些随机数据的存在,导致程序产生core dump。根据这个发现,三位研究者开发了FUZZ系统,用于生成伪随机输入数据来测试程序的完整性。现在,Fuzz已成为测试软件安全漏洞的一个重要部分。
SPIKE是一套C函数接口的API(Primitives ),注意没有windows版本,构造的基本语法:
静态内容:s_string() s_binary(),s_intelword(),s_string_repeat()
动态内容:s_string_variable(),
网络控制:spike_send_udp() spike_listen_udp() spike_send_tcp()
Block控制:s_binary_block_size_intel_word () s_block_end ()
变量控制:s_incrementfuzzstring () s_incrementfuzzvariable ()
接下来主要是一点读书笔记,
安装:
tar zfv SPIKE2.9.tar
先运行aclocal
然后运行 automake && autoheader && autoconf && ./configure
make
然后就生成很现成了(去掉。c以后):
root@condor:/usr/local/apple/SPIKE/SPIKE/src# ls *.c -l|grep fuzz
-rwxrwxr-x 1 500 500 12705 Apr 13 2004 closed_source_web_server_fuzz.c
-rwxrwxr-x 1 500 500 3664 Jan 15 2004 form_fuzz.c
-rwxrwxr-x 1 500 500 5953 Jan 15 2004 generic_web_server_fuzz.c
-rwxrwxr-x 1 500 500 6388 Jan 15 2004 generic_web_server_fuzz2.c
-rwxrwxr-x 1 500 500 12408 Jan 15 2004 msrpcfuzz.c
-rwxrwxr-x 1 500 500 12760 Jan 15 2004 msrpcfuzz_udp.c
-rwxrwxr-x 1 500 500 4242 Jan 15 2004 oldmsrpcfuzz.c
-rwxrwxr-x 1 500 500 7461 Jan 15 2004 post_fuzz.c
-rwxrwxr-x 1 500 500 8490 Jan 15 2004 sunrpcfuzz.c
-rwxrwxr-x 1 500 500 25 Jan 15 2004 webfuzz.c
-rwxrwxr-x 1 500 500 25 Jan 15 2004 webfuzz_blank.c
-rwxrwxr-x 1 500 500 1190 Jan 15 2004 webfuzzpostlude.c
-rwxrwxr-x 1 500 500 1290 Jan 15 2004 webfuzzprelude.c
好东西在 audits目录下:
root@condor:/usr/local/apple/SPIKE/SPIKE/src/audits# ls -l
total 68
drwxrwxr-x 2 500 500 4096 Apr 14 2004 BIZTALK2000
drwxrwxr-x 2 500 500 4096 Apr 14 2004 CIFS
drwxrwxr-x 2 500 500 4096 Apr 14 2004 COMPAQ
drwxrwxr-x 2 500 500 4096 Apr 14 2004 FTPD
drwxrwxr-x 2 500 500 4096 Apr 14 2004 H323
drwxrwxr-x 2 500 500 4096 Apr 14 2004 IMAP
drwxrwxr-x 2 500 500 4096 Apr 14 2004 MSContentManagementServer
drwxrwxr-x 3 500 500 4096 Apr 14 2004 MSSQL
drwxrwxr-x 2 500 500 4096 Apr 14 2004 ORACLE
drwxrwxr-x 2 500 500 4096 Apr 14 2004 POP3
drwxrwxr-x 2 500 500 4096 Apr 14 2004 PPTP
drwxrwxr-x 2 500 500 4096 Apr 14 2004 RealServer
drwxrwxr-x 2 500 500 4096 Nov 9 08:07 SMTP
drwxrwxr-x 2 500 500 4096 Apr 14 2004 SSL
drwxrwxr-x 2 500 500 4096 Apr 14 2004 UPNP
drwxrwxr-x 2 500 500 4096 Apr 14 2004 exchange2K
drwxrwxr-x 2 500 500 4096 Apr 14 2004 lotus
来看一个 ,都是脚本,。spk是脚本,脚本和上面的c程序是等价 效果的。
root@condor:/usr/local/apple/SPIKE/SPIKE/src/audits/SMTP# vim smtp3.spk
s_string_variable("HELO");
s_string(" ");
s_string_variable("localhost");
s_string("\r\n");
s_string("MAIL-FROM: <");
s_string_variable("");
s_string(">");
s_string("\r\n");
s_string("RCPT-TO: postmaster@company.mail");
s_string("DATA\r\n");
s_string("Message-ID: 123\r\n");
s_string("ASDF\r\n");
s_string("ASDF\r\n");
s_string(".\r\n");
s_string("QUIT\r\n");
里面有基于 GTk+ wxPython 图像界面 python程序 SPIKE_Console.py
没有环境跑不起来
来看个例子 一般fuzz调用流程 ,快速入门:
main (int argc, char ** argv)
{
signal (SIGPIPE, SIG_IGN); /*ignore when the server closes the connection on us */
our_spike = new_spike (); /*一个新的spike指针 */
s_init_fuzzing (); /*do some basic initialization in spike.c */
setspike (our_spike); /*设置当前指针. 接下来调用的其他函数s_string(), s_binary()等将作用在这个指针上. 可以有多个 spike指针,调用setspike() 切换 */
s_resetfuzzvariable (); /*清 fuzz变量为 0 ,s_string_variable() 调用将加1*/
while (!s_didlastvariable ()) /*did last variable 直到最后一个 fuzz变量 */
{
s_resetfuzzstring (); /*重置 fuzz使用的stirng ,一般是大量的 'A' */
/* 是否是最后一个fuzzstrings*/
while (!s_didlastfuzzstring ())
{
/* 清空spike的内部状态 */
spike_clear ();
/*设置第一个 变量 ,有时候为‘?’*/
s_setfirstvariable ();
/*PAYLOAD*/
push_your_HTTP_request_here(); /*通过调用s_push_variables('&',whateverstringyouwant)等添加你的实际包内容*/ if (spike_send_tcp (target, port) == 0)
{
printf ("Couldn't connect to host or send data!\r\n");
/*exit(-1); */
}
/*fuzzstring = fuzzstring + 1 - we advance to the next string
使用fuzzstring 填充当前fuzz变量*/
s_incrementfuzzstring ();
/*some loop control variables*/
notfin = 1;
retval = 1;
/*this next bit just reads back what the server sends to us - but
if it takes too long, we just disconnect*/
while (retval && notfin)
{
memset (buffer, 0x00, sizeof (buffer));
/*s_fd_wait() is a select() call basically. It returns 0 if it's time
to close the connection*/
notfin = s_fd_wait ();
if (!notfin)
{
printf ("Server didn't answer in time limit\n");
break;
}
retval = read (our_spike->fd, buffer, 2500);
printf ("**%.2500s**\n", buffer);
}
/*send fins!*/
spike_close_tcp ();
} /*end for each fuzz string */
/*next variable*/
s_incrementfuzzvariable ();
} /*end for each variable */
} 一些函数技巧
spike_send_tcp() 我的理解是长连接 ,需要 spike_close_tcp()来断开
spike_send() 短链接,
可以直接使用抓包数据
spike_clear(); /*nice clean spike*/
s_binary("使用sniffer工具抓到包直接贴在这里>");
s_send();
构造重复数据:
s_string_repeat("A",5000) - just like perl -e 'print "A" x 5000' 构造post数据方法,以下是等价的:
s_string_variables('&',"username=bob&password=feet");
s_string_variable("bob"); s_string("&password="); s_string_varialbe("feet");
其他学习建议 就是跑一跑例子,抓包看看 变化规律,就会明白 fuzz的过程。 一个完整例子,结束下block 这个重要的概念 ,基于上面的流程框架 ,测试http post 。
/*just a quicky demonstration of using SPIKE to send a POST command
to a web server*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /*for memset*/
#include <sys/types.h>
#include <sys/socket.h> #include "spike.h"
#include "hdebug.h"
#include "tcpstuff.h" void
usage()
{
fprintf(stderr,"Usage: ./post_spike target port\r\n");
exit(-1);
} int
main (int argc, char ** argv)
{
char * target;
char buffer[1500000];
char *url,*host;
int port;
struct spike * our_spike;
unsigned long retval;
int i;
if (argc!=3)
{
usage();
}
target=argv[1];
printf("Target is %s\r\n",argv[1]);
port=atoi(argv[2]);
our_spike=new_spike(); if (our_spike==NULL)
{
fprintf(stderr,"Malloc failed trying to allocate a spike.\r\n");
exit(-1);
}
setspike(our_spike);
memset(buffer,0x41,sizeof(buffer));
buffer[sizeof(buffer)]=0; for (i=0; i<500; i+=4)
{
memcpy(buffer+i,"%25s",4);
}
/*
Allow: OPTIONS, TRACE, GET, HEAD, DELETE, PUT, COPY, MOVE, PROPFIND, PROPPATCH, SEARCH, SUBSCRIBE, UNSUBSCRIBE, POLL, BDELETE, BCOPY, BMOVE, BPROPPATCH, BPROPFIND, LOCK, UNLOCK
*/
buffer[140000]=0;
printf("Buffer size = %d\r\n",strlen(buffer));
host=strdup("10.3.8.25");
url=strdup("/exchange/bob/Drafts/No%20Subject-4.EML/?Cmd=addattach&Embedded=0");
/*takes a url, host, and posts it*/
s_string("POST ");
s_string(url);
// s_string_repeat("%n",15000);
s_string(" HTTP/1.1\r\n");
s_string("Host: ");
s_string(host);
s_string("\r\n");
s_string("Authorization: Basic Ym9iOmJvYg==\r\n");
//s_string("Cookie: sessionid=b1c4d131-9439-4a7b-894f-7185ca8c6695,0x9\n");
s_string("Cookie: sessionid=03570e97-62ab-4372-bd98-f7faac2e2619,0x409; sessionid=374642e5-8427-4be5-9bb2-1d90c01ed28c,0x409; ASPSESSIONIDQQGQQNOC=");
s_string("OIJHFNJBFLCAAPHINMAJGHJM\r\n");
s_string("Referer: http://10.3.8.25/exchange/bob/Drafts/No%20Subject-4.EML?Cmd=editattach\r\n");
s_string("Connection: Keep-Alive\r\n");
s_string("User-Agent: Mozilla/4.76 [en] (X11; U; Linux 2.4.2-2 i686)\r\n");
s_string("Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\n");
s_string("Accept-Encoding: gzip\r\n");
s_string("Accept-Language: en\r\n");
s_string("Accept-Charset: iso-8859-1,*,utf-8\r\n");
s_string("Content-type: multipart");
s_string("/form-data; ");
s_string("boundary=");
s_string("---------------------------42423833519577477931714636915");
s_string("\r\n");
s_string("Content-length: ");
//这个位置是个 字符 表示 post block 段的大小
s_blocksize_string("post",7);
s_string("\r\n\r\n");
//post 端定义开始
s_block_start("post");
/*start post here*/
s_string("-----------------------------42423833519577477931714636915");
s_string("\r\n");
s_string("Content-Disposition: ");
s_string("form-data; name=\"attachFile");
s_string("\"; filename=\"/tmp/asdf");
s_string("\"\r\n");
s_string("Content-Type: ");
s_string("application/octet-stream\r\n");
s_string("Content-Transfer-Encoding: ");
s_string("binary\r\n");
s_string("-----------------------------42423833519577477931714636915--\r\n");
/*结束 POST*/
s_block_end("post");
/*
s_print_buffer();
s_printf_buffer();
*/
printf("Sending to %s on port %d\r\n",target,port);
if (spike_send_tcp(target,port)<0)
{
printf("Couldn't connect to host or send data!\r\n");
exit(-1);
} printf("reading\r\n");
memset(buffer,0x00,sizeof(buffer));
retval=1;
while (retval!=-1)
{
s_fd_wait();
retval=read(our_spike->fd,buffer,1500);
printf("%s",buffer);
}
return 0;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!