Fuzzing Module

项目地址:https://github.com/alex-maleno/Fuzzing-Module

execersise1:

以下程序存在问题
当输入的字符串的第一个或最后一个字符为\x00时触发abort()
其次当循环遍历到的当前字符的数字比前一个遍历到的数字大1时触发abort()

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

int main() {

   string str;

   cout << "enter input string: ";
   getline(cin, str);
   cout << str << endl << str [0] << endl;

    if(str[0] == 0 || str[str.length() - 1] == 0) {
        abort();
    }
    else {
        int count = 0;
        char prev_num = 'x';
        while (count != str.length() - 1) {
            char c = str[count];
            if(c >= 48 && c <= 57) {
                if(c == prev_num + 1) {
                    abort();
                }
                prev_num = c;
            } 
            count++;
        }
    }
    
    return 0;
}

当前目录下创建ipt,opt文件夹,在ipt/下生成随机种子

dd if=/dev/urandom of=1.in bs=64 count=10
dd if=/dev/urandom of=2.in bs=64 count=10
dd if=/dev/urandom of=3.in bs=64 count=10
dd if=/dev/urandom of=4.in bs=64 count=10
dd if=/dev/urandom of=5.in bs=64 count=10

使用以下命令编译目标

afl-clang-fast++ simple_crash.cpp -o sc

在当前目标文件夹下分别新建一个用于输入的文件夹和输出的文件夹
然后开始fuzz

afl-fuzz -i ipt/ -o opt/ -- ./sc

本地环境下测试不到1min能将以上触发abort()的输入全部跑出,输出存于crash的文件夹下

execersise2:

主要逻辑:

/*
 * George Sidamon-Eristoff
 * 30 March 2022
 * Comp 98 - Senior Capstone, 2nd Semester
 * airplane_object.cpp contains the function contracs and definitions for the Airplane class
 *
 * Note: there are purposely not many comments so the bug is more difficult to find
 */

#include <iostream>
#include <string>

#include "airplane_object.hpp"


Airplane::Airplane(){
    crew.num = 2;
    crew.captain_name = "Captain";
    crew.copilot_name = "CoPilot";
}


void Airplane::takeoff(){
    if (crew.num >= 1) {
        std::cout << "Takeoff!\n";
    } else {
        std::cout << "Nobody to fly the plane!\n";
    }
    return;
}

void Airplane::land(){
    if (crew.num >= 1) {
        std::cout << "Landed safely!\n";
    } else {
        std::cout << "Nobody left to land the plane!\n";
    }
    return;
}

void Airplane::hire(){
    crew.num += 1;
    std::cout << "Welcome aboard!\n";
    return;
}


void Airplane::fire(){
    crew.num -= 1;
    std::cout << "You're out of here!\n";
    return;
}

void Airplane::interact() {
    std::string input  = "";
    getline(std::cin, input);
    int input_length = input.length();
    if (input.empty()) {
        std::cout << "No command.\n";
    } else {
        int i = 0;
        while (input[i] != 'q' and i < input_length) {
            // std::cout << "i = " << i << "  input[i] =" << input[i] << "\n";
            if (input[i] == 't') {
                takeoff();
            } else if (input[i] == 'l') {
                if (crew.num == 0) {
                    abort();
                }
                land();
            } else if (input[i] == 'h') {
                hire();
            } else if (input[i] == 'f') {
                fire();
            }
            i++;
        }
    }
    return;
}

当输入l时会判断crew的数量,当crew.num==0时程序触发abort()

此题使用cmake,当前窗口临时设置环境变量指定编译器,设置好之后env | grep 查看

  export CC=afl-clang-fast
  export CXX=afl-clang-fast++

然后

cmake . && make 

之后正常fuzz,跑出7个crash,且都符合上述触发abort()的条件

execersise3:

此次练习熟悉AFL++的一个特性,delayed initialization
触发abort()的函数存在于specs.cpp中,很容易触发


void Specs::choose_color() {
    std::string color;
    std::cout << "enter desired aircraft color: ";
    std::cin >> color;
    if (isNumber(color))
        abort();
}

void Specs::min_alt() {
    // bool too_low = true;
    std::cout << "enter aircraft minimum altitude: ";
    std::cin >> alt;
    // do {
        // too_low = false;
    if(alt < 0) {
        std::cout << "too low. crashing!" << std::endl;
        abort();
    }
    else if (alt > 500) {
        std::cout << "too high. lowering to 500";
        alt = 500;
        // too_low = true;
    }
    // } while(too_low);
}

void Specs::min_airspeed() {
    bool out_of_bounds = true;
    std::cout << "enter aircraft minimum airspeed: ";
    std::cin >> speed;
    do {
        out_of_bounds = false;
        if(speed < 0)
            abort();
        if(speed < 100) {
            std::cout << "too low. please re-enter: ";
            std::cin >> speed;
            out_of_bounds = true;
        } else if (speed > 200) {
            std::cout << "too high. please re-enter: ";
            std::cin >> speed;
            out_of_bounds = true;
        }
    } while(out_of_bounds);
}

void Specs::fuel_cap() {
    bool too_high = true;
    std::cout << "enter fuel capacity: ";
    std::cin >> fuel;
    do {
        too_high = false;
        if(fuel < 0)
            abort();
        if (fuel > 100) {
            std::cout << "too high. please re-enter: ";
            std::cin >> fuel;
            too_high = true;
        }
    } while(too_high);
}

}

官方文档 : https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md

官方文档中描述的afl++只执行一次程序,并在main()之前停止,然后克隆这个主进程优化性能,如消除一些时间成本,比如程序的链接等,但在一些情况下可能并不总是有效,如加载一些较大的配置文件
文档中有个词叫Deferred initialization ,翻译过来可以叫作延迟初始化,指在main()函数中的某个位置开始克隆,在一些情况下可以有效提高效率,只需要使用如下命令:

#ifdef __AFL_HAVE_MANUAL_CONTROL
__AFL_INIT();
#endif

以上命令添加在main()中初始化spec后,比如specs-slice.cpp中:

/*
 *
 *
 * This file isolates the Specs class and tests out the 
 * choose_color function specifically.
 * 
 * 
 * 
 */

#include "specs.h"

int main(int argc, char** argv) {
    // In order to call any functions in the Specs class, a Specs
    // object is necessary. This is using one of the constructors
    // found in the Specs class.
    Specs spec(505, 110, 50);
    // By looking at all the code in our project, this is all the 
    // necessary setup required. Most projects will have much more
    // that is needed to be done in order to properly setup objects.

    // This section should be in your code that you write after all the 
    // necessary setup is done. It allows AFL++ to start from here in 
    // your main() to save time and just throw new input at the target.
    #ifdef __AFL_HAVE_MANUAL_CONTROL
        __AFL_INIT();
    #endif

    spec.choose_color();
    //spec.min_alt();

    return 0;
}

以上说明结束后进行fuzz

设置env环境变量后make:

  export CC=afl-clang-fast
  export CXX=afl-clang-fast++
  make

当前目录下创建ipt,opt文件夹,在ipt/下生成随机种子

dd if=/dev/urandom of=1.in bs=64 count=10
dd if=/dev/urandom of=2.in bs=64 count=10
dd if=/dev/urandom of=3.in bs=64 count=10
dd if=/dev/urandom of=4.in bs=64 count=10
dd if=/dev/urandom of=5.in bs=64 count=10

之后的fuzz都能跑出对应crash
分别测试了默认初始化和延迟初始化的速度:
延迟:

默认:

还是可以发现较明显的速度差异