测试应用 wget
版本号 1.19.1
fuzz工具 afl
调试工具 gdb
交互功能实现 preeny

wget编译安装

首先wget下载源码,并使用afl-clang-fast进行安装

wget https://ftp.gnu.org/gnu/wget/wget-1.19.1.tar.gz
tar zxvf wget-1.19.1.tar.gz
cd wget-1.19.1
CXX=afl-clang-fast++ CC=afl-clang-fast ./configure --prefix=/home/mortywget
AFL_USE_ASAN=1 make
make install

验证

root@c7c87f16a29d:/home/mortywget/bin# ./wget --version
GNU Wget 1.19.1 built on linux-gnu.

preeny

Preeny项目重写了一些交互的函数,我们可以通过LD_PRELOAD预加载机制,对程序中的交互进行修改,例如将socket相关函数改写为从用户输入输出(stdin,stdout)进行交互,从而方便我们使用afl进行fuzz

项目下载地址

https://github.com/zardus/preeny

此处省略安装过程…

验证preeny是否安装成功

预加载desock.so文件,并启动一个socket交互程序wget,若输入的字符串成功当作wget请求的返回值 ,则表明preeny安装配置成功

root@c7c87f16a29d:~# LD_PRELOAD="/root/preeny/x86_64-linux-gnu/desock.so" wget localhost:6666 -q -O result < <(echo "success");
GET / HTTP/1.1
User-Agent: Wget/1.17.1 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: localhost:6666
Connection: Keep-Alive

root@c7c87f16a29d:~# more result 
success

我们看到result文件中包含了"success"字符串,说明preeny已经将我们的输入转化成了http response返回结果,说明我们preeny安装配置无误

开始fuzz

本次我们测试wget对于状态码为4xx的接收情况
首先创建我们的payload

HTTP/1.1 401 Not Authorized
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive

test

运行fuzz

由于此时wget程序接收到response包后并未及时断开,我们的fuzz过程会非常的慢,甚至出现无法fuzz的情况,运行如下命令可看到wget接收到response包后并未及时断开

root@c7c87f16a29d:/home/mortywget/bin# nc -lp 6666 < in/a & ./wget localhost:6666 -F -O /dev/null
[1] 7672
--2020-04-20 07:31:52--  http://localhost:6666/
Resolving localhost... 127.0.0.1, ::1
Connecting to localhost|127.0.0.1|:6666... connected.
HTTP request sent, awaiting response... GET / HTTP/1.1
User-Agent: Wget/1.19.1 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: localhost:6666
Connection: Keep-Alive

401 Not Authorized

对于这种情况,我们可以使用如下命令架起nc,让其返回特定的response包

nc -lp 6666 < out/hangs/id\:000000\,src\:000000\,op\:flip1\,pos\:4

然后通过gdb调试找到程序卡住的位置

gdb-peda$ bt
#0  0x00007ffff65d25b3 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:84
#1  0x00000000004c2450 in select_fd (fd=<optimized out>, maxtime=<optimized out>, wait_for=<optimized out>) at connect.c:714
#2  0x00000000004c34b2 in sock_poll (fd=0x4, timeout=<optimized out>, wait_for=0x1) at connect.c:801
#3  poll_internal (fd=<optimized out>, info=0x0, wf=0x1, timeout=<optimized out>) at connect.c:914
#4  fd_read (fd=0x4, buf=0x7fffffffcd00 "gfedcbazzzzffffgggghhhhiiiiddddeeeeffffccccccccbbbbbbb", 'a' <repeats 29 times>, "bbb", 'a' <repeats 58 times>, 'A' <repeats 56 times>..., 
    bufsize=0xff, timeout=<optimized out>) at connect.c:933
#5  0x000000000052723c in skip_short_body (fd=<optimized out>, contlen=<optimized out>, chunked=<optimized out>) at http.c:989
#6  0x0000000000519a95 in gethttp (u=<optimized out>, original_url=<optimized out>, hs=<optimized out>, dt=<optimized out>, proxy=<optimized out>, iri=<optimized out>, 
    count=<optimized out>) at http.c:3524
#7  0x0000000000512aa7 in http_loop (u=<optimized out>, original_url=<optimized out>, newloc=0x7fffffffe310, local_file=<optimized out>, referer=<optimized out>, dt=<optimized out>, 
    proxy=<optimized out>, iri=<optimized out>) at http.c:4193
#8  0x00000000005556aa in retrieve_url (orig_parsed=<optimized out>, origurl=0x60300000e080 "http://localhost:6666", file=<optimized out>, newloc=<optimized out>, refurl=<optimized out>, 
    dt=<optimized out>, recursive=<optimized out>, iri=<optimized out>, register_status=<optimized out>) at retr.c:817
#9  0x000000000053c77b in main (argc=<optimized out>, argv=0x7fffffffe3f0, argv@entry=0x7fffffffe738) at main.c:2081
#10 0x00007ffff64f5830 in __libc_start_main (main=0x538f70 <main>, argc=0x2, argv=0x7fffffffe738, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, 
    stack_end=0x7fffffffe728) at ../csu/libc-start.c:291
#11 0x00000000004bf659 in _start ()

在确定卡住位置之后,修改其源码,使其强制断开连接,退出程序

http.c的如下位置中分别添加exit(0):
```

点击收藏 | 2 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖