You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AFLplusplus/覃业斌-AFL++示例运行.md

9.9 KiB

一、功能介绍

AFL++是一个社区驱动的开源模糊测试工具它是在原始的American Fuzzy Lop (AFL)的基础上发展起来的。AFL++集成了多种模糊测试技术,提供了一个可扩展的平台,允许研究人员和开发者轻松地添加新的模糊测试策略和技术。它的特点包括:

  1. 种子调度AFL++采用了AFLFast的调度算法包括多种策略如 fast, coe, explore, quad, lin, exploit等,以及新增的 mmoptrare策略,以优化测试用例的选择和执行。
  2. 变异器AFL++在原有的 havocdeterministic变异器基础上增加了多种变异方式包括自定义变异器API、Input-To-State变异器和MOpt Mutator这些变异器可以提高模糊测试的效率和效果。
  3. 插桩支持AFL++支持多种插桩方式包括LLVM、GCC、QEMU、Unicornafl和QBDI以适应不同的测试需求和环境。
  4. 绕过障碍AFL++集成了如LAF-Intel和RedQueen等技术这些技术可以帮助模糊测试工具绕过程序中的一些常见障碍如复杂的字符串和校验和检查。
  5. 结构化输入变异AFL++支持对结构化输入进行变异如AFLSmart它可以利用输入模型来减少生成输入的空间从而更有效地探索程序中的深层路径。
  6. Custom Mutator APIAFL++提供了自定义变异器API允许用户根据自己的需要开发新的变异策略这对于学术研究和特定场景的测试非常有用。

AFL++的目标是提供一个稳定的基础使得未来的模糊测试研究可以在此基础上进行同时也为现有的模糊测试技术提供一个集成的平台。它与原始的AFL相比做了大量的改进和优化以适应快速发展的模糊测试领域。

AFL++项目地址

二、编译安装

项目推荐使用docker直接pull下来但由于网络问题本次示例采用在linux虚拟机上编译安装

git clone https://github.com/AFLplusplus/AFLplusplus # 克隆项目
sudo apt-get install -y build-essential python3-dev automake cmake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools cargo libgtk-3-dev #安装依赖环境
# 如果安装依赖环境出现问题先安装下面的llvm
sudo apt-get install -y lld-14 llvm-14 llvm-14-dev clang-14 || sudo apt-get install -y lld llvm llvm-dev clang
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev
#编译
git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
make distrib
sudo make install

安装完成后可以在使用afl-fuzz命令测试是否安装成功 1

三、运行示例

(一) 目标程序的源码

一个栈溢出案例代码如下当输入为abcd时会出现崩溃

//test.c
#include <stdio.h>
#include <string.h>

void vulnerable_function(char *input) 
{
    char buffer[4]; // 定义一个长度为4的字符数组

    // 复制用户输入到buffer中
    strcpy(buffer, input);

    printf("输入内容: %s\n", buffer);
}

int main() 
{
    char user_input[100];

    printf("请输入一串字符(以回车结束):");
    fgets(user_input, sizeof(user_input), stdin);

    // 移除换行符
    user_input[strcspn(user_input, "\n")] = 0;

    // 检查前四个字符是否是'a', 'b', 'c', 'd'
    if (user_input[0] == 'a' ){
        if( user_input[1] == 'b' ) {
            if (user_input[2] == 'c'){
                if (user_input[3] == 'd'){
                    vulnerable_function(user_input);
                }
            }
        } 
    }

    return 0;
}

(二)模糊测试以及准备工作

在模糊测试前先要进行源码编译插桩创建语料库

  1. 源码编译插桩:使用 afl++ 自带的插桩编译器afl-gcc 2
  2. 准备语料库:作为程序输入的原始材料,必须有才可以运行,原始材料越好漏洞发现的越快
 ➜  afl echo "abc" >> ./input/seed1
  1. 开启模糊测试:指定必要的目标文件夹就可以开启模糊测试了
➜  afl afl-fuzz -i input/ -o output/ ./test
afl-fuzz++4.22a based on afl by Michal Zalewski and a large online community
[+] AFL++ is maintained by Marc "van Hauser" Heuse, Dominik Maier, Andrea Fioraldi and Heiko "hexcoder" Eißfeldt
[+] AFL++ is open source, get it at https://github.com/AFLplusplus/AFLplusplus
[+] NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md
[+] No -M/-S set, autoconfiguring for "-S default"
[*] Getting to work...
[+] Using exploration-based constant power schedule (EXPLORE)
[+] Enabled testcache with 50 MB
[+] Generating fuzz data with a length of min=1 max=1048576
[*] Checking core_pattern...
[!] WARNING: Could not check CPU scaling governor
[+] You have 16 CPU cores and 2 runnable tasks (utilization: 12%).
[+] Try parallel jobs - see /usr/local/share/doc/afl/fuzzing_in_depth.md#c-using-multiple-cores
[*] Setting up output directories...
[+] Output directory exists but deemed OK to reuse.
[*] Deleting old session data...
[+] Output dir cleanup successful.
[*] Checking CPU core loadout...
[+] Found a free CPU core, try binding to #0.
[*] Validating target binary...
[*] Scanning 'input/'...
[*] Creating hard links for all input files...
[+] Loaded a total of 1 seeds.
[*] Spinning up the fork server...
[!] WARNING: Old fork server model is used by the target, this still works though.
[+] All right - old fork server is up.
[*] No auto-generated dictionary tokens to reuse.
[*] Attempting dry run with 'id:000000,time:0,execs:0,orig:seed1'...
    len = 4, map size = 5, exec speed = 157 us, hash = ad4e684fcf34ff0e
[+] All test cases processed.
[+] Here are some useful stats:

    Test case count : 1 favored, 0 variable, 0 ignored, 1 total
       Bitmap range : 5 to 5 bits (average: 5.00 bits)
        Exec timing : 157 to 157 us (average: 157 us)

[*] No -t option specified, so I'll use an exec timeout of 20 ms.
[+] All set and ready to roll!

            american fuzzy lop ++4.22a {default} (./test) [explore]
┌─ process timing ────────────────────────────────────┬─ overall results ────┐
│        run time : 0 days, 0 hrs, 0 min, 1 sec       │  cycles done : 15    │
│   last new find : 0 days, 0 hrs, 0 min, 1 sec       │ corpus count : 4     │
│last saved crash : 0 days, 0 hrs, 0 min, 1 sec       │saved crashes : 1     │
│ last saved hang : none seen yet                     │  saved hangs : 0     │
├─ cycle progress ─────────────────────┬─ map coverage┴──────────────────────┤
│  now processing : 3.19 (75.0%)       │    map density : 0.01% / 0.01%      │
│  runs timed out : 0 (0.00%)          │ count coverage : 1.00 bits/tuple    │
├─ stage progress ─────────────────────┼─ findings in depth ─────────────────┤
│  now trying : havoc                  │ favored items : 4 (100.00%)         │
│ stage execs : 85/100 (85.00%)        │  new edges on : 4 (100.00%)         │
│ total execs : 10.2k                  │ total crashes : 5 (1 saved)         │
│  exec speed : 8074/sec               │  total tmouts : 0 (0 saved)         │
├─ fuzzing strategy yields ────────────┴─────────────┬─ item geometry ───────┤
│   bit flips : 0/32, 0/31, 0/29                     │    levels : 2         │
│  byte flips : 0/4, 0/3, 0/1                        │   pending : 0         │
│ arithmetics : 0/238, 0/25, 0/0                     │  pend fav : 0         │
│  known ints : 0/23, 0/84, 0/46                     │ own finds : 3         │
│  dictionary : 0/0, 0/0, 0/0, 0/0                   │  imported : 0         │
│havoc/splice : 1/9650, 0/0                          │ stability : 100.00%   │
│py/custom/rq : unused, unused, unused, unused       ├───────────────────────┘
│    trim/eff : n/a, 25.00%                          │          [cpu000: 12%]
└─ strategy: explore ────────── state: started :-) ──┘^C

+++ Testing aborted by user +++
[*] Writing output//default/fastresume.bin ...
[+] Written fastresume.bin with 295308 bytes!
[+] We're done here. Have a nice day!
  1. afl-fuzz: 这是 AFL++ 的核心工具用于执行模糊测试。AFL++ 是一个强大的模糊测试工具,它通过自动化生成输入数据来测试目标程序,从而发现潜在的安全漏洞或程序崩溃。
  2. -i input/: 这个选项指定了 AFL++ 用来开始模糊测试的初始输入种子文件的目录。在这里,input/ 是包含初始输入数据的目录。AFL++ 会基于这些初始输入生成变异后的测试数据。
  3. -o output/: 这个选项指定了 AFL++ 将输出模糊测试结果的目录。output/ 目录将包含测试过程中生成的各种数据,比如发现的崩溃或挂起的输入、统计信息等。
  4. ./test: 这是要测试的目标程序。在这个例子中,./test 是你要使用 AFL++ 进行模糊测试的可执行文件。AFL++ 会向这个程序提供变异后的输入,观察它的行为(例如,是否会崩溃或触发其他异常行为)。

(三)验证漏洞

崩溃的输入样本会被保存在output目录下的crashes目录查看一下与原先对源码分析的结果一样也成功使程序崩溃示例完成

➜  afl cat output/default/crashes/id:000000,sig:06,src:000000,time:101,execs:789,op:havoc,rep:2
abcdcccccccccccccccccccccccc
➜  afl ./test
请输入一串字符以回车结束abcdcccccccccccccccccccccccc
*** buffer overflow detected ***: terminated
[1]    1456167 IOT instruction  ./test