mpg321 堆溢出分析过程

1 前言

在使用Vuzzer重现其论文中的实验时,对mpg321的fuzzing发现三个crash,其中一个为segementation fault.下文为对这个segmentation fault的分析过程。

2 环境准备

mpg321编译:

mpg321_0.3.2.orig.tar.gz (-g -O0编译)

依赖库编译安装:

  • libao-1.2.0(-g -O0编译)
  • libmad-0.15.1b(-g -O0编译)
  • libid3tag-0.15.1b (-g -O0编译)
  • libasound2-dev (apt-get install)

ubuntu 14.04 X64

3 调试过程

A coredump调试

首先配置core dump 记录 crash的 coredump 信息。

$: ulimit -c unlimited (不限制core文件大小)

使用crash input重新运行程序,得到coredump 信息:

使用gdb调试 coredump,得到崩溃时的调用栈:

从崩溃的调用栈处,看到的信息是调用calloc分配84字节内存的时候导致了segmentataion fault。从调用栈追踪,看不出什么问题。

在网上搜索了关于calloc导致segmentaion fault,大部分都是由于在程序的其他地方堆被破坏,然后在后续分配内存的时候导致出错。推荐的heap check 工具为 gperftools http://https://github.com/gperftools/gperftools

gperftools配置安装后使用没有什么发现(安装使用可能还有问题,没有继续研究),改用 LLVM的 AddressSanitizer(安装LLVM...)

LLVM 的安装源:http://apt.llvm.org/

B 堆溢出调试

在使用LLVM ASAN编译mpg321时,发现了一件奇怪的事情,使用-O0 -O1优化,clang都无法识别libmad库中的一个函数,而使用-O2却可以。。。

编译好之后,运行crash input结果如下:

这里显示的结果是:

在 0x530602处 向内存 0x602...398 开始处写入8字节

但是 0x602....398处于分配的内存区域[...390 ,...398)偏移0个字节的地方

意思就是分配了8字节的内存,但是在写的时候,写到第9字节去了。

这个输出并不是很友好,看不出在哪里分配,哪里写入的,继续查看AddressSanitizer的使用说明,发现通过导出 ASAN_SYMBOLIZER_PATH环境变量后,可以看到更具体的符号信息。

导出环境变量后得到的结果如下:

这样我们得到分配内存的代码和写入内存代码的位置:

分配内存:

写入内存:

通过查看源码上下文,猜测在分配时,分配了8个字节的内存,在使用时,访问到第九个字节。

使用gdb调试下断点,在mad.c:289行处,变量current_frame为1,而playbuf->frames存储的元素为指针,在X64系统中,指针大小为8字节,current_frame为1,访问到的是第二个指针,即playbuf->frames开始处第九个字节。如果分配了8字节内存,这里的访问就越界了。

再使用gdb调试,在分配内存处下断点,得到malloc的参数为8,即分配了8字节内存。验证了上面的猜想。

从源码看,如果这里分配了8字节内存,那是不是playbuf.num_frames值为0,然后malloc((playbuf.num_frames + 1) * sizeof(void*))分配8字节内存? 但是 在写入内存时,判断了 current_frame

继续调试,看看playbuf.num_frames值到底是是什么。

这里,使用gdb 指令单步模式,并打开汇编代码显示:

发现 playbuf.num_frames 的值为0x8000000000000000

lea 0x8(,%rax,8) %rdi 这里 %rax即为 playbuf.num_frames

也就是(playbuf.num_frames + 1)*8 在汇编层面,是(playbuf.num_frames*8 + 8) 而playbuf.num_frames为 unsigned long 类型,playbuf.num_frames*8 之后溢出为0,最后导致malloc分配了8字节内存。

但是在写入内存处,current_frame也是 unsigned long类型,current_frame

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值