Skip to content
/ squid Public

RISC-V emulator for high-performance fuzzing with AOT instead of JIT compilation 🦑

License

Notifications You must be signed in to change notification settings

fkie-cad/squid

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


squid

squid is a RISC-V emulator with features that make it a powerful tool for vulnerability research and fuzzing.

It utilizes AOT instead of JIT compilation and allows you to rewrite the binary's code before emulation. During runtime, you get full control over your target by handling all system calls and other events yourself. This makes it easy to create and combine new sanitizers and test programs for all kinds of vulnerabilities, not just memory corruptions.

Features

  • Fast snapshots
  • Byte-level permissions on memory
  • Rewriting binaries before emulation
  • Integration into LibAFL

However, it can run only single-threaded Linux user-space applications that are written in C.
The source of the target must be available because squid supports only binaries that have been compiled with this specific set of flags:

-fPIE -pie -O0 -g -fno-jump-tables -mno-relax -D__thread=

This makes squid unsuitable for blackbox fuzzing. Instead, it was built to augment traditional greybox fuzzing. It is encouraged to combine squid with native fuzzers to achieve both, high throughput and enhanced bug detection.

Demo

As a quick appetizer let's have a look at how we can overcome common restrictions of LLVM's sanitizers with squid.

One of the biggest restrictions is that multiple sanitizers cannot be combined in a single build. Trying to invoke a compiler like this:

clang -fsanitize=address,memory

results in

clang: error: invalid argument '-fsanitize=address' not allowed with '-fsanitize=memory'

However, since squid allows us to do binary rewriting, we can recreate ASAN and MSAN instrumentation ourselves. We just have to compile our target with the flags mentioned above and then we can instrument and emulate it like this:

fn main() {
    // 1) Load and lift the target binary into our custom IR
    let mut compiler Compiler::loader()
        .binary("./some-riscv-binary")  // The target binary
        .load();

    // 2) Run the ASAN pass over the binary to insert redzones
    //    and interceptors for the heap functions similar to LLVM's
    //    ASAN.
    let mut asan_pass = AsanPass::new();
    compiler.run_pass(&mut asan_pass);

    // 3) AOT compile functions in IR to native machine code by
    //    translating the IR to C code that is then compiled with clang
    let backend = ClangBackend::builder()
        .stack_size(2 * 1024 * 1024)
        .heap_size(16 * 1024 * 1024)
        .enable_uninit_stack(true) // MSAN !
        .build();
    let mut runtime = compiler.compile(backend);

    // 4) Run the binary, handle syscalls and interceptors
    loop {
        match runtime.run() {
            Ok(event) => match event {
                EVENT_SYSCALL => /* we have to emulate system calls ourselves here... */,
                EVENT_ASAN => /* ASAN's interceptors have fired */
            },
            Err(fault) => /* Some kind of fault occured, e.g. a segfault */,
        }
    }
}

This gives us support for

  • ASAN: Because the AsanPass inserts redzones around global variables and registers interceptors that must be handled in runtime.run()
  • MSAN: Because we tell the backend to mark newly created stackframes as uninitialized with enable_uninit_stack(true). New heap memory returned to malloc() is always marked as uninitialized per default.

And then, we could go even further and combine even more sanitizers to catch a broader range of vulnerabilities, not just memory corruptions.

Getting Started

You can find detailed explanations how to harness squid in our wiki.
For a gentle introduction, see the hello world example.
For an example how to combine native and emulation-based fuzzing for maximum effectiveness, see our readelf fuzzer.

If you find that something is not properly documented / explained or you have any other questions, please do not hesitate to create an issue.

About

RISC-V emulator for high-performance fuzzing with AOT instead of JIT compilation 🦑

Topics

Resources

License

Stars

Watchers

Forks

Languages