Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
ydongyeon opened this issue Mar 6, 2024 · 6 comments
Open

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

ydongyeon opened this issue Mar 6, 2024 · 6 comments

Comments

@ydongyeon
Copy link

ydongyeon commented Mar 6, 2024

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
Copy link
Member

smoelius commented Mar 6, 2024

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:

afl.rs/afl/src/lib.rs

Lines 49 to 52 in 462eff5

// this marker strings needs to be in the produced executable for
// afl-fuzz to detect `persistent mode` and `defered mode`
static PERSIST_MARKER: &str = "##SIG_AFL_PERSISTENT##\0";
static DEFERED_MARKER: &str = "##SIG_AFL_DEFER_FORKSRV##\0";

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
Copy link
Author

ydongyeon commented Mar 6, 2024

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
Copy link
Member

smoelius commented Mar 6, 2024

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

#[allow(unused_imports)]
use afl::fuzz;

@ydongyeon
Copy link
Author

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

@smoelius
Copy link
Member

smoelius commented Mar 7, 2024

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
Copy link
Author

Thank you for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants