初探AFL-Fuzz
字数 1150 2025-08-05 19:10:02
AFL-Fuzz 模糊测试工具详解
AFL-Fuzz 介绍
AFL (American Fuzzy Lop) 是由 Google 安全工程师 Michał Zalewski 开发的一款开源模糊测试工具,主要用于挖掘内存安全漏洞,如:
- 栈溢出
- 堆溢出
- UAF (Use After Free)
- double free 等
Fuzzing 概念
Fuzzing 是通过构造测试输入对软件进行大量测试来发现软件漏洞的模糊测试方法。在现实漏洞挖掘中,因其简单高效的特点成为主流方法。
AFL 工作原理
- 编译时插桩:通过对源码重新编译时进行插桩的方式自动产生测试用例
- 执行路径探索:探索二进制程序内部新的执行路径
- 支持闭源程序:配合 QEMU 可对闭源二进制代码进行测试(效率较低)
安装 AFL
- 从官网下载压缩包
- 解压后在目录中执行:
make
sudo make install
- 验证安装:终端输入
afl-后按 Tab 键,应显示一系列 AFL 命令
有源码程序的 Fuzzing 测试
示例测试程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
int vuln(char *str) {
int len = strlen(str);
if(str[0] == 'A' && len == 66) {
raise(SIGSEGV); // 首字符为A且长度为66则异常退出
}
else if(str[0] == 'F' && len == 6) {
raise(SIGSEGV); // 首字符为F且长度为6则异常退出
}
else {
printf("it is good!\n");
}
return 0;
}
int main(int argc, char *argv[]) {
char buf[100]={0};
gets(buf); // 栈溢出漏洞
printf(buf); // 格式化字符串漏洞
vuln(buf);
return 0;
}
测试流程
- 插桩编译:
afl-gcc -g -o afl_test afl_test.c
# 对于C++程序使用afl-g++
- 准备测试目录:
mkdir fuzz_in fuzz_out
echo "aaa" > fuzz_in/testcase
- 设置 core_pattern:
sudo su
echo core >/proc/sys/kernel/core_pattern
- 开始 Fuzzing:
afl-fuzz -i fuzz_in -o fuzz_out ./afl_test
AFL 界面解读
-
process timing:
- 运行时间
- 最近发现新路径时间
- 最近崩溃时间
- 最近超时时间
-
overall results:
- 总周期数(颜色变化指示进度)
- 总路径数
- 崩溃次数
- 超时次数
-
stage progress:
- 当前测试策略
- 进度
- 执行总次数
- 执行速度(理想应>500次/秒)
分析 Crash 结果
输出目录结构:
crashes/:崩溃样例hangs/:超时样例queue/:不同执行路径的测试用例
示例发现的漏洞:
- 栈溢出漏洞
- 首字符为F且长度为6的异常退出
- 格式化字符串%n任意地址写漏洞
- 首字符为A且长度为66的异常退出
无源码程序的 Fuzzing 测试
QEMU 模式安装
cd qemu_mode
./build_qemu_support.sh
cd ..
make install
测试流程
- 普通编译程序:
gcc -g -o afl_test2 afl_test.c
- 开始 Fuzzing:
afl-fuzz -i fuzz_in -o fuzz_out -Q ./afl_test2
注意:QEMU 模式执行效率显著降低(约600次/秒 vs 插桩模式4700次/秒)
测试 readelf 示例
- 准备测试环境:
mkdir in out
cd in
cp afl-2.52b/testcases/others/elf/small_exec.elf .
cd ..
sudo cp /usr/bin/readelf .
- 开始 Fuzzing:
afl-fuzz -i in -o out -Q ./readelf -a @@
关键注意事项
- 测试用例:初始测试文件最好小于1KB
- Makefile 项目:编译时需修改 Makefile
CC=/path/to/afl/afl-gcc ./configure make clean all - 输入方式:
- 从stdin读取:
./afl-fuzz -i in -o out /path/to/program [...params...] - 从文件读取:
./afl-fuzz -i in -o out /path/to/program @@
- 从stdin读取:
- 性能优化:执行速度低于500次/秒时应考虑优化