求助:AFL-fuzz无法检测到崩溃——首次使用AFL测试简易漏洞C代码遇阻
解决AFL-fuzz未检测到缓冲区溢出崩溃的问题
我来帮你排查这个入门时很容易踩的坑——你遇到的核心问题其实是AFL的输入传递方式和你的程序不匹配,咱们一步步来解决:
1. 关键问题:AFL默认输入是标准输入(stdin),你的程序却从命令行参数读取
你的程序通过argv[1]获取输入,但AFL-fuzz默认会把测试用例发送到程序的标准输入(stdin),而非命令行参数。这就导致AFL生成的所有测试用例根本没传到能触发缓冲区溢出的strcpy那里,自然不会发现崩溃。
两种解决方式:
方式一:修改程序,让它从stdin读取输入
把代码改成从标准输入获取内容,这样AFL的测试用例就能直接被程序接收:
#include <stdio.h> #include <string.h> int main(void){ char name[10]; // 从stdin读取输入 if (fgets(name, sizeof(name), stdin) != NULL) { // 去掉fgets自带的换行符 name[strcspn(name, "\n")] = '\0'; printf("HELLO %s\n", name); } return 0; }
重新用afl-gcc test.c -o test编译后,再运行afl-fuzz -i afl_in -o afl_out -- ./test,应该很快就能看到AFL检测到崩溃。
方式二:用AFL的@@占位符传递命令行参数
如果你不想修改代码,可以在启动AFL时用@@占位符,它会让AFL把测试用例保存成临时文件,然后把文件名作为命令行参数传给你的程序。你需要先修改程序读取这个文件的内容:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, char * argv[]){ char name[10]; if (argc > 1) { FILE *f = fopen(argv[1], "r"); if (f == NULL) { perror("fopen"); return 1; } // 从文件读取内容到name fgets(name, sizeof(name), f); fclose(f); name[strcspn(name, "\n")] = '\0'; strcpy(name, name); // 保留原有的溢出触发点 printf("HELLO %s\n", name); } return 0; }
然后用这个命令启动fuzz:
afl-fuzz -i afl_in -o afl_out -- ./test @@
2. 辅助检查:确保系统允许生成核心转储
AFL需要通过检测核心转储来识别崩溃,所以要先确认系统开启了core dump:
ulimit -c unlimited
执行这个命令后再启动afl-fuzz,避免因为系统限制导致AFL无法捕获崩溃。
3. 验证测试用例的正确性
你之前创建的崩溃测试用例带了换行符,可能会影响测试结果。可以用以下命令生成不带换行的测试用例:
python3 -c "print('A'*26, end='')" > afl_in/testcase_crash
这样测试用例就是纯26个A,和你手动触发崩溃时的输入一致。
按照上面的步骤调整后,重新运行AFL,不出意外的话几分钟内就能检测到缓冲区溢出导致的崩溃了。
内容的提问来源于stack exchange,提问作者Snox
相关产品推荐
相关产品推荐

