AFLplusplus / LibAFL

Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...
Other
2.03k stars 316 forks source link

Google Summer of Code #29

Closed domenukk closed 3 years ago

domenukk commented 3 years ago

Welcome Students :)

This is libAFL, our new fuzzing library. It's not public just yet, but will be opened up soon! Take a look around in the code base, look at the (todos)[./TODOS.md] and issues if you already feel like coding, feel free to post any questions in this issue or open your own issues.

In case anybody wants to open a PR, talk to @andreafioraldi or me.

MohitPatni0731 commented 3 years ago

Hey I am new to this organization. Can anyone guide me to how to get started because I really want to contribute in Open Source.

domenukk commented 3 years ago

Hey @MohitPatni0731 welcome :) I think the best way to get started is to first check out the example fuzzers in ./fuzzers, especially the libpng fuzzer, and try to get it running. Then, try to understand what's going on (at least on a high level), and see how you like working with the codebase. If that's all working, there are many TODOs, probably some are very fuzzing-specific, so don't be afraid to ask questions. :)

tokatoka commented 3 years ago

Hello,

I've been trying to run libfuzzer_libpng. When I run "./test.sh", nothing happens after echoing "Spawning client",

toka@:~/LibAFL/fuzzers/libfuzzer_libpng$ ./test.sh
    Finished release [optimized + debuginfo] target(s) in 0.03s
Spawning client

Is this an expected behavior? (I'm a bit anxious because I don't even see the println! in main())

domenukk commented 3 years ago

Just tried it and indeed it's not fuzzing with the current main, I'll take a look

tokatoka commented 3 years ago

Hi!

Thanks for your quick reply.

In addition, I think in test.sh, RUST_BACKTRACE=full taskset 0 ./.libfuzzer_test.elf & should be changed to RUST_BACKTRACE=full taskset 0x1 ./.libfuzzer_test.elf & instead to make it work. (because 0 is invalid as a bitmask, I guess)

domenukk commented 3 years ago

Good catch! I would add a -c to select this specific cpu (then we don't need bitmasks)

domenukk commented 3 years ago

@tokatoka should work again with f7db29d21319ef6213cb5f833cd86a86fae38c30

tokatoka commented 3 years ago

Hello,

After skimming through the source codes and TODO.md, I feel Timeouts for executors would be a good first thing to work on for me. It seems timeouts and crashes as signals are already handled in executors/inprocess.rs.

So, does Timeout for executors mean that we want something like fsrv.exec_tmount as in LibAFL-legacy? (https://github.com/AFLplusplus/LibAFL-legacy/blob/dev/src/aflpp.c#L252)

I'm a bit of a newbie, so correct me if I'm wrong :)

domenukk commented 3 years ago

@tokatoka yes similar to that, although you're looking at the forkserver here, for the in-process executor we need another concept. Probably it's fine for now to, on Unix, set a simple alarm before execution and unset it afterwards. Eventually we'll want a way to do this more coarse grained to get rid of too many syscalls, or we might even abuse the broker for timing

vanhauser-thc commented 3 years ago

, or we might even abuse the broker for timing

@domenukk I am pretty sure no one who is reading the issue understands at this point what our broker is :) keep it simple! :)

vj-27 commented 3 years ago

if anyone is from a C/C++ background and new to Rust, this book might be useful to get started.

tokatoka commented 3 years ago

Hi,

I've made some simple modifications to set timeouts for executors using alarm. Can I get a permit to make a pull request?

(and should I make a new issue and discuss the Timeouts for executors before making a pull request?)

domenukk commented 3 years ago

Awesome! :) You should now be able to push to a new branch and create a PR from there. I think discussing details in the PR is fine, but up to you.

domenukk commented 3 years ago

Just pointing this out: a perfect and easy start in the codebase may be contributing some rustdoc, including usage examples for parts of the lib. Don't be afraid to ask y'all :)

chibinz commented 3 years ago

I did some initial research on the forkserver and wanted to discuss some of the issues, obstacles and design choices of transitioning from C to Rust.

  1. Original AFL++ forkserver uses pipe to for fuzzer communication with the forkserver. File descriptors are inherited by the child process and forkserver fixes read end of control pipe and write end of status pipe to FORKSRV_FD/+1. But ideas.md seems to suggest using Socketpair for communication, similar to Angora's UnixStream. This offers 2 benefit: first it is supported in the std library (which pipe doesn't), second it is birectional. However, switching to UnixStream means that the forkserver (runtime) has to change as well. Do we wish to be backward compatible with afl-compiler-rt.o.c? Or rewrite the runtime in Rust with extern "C", maybe?
  2. Continuing from 1. Previous fuzzer <-> forkserver communication "protocol" is mainly implemented through reading and writing 4 bytes at a time. The transferred 4 bytes have special meaning depending on the context. such as bitflags indicating the forkserver's supported options. Since we're transitioning to rust, I think a better idea would be to create an enum type for all kinds of messages, and then serialize and deserialize them across the SocketPair (If we rewrite the runtime). Because communication happens mostly upon startup and once per execution, the overhead should be relatively low, in exchange for better extensibility and readability, perhaps?
  3. Rust's standard way of spawning a subprocess is to use std::process::Command. Original implementation calls fork, setup the pipe file descriptors, rlimit, and the environment variables accordingly, and finally calls execv to spin up the forkserver. Command, unfortunately, does not allow for such flexibility... It has envs to set env variables, but get_envs is not yet stablized. Trait std::os::unix::process::CommandExt provides an unsafe method before_exec that allows us to call an custom function before execution. To use fork in Rust, we might want to bring in the nix crate as an dependency... (Add forkserver as a feature to keep the crate no_std?)

Would like to hear your advice and opinion on these 3 points :)

vanhauser-thc commented 3 years ago

IMHO the compatibility to afl++ compiled binaries is important at the moment. otherwise libafl would need its own runtime and compiler. however for the future an alternative would be nice (for libafl & afl++ 4.0+ ;) - that uses a different mechanism that has less overhead. dominik and andrea are the head of the project though

peperunas commented 3 years ago

Just an idea for @domenukk and @andreafioraldi: what do you think to create some low-hanging fruit feature requests/bug fixes for newcomers?

julihoh commented 3 years ago

Hey :)

  1. Rust's standard way of spawning a subprocess is to use std::process::Command. Original implementation calls fork, setup the pipe file descriptors, rlimit, and the environment variables accordingly, and finally calls execv to spin up the forkserver. Command, unfortunately, does not allow for such flexibility... It has envs to set env variables, but get_envs is not yet stablized. Trait std::os::unix::process::CommandExt provides an unsafe method before_exec that allows us to call an custom function before execution. To use fork in Rust, we might want to bring in the nix crate as an dependency... (Add forkserver as a feature to keep the crate no_std?)

Not sure if you are still looking into this, but the Angora fuzzer is also implemented in Rust and has a forkserver. It also has a neat little extension for Command the enables some of the features you mentioned.

Just thought I'd leave it here in case you weren't already aware and need some inspiration :)

Cheers

andreafioraldi commented 3 years ago

@peperunas in the TODOs, other feedbacks and other objectives are a quite small and easy to implement feature. Look at libfuzzer_libpng_cmpalloc in the dev branch. Here I added the cmp and alloc feedbacks that maximize the cmp matching bits (a la libfuzzer -value-profile) and the allocations sizes wrapping malloc. In LibAFL, the objectives are a kind of feedback not used to evolve the corpus, but to classify an input as "solution". The most trivial example of solution in a fuzzer is a crash, see how CrashFeedback is used in our examples. Ofc a fuzzer can explore the program states not just for crashes, but for other user-specified objectives too, think about directed fuzzing in which we search for just one specific crash, or reachability in which we fuzz to hit a specific program point. You can start implementing also additional objectives, reachability is the easiest one. You need to implement the ReachabilityFeedback, the corresponding Observer and a test fuzzer (libfuzzer_libpng_reachability).

domenukk commented 3 years ago

I've added a rather simple issue if anyone feels like picking it up, https://github.com/AFLplusplus/LibAFL/issues/36 (let us know if you do, else we work on it in parallel)

TaKO8Ki commented 3 years ago

@domenukk

Hi,

I want to make some simple modifications. Can I get a permission to push?

domenukk commented 3 years ago

@TaKO8Ki of course. You got access now. :) Please don't push to main or dev directly, but create your own branch and open a PR from there. Thx ;)

vanhauser-thc commented 3 years ago

Students, the deadline for your GSoC applications are near. Do not forget! :)

tokatoka commented 3 years ago

When I'm done with writing the proposal, can I have my proposal reviewed by a mentor before submitting to GSoC (if possible) ?

andreafioraldi commented 3 years ago

When I'm done with writing the proposal, can I have my proposal reviewed by a mentor before submitting to GSoC (if possible) ?

Yes ofc, mail gsoc@aflplus.plus

krishna619 commented 3 years ago

Hi, can we consider Mersenne Twister (PRNG) as rand implementation for black box generation because sequences with too short of a period can be observed, recorded, and reused by an attacker.? thanks

tokatoka commented 3 years ago

@vanhauser-thc Sorry, I mistakenly unpinned this issue.

I'm sorry, I thought it was some kind of popup for me...

domenukk commented 3 years ago

Hi, can we consider Mersenne Twister (PRNG) as rand implementation for black box generation because sequences with too short of a period can be observed, recorded, and reused by an attacker.? thanks

@krishna619 Did you actually observer any issues with the current Rand implementations? Feel free to add different implementations it to the existing Rands in utils implementations, but I assume it's a lot slower and will not produce better results for fuzzing.

domenukk commented 3 years ago

Don't forget to submit your proposals :)