rust-fuzz / afl.rs

🐇 Fuzzing Rust code with American Fuzzy Lop
https://rust-fuzz.github.io/book/afl.html
Apache License 2.0
1.61k stars 105 forks source link

Cannot combine afl.rs with asan when testing real world programs #470

Open ydongyeon opened 4 months ago

ydongyeon commented 4 months ago

Hi, I'v stuck with a problem that I cannot combine afl.rs with asan when it deals with real world programs without any use of 'fuzz' macro that afl.rs serves.

let mut rustflags = format!(
    "--cfg fuzzing \
     -C debug-assertions \
     -C overflow_checks \
     -C passes={} \
     -C codegen-units=1 \
     -C llvm-args=-sanitizer-coverage-level=3 \
     -C llvm-args=-sanitizer-coverage-trace-pc-guard \
     -C llvm-args=-sanitizer-coverage-prune-blocks=0 \
     -C opt-level=3 \
     -C target-cpu=native \
     -C debuginfo=0 \
     -l afl-llvm-rt \
     -L {} ",
    passes,
    common::afl_llvm_rt_dir(None).display()
);

This is the flags which are afl.rs is using. And if I build the program using "RUSTFLAGS="-Zsanitizer=address" cargo afl build" and run the afl fuzzing by "cargo afl fuzz -i in -o out target/debug/exectuable" it shows a problem like below

스크린샷 2024-03-06 오후 5 19 25

I think the pass (sancov-module) that afl.rs use is not compatible with asan with those flag options

let mut rustflags = format!(
    "--cfg fuzzing \
     -C debug-assertions \
     -C overflow_checks \
     -C passes={} \
     -C codegen-units=1 \
     -C llvm-args=-sanitizer-coverage-level=3 \
     -C llvm-args=-sanitizer-coverage-trace-pc-guard \
     -C llvm-args=-sanitizer-coverage-prune-blocks=0 \
     -C opt-level=3 \
     -C target-cpu=native \
     -C debuginfo=0 \
     -l afl-llvm-rt \
     -L {} ",

I've tried changing opt-level to 0, but it still does not solve the problem. Is there any way to use afl.rs with asan ?

smoelius commented 4 months ago

I cannot combine afl.rs with asan when it deals with real world programs without any use of 'fuzz' macro that afl.rs serves.

Does that mean the program doesn't import the afl package?

The afl package includes certain strings that AFLplusplus looks for: https://github.com/rust-fuzz/afl.rs/blob/462eff52b3c3ed9c3ea6f75d7cd9fbe66cab3949/afl/src/lib.rs#L49-L52

If those strings are not present, then AFLpluplus produces an error like you observed.

Otherwise, afl.rs should work with ASAN (at least it did a few months ago).

ydongyeon commented 4 months ago

Does that mean the program doesn't import the afl package?

The afl package includes certain strings that AFLplusplus looks for:

Yes, program doesn't import afl package. Because using afl.rs/afl/src/lib.rs fuzz api always uses persistent mode and needs some fuzzing driver.

But I want to fuzz real applications without fuzz driver as traditional afl does.

For example I want to fuzz such example without using fuzz!(|data:&[u8]|)

fn main() {
    let mut line = String::new();
    let _b1 = std::io::stdin().read_line(&mut line).unwrap();
    let length = line.len()-1;
    // if line.chars().nth(0).unwrap() < '|'{
    //     println!("{:?}", line.chars().nth(0).unwrap());
    // }

    if length < 10
    {
       ...
    }
}

To do this, I build the program by using RUSTFLAGS="-Zsanitizer=address" cargo afl build. If I don't add RUSTFLAGS="-Zsanitizer=address" flag, there is no problem for fuzzing. But when I add such address sanitizer flag, there is problem.

As you mentioned, if I use fuzz! api with ASAN by importing afl package, there is no problem because it uses persistent mode. I'm not sure but the reason for it is fuzz! api manually initialize fork server. unsafe { __afl_manual_init() };

So, when building the program using RUSTFLAGS="-Zsanitizer=address" cargo afl build, I think there is some incompatible problem between ASAN and some sancov-module pass.

smoelius commented 4 months ago

If you add this at the top of the file, is the outcome the same?

#[allow(unused_imports)]
use afl::fuzz;
ydongyeon commented 4 months ago

Oh, now it works. Thank you very much! But I wonder why adding #[allow(unused_imports)] use afl::fuzz; handles such problems ?

smoelius commented 4 months ago

I'm not sure, to be honest. I would have said, "because it gets the strings into the binary."

But I was able to observe the same behavior as you. It surprises me that cargo-afl works on a binary that doesn't import the afl package. I would have expected cargo-afl to fail because it couldn't find those strings.

Furthermore, I understand why you say this:

So, when building the program using RUSTFLAGS="-Zsanitizer=address" cargo afl build, I think there is some incompatible problem between ASAN and some sancov-module pass.

Let's please leave this issue open for now.

ydongyeon commented 4 months ago

Thank you for your help!