Skip to content

Commit

Permalink
Merge pull request #78 from AFLplusplus/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
andreafioraldi authored Apr 30, 2021
2 parents 2864d62 + 5b70724 commit bd22ea5
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 47 deletions.
28 changes: 13 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ LibAFL is written and maintained by Andrea Fioraldi <[email protected]> a

LibAFL gives you many of the benefits of an off-the-shelf fuzzer, while being completely customizable.
Some highlight features currently include:
- `multi platform`: LibAFL was confirmed to work on *Windows*, *MacOS*, *Linux*, and *Android* on *x86_64* and *aarch64*.
- `portable`: `LibAFL` can be built in `no_std` mode. Inject LibAFL in obscure targets like embedded devices and hypervisors.
- `fast`: We do everything we can at compile time, keeping runtime overhead minimal. Users reach 120k execs/sec in frida-mode on a phone (using all cores).
- `scalable`: `Low Level Message Passing`, `LLMP` for short, allows LibAFL to scale almost linearly over cores, and via TCP to multiple machines soon!
- `adaptable`: You can replace each part of LibAFL. For example, `BytesInput` is just one potential form input:
feel free to add an AST-based input for structured fuzzing, and more.
- `scalable`: `Low Level Message Passing`, `LLMP` for short, allows LibAFL to scale almost linearly over cores, and via TCP to multiple machines!
- `fast`: We do everything we can at compile time, keeping runtime overhead minimal.
- `multi platform`: LibAFL was confirmed to work on *Windows*, *MacOS*, *Linux*, and *Android* on *x86_64* and *aarch64*. `LibAFL` can be built in `no_std` mode to inject LibAFL into obscure targets like embedded devices and hypervisors.
- `bring your own target`: We support binary-only modes, like Frida-Mode, as well as multiple compilation passes for sourced-based instrumentation. Of course it's easy to add custom instrumentation backends.
- `usable`: We hope. But we'll let you be the judge. Enjoy LibAFL.

## Overview

Expand All @@ -26,26 +24,25 @@ It is fast, multi-platform, no_std compatible, and scales over cores and machine

It offers a main crate that provide building blocks for custom fuzzers, [libafl](./libafl), a library containing common code that can be used for targets instrumentation, [libafl_targets](./libafl_targets), and a library providing facilities to wrap compilers, [libafl_cc](./libafl_cc).

LibAFL offers integrations with popular instrumemntation frameworks. At the moment, the supported backends are:
LibAFL offers integrations with popular instrumentation frameworks. At the moment, the supported backends are:

+ SanitizerCoverage, in [libafl_targets](./libafl_targets)
+ Frida, in [libafl_frida](./libafl_frida), by s1341 <[email protected]> (Windows support is broken atm, it relies on [this upstream issue](https://github.com/meme/frida-rust/issues/9) to be fixed.)
+ More to come (QEMU-mode, ...)

LibAFL offers integrations with popular instrumemntation frameworks too. At the moment, the supported backends are:

+ SanitizerCoverage, in [libafl_targets](./libafl_targets)
+ Frida, in [libafl_frida](./libafl_frida), by s1341 <[email protected]> (Windows support will be added soon)

## Getting started

Clone the LibAFL repository with
1. Install the Rust development language. We highly recommend *not* to use e.g.
your Linux distribution package as this is likely outdated. So rather install
Rust directly, instructions can be found [here](https://www.rust-lang.org/tools/install).

2. Clone the LibAFL repository with

```
git clone https://github.com/AFLplusplus/LibAFL
```

To get the latest and greatest features,
If you want to get the latest and greatest features,
```
git checkout dev
```
Expand All @@ -56,18 +53,19 @@ Build the library using
cargo build --release
```

Build the API documentation with
4. Build the API documentation with

```
cargo doc
```

Browse the LibAFL book (WIP!) with (requires [mdbook](https://github.com/rust-lang/mdBook))
5. Browse the LibAFL book (WIP!) with (requires [mdbook](https://github.com/rust-lang/mdBook))

```
cd docs && mdbook serve
```


We collect all example fuzzers in [`./fuzzers`](./fuzzers/).
Be sure to read their documentation (and source), this is *the natural way to get started!*

Expand Down
2 changes: 1 addition & 1 deletion docs/src/design/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The LibAFL architecture is built around some entities to allow code reuse and low-cost abstractions.

Initially, we started thinking to implement LibAFL in an Object Oriented language, such C++. When we landed to Rust, we immediately changed our idea as we realized that, while Rust allow a sort of OOP pattern, we can build the library using a more sane approach like the one described in [this blogpost](https://kyren.github.io/2018/09/14/rustconf-talk.html) about game design in Rust.
Initially, we started thinking to implement LibAFL in an Object Oriented language, such C++. When we landed to Rust, we immediately changed our idea as we realized that, while Rust allows a sort of OOP pattern, we can build the library using a more sane approach like the one described in [this blogpost](https://kyren.github.io/2018/09/14/rustconf-talk.html) about game design in Rust.

The LibAFL code reuse meachanism is so based on components rather than sub-classes, but there are still some OOP patterns in the library.

Expand Down
12 changes: 6 additions & 6 deletions docs/src/getting_started/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ In addition, if you want to perform source-level fuzz testing of C/C++ applicati
you will likely need Clang with its instrumentation options to compile the programs
under test.

You can download and build the LLVM source tree, Clang included, following the steps
explained [here](https://clang.llvm.org/get_started.html).

Alternatively, on Linux, you can use your distro's package manager to get Clang,
On Linux you can use your distro's package manager to get Clang,
but these packages are not always updated, so we suggest you to use the
Debian/Ubuntu prebuilt packages from LLVM that are available using their [official repository](https://apt.llvm.org/).

For Miscrosoft Windows, you can download the [installer package](https://llvm.org/builds/) that LLVM generates periodically.
For Microsoft Windows, you can download the [installer package](https://llvm.org/builds/) that LLVM generates periodically.

Despite that Clang is the default C compiler on macOS, we discourage the use of the build shipped by Apple and encourage
the installation from `brew` or direclty a fresh build from the source code.
the installation from `brew` or directly a fresh build from the source code.

Alternatively you can download and build the LLVM source tree - Clang included - following the steps
explained [here](https://clang.llvm.org/get_started.html).

## Rust installation

Expand Down
2 changes: 1 addition & 1 deletion docs/src/medatata/definition.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ pub struct MyMetadata {
}
```

The struct must be static, so it cannot holds references to borrowed objects.
The struct must be static, so it cannot hold references to borrowed objects.


2 changes: 1 addition & 1 deletion fuzzers/frida_libpng/harness.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static char * allocation = NULL;
__attribute__((noinline))
void func3( char * alloc) {
printf("func3\n");
if (random() % 5 == 0) {
if (random() == 0) {
alloc[0xff] = 0xde;
}
}
Expand Down
9 changes: 5 additions & 4 deletions fuzzers/frida_libpng/src/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,10 @@ pub fn main() {
env::args()
.nth(3)
.expect("no modules to instrument specified")
.split(":")
.split(':')
.map(|module_name| std::fs::canonicalize(module_name).unwrap())
.collect(),
vec![PathBuf::from("./corpus")],
&vec![PathBuf::from("./corpus")],
PathBuf::from("./crashes"),
1337,
)
Expand All @@ -224,8 +225,8 @@ fn fuzz(
unsafe fn fuzz(
module_name: &str,
symbol_name: &str,
modules_to_instrument: Vec<&str>,
corpus_dirs: Vec<PathBuf>,
modules_to_instrument: Vec<PathBuf>,
corpus_dirs: &Vec<PathBuf>,
objective_dir: PathBuf,
broker_port: u16,
) -> Result<(), Error> {
Expand Down
1 change: 0 additions & 1 deletion libafl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ libafl_derive = { version = "*", optional = true, path = "../libafl_derive" }
serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] } # an easy way to debug print SerdeAnyMap
compression = { version = "0.1.5" }
num_enum = "0.5.1"
spin = "0.9.0"

[target.'cfg(target_os = "android")'.dependencies]
backtrace = { version = "0.3", optional = true, default-features = false, features = ["std", "libbacktrace"] } # for llmp_debug
Expand Down
2 changes: 1 addition & 1 deletion libafl_frida/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ termcolor = "1.1.2"
serde = "1.0"
backtrace = { version = "0.3.58", default-features = false, features = ["std", "serde"] }
num-traits = "0.2.14"
seahash = "4.1.0"
ahash = "0.7"

[target.'cfg(unix)'.dependencies]
gothook = { version = "0.1" }
23 changes: 12 additions & 11 deletions libafl_frida/src/asan_rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use std::{
cell::{RefCell, RefMut},
ffi::c_void,
io::{self, Write},
path::PathBuf,
rc::Rc,
};
use termcolor::{Color, ColorSpec, WriteColor};
Expand Down Expand Up @@ -697,7 +698,7 @@ impl AsanRuntime {
/// Initialize the runtime so that it is read for action. Take care not to move the runtime
/// instance after this function has been called, as the generated blobs would become
/// invalid!
pub fn init(&mut self, modules_to_instrument: &[&str]) {
pub fn init(&mut self, modules_to_instrument: &[PathBuf]) {
// workaround frida's frida-gum-allocate-near bug:
unsafe {
for _ in 0..512 {
Expand Down Expand Up @@ -730,7 +731,7 @@ impl AsanRuntime {
self.unpoison_all_existing_memory();
for module_name in modules_to_instrument {
#[cfg(unix)]
self.hook_library(module_name);
self.hook_library(module_name.to_str().unwrap());
}
}

Expand Down Expand Up @@ -786,15 +787,14 @@ impl AsanRuntime {
pub fn register_thread(&self) {
let mut allocator = Allocator::get();
let (stack_start, stack_end) = Self::current_stack();
println!("current stack: {:#016x}-{:#016x}", stack_start, stack_end);
allocator.map_shadow_for_region(stack_start, stack_end, true);

//let (tls_start, tls_end) = Self::current_tls();
//allocator.map_shadow_for_region(tls_start, tls_end, true);
//println!(
//"registering thread with stack {:x}:{:x} and tls {:x}:{:x}",
//stack_start as usize, stack_end as usize, tls_start as usize, tls_end as usize
//);
let (tls_start, tls_end) = Self::current_tls();
allocator.map_shadow_for_region(tls_start, tls_end, true);
println!(
"registering thread with stack {:x}:{:x} and tls {:x}:{:x}",
stack_start as usize, stack_end as usize, tls_start as usize, tls_end as usize
);
}

/// Determine the stack start, end for the currently running thread
Expand Down Expand Up @@ -829,6 +829,9 @@ impl AsanRuntime {
/// Determine the tls start, end for the currently running thread
fn current_tls() -> (usize, usize) {
let tls_address = unsafe { get_tls_ptr() } as usize;
// we need to mask off the highest byte, due to 'High Byte Ignore"
#[cfg(target_os = "android")]
let tls_address = tls_address & 0xffffffffffffff;

let (start, end, _, _) = find_mapping_for_address(tls_address).unwrap();
(start, end)
Expand Down Expand Up @@ -1421,7 +1424,6 @@ impl AsanRuntime {
; b >skip_report

; report:
; brk 0x11
; stp x29, x30, [sp, #-0x10]!
; mov x29, sp

Expand Down Expand Up @@ -1541,7 +1543,6 @@ impl AsanRuntime {
; b >skip_report

; report:
; brk 0x22
; stp x29, x30, [sp, #-0x10]!
; mov x29, sp

Expand Down
18 changes: 12 additions & 6 deletions libafl_frida/src/helper.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use ahash::AHasher;
use std::hash::Hasher;

use libafl::inputs::{HasTargetBytes, Input};

#[cfg(any(target_os = "linux", target_os = "android"))]
Expand Down Expand Up @@ -26,7 +29,7 @@ use frida_gum::{Gum, Module, PageProtection};
use num_traits::cast::FromPrimitive;

use rangemap::RangeMap;
use std::rc::Rc;
use std::{path::PathBuf, rc::Rc};

use crate::{asan_rt::AsanRuntime, FridaOptions};

Expand Down Expand Up @@ -82,9 +85,12 @@ impl<'a> FridaHelper<'a> for FridaInstrumentationHelper<'a> {

fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) {
if self.options.drcov_enabled() {
let mut hasher = AHasher::new_with_keys(0, 0);
hasher.write(input.target_bytes().as_slice());

let filename = format!(
"./coverage/{:016x}.drcov",
seahash::hash(input.target_bytes().as_slice())
hasher.finish(),
);
DrCovWriter::new(&filename, &self.ranges, &mut self.drcov_basic_blocks).write();
}
Expand Down Expand Up @@ -193,7 +199,7 @@ impl<'a> FridaInstrumentationHelper<'a> {
gum: &'a Gum,
options: FridaOptions,
_harness_module_name: &str,
modules_to_instrument: &'a [&str],
modules_to_instrument: &'a [PathBuf],
) -> Self {
let mut helper = Self {
map: [0u8; MAP_SIZE],
Expand All @@ -214,11 +220,11 @@ impl<'a> FridaInstrumentationHelper<'a> {

if options.stalker_enabled() {
for (id, module_name) in modules_to_instrument.iter().enumerate() {
let (lib_start, lib_end) = find_mapping_for_path(module_name);
println!("including range {:x}-{:x} for {}", lib_start, lib_end, module_name);
let (lib_start, lib_end) = find_mapping_for_path(module_name.to_str().unwrap());
println!("including range {:x}-{:x} for {:?}", lib_start, lib_end, module_name);
helper
.ranges
.insert(lib_start..lib_end, (id as u16, module_name));
.insert(lib_start..lib_end, (id as u16, module_name.to_str().unwrap()));
}

if helper.options.drcov_enabled() {
Expand Down

0 comments on commit bd22ea5

Please sign in to comment.