AFL重现Crash
如果使用过afl会发现在output中存在Crashes文件夹,里面是许多类似于id:00000:xxxxxxx命名的文件,这些文件就是使得afl发生崩溃的用例,重新运行这些crash文件即可看到fuzz过程中出现的报错和调用信息,从而确定跑出来的crash究竟是不是我们想要的报错点,还是一些其他的报错甚至是新的未发现的crash,这里需要使用到ASAN。获取当前线程的函数调用栈信息,当前线程中函
1
如果使用过afl会发现在output中存在Crashes文件夹,里面是许多类似于id:00000:xxxxxxx命名的文件,这些文件就是使得afl发生崩溃的用例,重新运行这些crash文件即可看到fuzz过程中出现的报错和调用信息,从而确定跑出来的crash究竟是不是我们想要的报错点,还是一些其他的报错甚至是新的未发现的crash,这里需要使用到ASAN。
2
具体如何重现Crash呢,首先重现crash使用的可执行文件不是之前进行fuzz时使用的可执行文件,因为之前在对程序编译时使用的语句可能如下:
CFLAGS="" CXXFLAGS="" ../configure --disable-shared --prefix=`pwd`
这一次的编译过程需要使用到
-fsanitize=address
可以考虑用-fsanitize=address选项编译和链接
用-fno-omit-frame-pointer编译,以在错误消息中添加堆栈跟踪
用-O1获得更好的性能
以及如果只需要检测内存泄漏,只需要-fsanitize=leak,而不需要-fsanitize=address,若对内存泄露不感兴趣需要使用export ASAN_OPTIONS=detect_leaks=0 来将其禁用
ASAN全称Address Sanitizer,集成到gcc,为一个内存检测工具,我们用它来显示程序遇到的异常状况。重新编译生成可执行文件后,我们就可以使用它运行之前获得的crash
./ASANbin crashes/id:000001:xxxxxxxx
如果报错可能是运行程序缺少动态链接库,直接运行程序./ASANbin看看输出中有没有提示缺少文件,比如
error while loading shared libraries:libpng16.so.16:cannot open shared object file:No such file or directory
此时使用ldd ASANbin查看可执行文件需要的库
可见没有这个库,这时可以使用ldconfig -p | grep libpng
查看libpng有无,可以看到
也就是说存在libpng12.so但是没有16,使用apt-get install libpng16-dev
下载
之后如果ASANbin运行没有问题了
即可继续使用./ASANbin crashes/id:000001:xxxxxxxx
运行crash
此时会显示类似于下图的输出
但是我们期望看到的应该是某个文件的某一行出错,而不是0x4d194a这种,这是为什么呢
这里尝试使用gdb查看调用栈信息
gdb -q ASANbin
然后
(gdb) run < /id:000000:xxxxx
此时显示如下图
要想使用gdb调试功能,需要在gcc编译时添加-g
参数,对于几个gdb命令简要介绍下:
1、gdb -q +${exe} :对可执行文件调试,不打印gdb版本信息
2、break或b :对函数或代码行打断点,使用info breakpoints查看当前所有的断点
3、run或r:运行程序,运行到第一个断点
4、continue或c:继续运行程序到下一个断点
5、next或n:单步跳过,执行一步程序,若遇到函数直接完成函数而不会进入函数
6、step或s:单步进入,执行一步,若遇到函数会进入函数
7、quit或q:退出gdb
8、bt(backtrace)
获取当前线程的函数调用栈信息,当前线程中函数调用的序列,从当前位置回溯到程序的入口,查看程序执行的路径。
9、info stack
info stack 显示当前线程比 bt 更详细的调用栈信息,包括局部变量和寄存器值。
设置断点或者直接运行程序,当程序暂停时,可以使用 bt来查看栈信息,但是在我们这次尝试中失败了,我们并不能看到行号。
查看HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)
,我们得知LeakSanitizer 在内部使用 ptrace,可能会挂起所有线程,以扫描泄漏而不会出现误报,如果在 gdb 或 strace 下运行应用程序,则 LeakSanitizer 将无法通过 ptrace 附加。
可见LeakSanitizer无法和gdb一起工作,在gdb下使用时需要通过设置ASAN_OPTIONS=detect_leaks=0来将其禁用。
这里可能的一个解决方案是使用sudo,由于在服务器上没有sudo权限,这里使用docker进行尝试,注意docker run 命令还要增加–privileged,否则 LeakSanitizer 仍然会报错,其他步骤都相同,最后可以看到现在的报错:
终于能看到行号,从而判断当前crash是不是我们期望的发生崩溃的例子。
Jarvis 24.3.17
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)