Skip to content

A bare-metal x86 instruction set fuzzer a la Sandsifter

License

Notifications You must be signed in to change notification settings

blitz/baresifter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Baresifter

Tests stability-experimental GitHub GitHub commit activity

Baresifter is a 64-bit x86 instruction set fuzzer modeled after Sandsifter. In contrast to Sandsifter, Baresifter is intended to run bare-metal without any operating system. It's most easy to set up to run in a virtual machine.

When loaded, the main fuzzing logic runs in ring0 as a tiny kernel. To safely execute arbitrary instructions, baresifter creates a single executable page in ring3 user space. For every instruction candidate, baresifter writes the instruction bytes to this user space page and attempts to execute it by exiting to user space. It follows the same algorithm as outlined in the original Sandsifter paper to find interesting instructions and guess instruction length.

Building and running

The build is currently tested on NixOS and other Linux distributions with Nix installed. If you haven't done so, install Nix.

Then enter a nix-shell and build baresifter:

% nix-shell
# Dependencies are fetched. This might take a bit.

nix-shell % scons -C src

Once you have built baresifter, you can run it in Qemu:

# Execute 1000 instructions in Qemu's full emulation mode.
nix-shell % baresifter-run tcg src/baresifter.x86_64.elf stop_after=1000
...

# Run forever with KVM enabled.
nix-shell % baresifter-run kvm src/baresifter.x86_64.elf
...

To run baresifter bare-metal, use either grub or syslinux and boot baresifter.elf32 as multiboot kernel. It will dump instruction traces on the serial port. The serial port is hardcoded, so you might need to change that: git grep serial_output.

Interpreting results

Baresifter outputs data in a tabular format that looks like:

EXC <exc> <OK|??> | <instruction hex bytes>

exc is the CPU exception that was triggered, when baresifter tried to execute the instruction. OK indicates the CPU decoded the instruction, ?? means we probably hit a bug in Baresifter. The rest are the instruction bytes in hexadecimal.

A concrete example looks like this:

EXC 0D OK | 0F 08
EXC 06 OK | 0F 0A
EXC 01 OK | 0F 0D 00

The first line is an instruction that decoded successfully and generated a general protection exception (#GP / 0x0D) when executing. In this case, it was a invd instruction. The second line is an invalid opcode (0x06). The third line is an instruction that decoded and executed correctly by running into a #DB (0x01) exception.

Earlier versions of Baresifter had a built-in disassembler to disassemble on-the-fly and find interesting discrepancies. This was removed in favor of offline analysis of the logs, but this offline analysis does not exist yet.