
Leichtgewichtiges Fuzzing eines Speicher-Snapshots mithilfe von KVM
Leichtgewichtiges Fuzzing eines Speicher-Snapshots mit KVM
Snapchange bietet die Möglichkeit, einen rohen Speicherdump und den Registerzustand in eine KVM-Virtual Machine (VM) zur Ausführung zu laden. An einem bestimmten Punkt der Ausführung kann diese VM in ihren Ausgangszustand zurückversetzt werden, indem die von KVM gefundenen Dirty Pages oder die von einem Fuzzer manuell als dirty markierten Seiten zurückgesetzt werden.
LibTIFF mit ASANFFmpeg mit benutzerdefiniertem Mutator$ cp -r -L fuzzer_template your_new_fuzzer
your_new_fuzzer/create_snapshot.sh, um einen Snapshot Ihres Ziels zu erstellensrc/fuzzer.rs, um mutierte Daten in die Gast-VM einzuspeisen#[derive(Default)]
pub struct TemplateFuzzer;
impl Fuzzer for TemplateFuzzer {
// The type of Input being fuzzed. Used to know how to generate and mutate useful inputs.
type Input = Vec<u8>;
// The starting address of the snapshot
const START_ADDRESS: u64 = 0x402363;
// The maximum length of mutated input to generate
const MAX_INPUT_LENGTH: usize = 100;
fn set_input(&mut self, input: &Self::Input, fuzzvm: &mut FuzzVm<Self>) -> Result<()> {
// Write the mutated input into the data buffer in the guest VM
fuzzvm.write_bytes_dirty(VirtAddr(0x402004), CR3, &input)?;
Ok(())
}
fn reset_breakpoints(&self) -> Option<&[BreakpointLookup]> {
Some(&[
// Reset when the VM hits example1!main+0x123
BreakpointLookup::SymbolOffset("example1!main", 0x123)
])
}
}
$ cargo run -r -- fuzz -c 16
Kurzüberblick über die in diesem README verwendeten Begriffe:
Der Hypervisor beginnt damit, die physische Speicherdatei für jeden angeforderten Kern abzubilden. Auf diese Weise besitzt jeder Kern seine eigene, eindeutige Kopie des Speichers. Anschließend erstellt der Hypervisor den KVM-Gast und übergibt diesem Gast den zugrunde liegenden Speicher. Der Registerzustand dieses Gasts wird dann mit dem angegebenen Registerzustand initialisiert und die Ausführung des Gasts gestartet. Der Hypervisor wartet, bis der Gast ein Exit auslöst. Jeder Exit wird vom Hypervisor behandelt und einige werden an den Fuzzer zur zielspezifischen Mutation, Modifikation oder Introspection weitergegeben. Wenn der Handler des Exits anzeigt, dass der Gast zurückgesetzt werden soll, verlässt der Hypervisor die Run-Loop, setzt den Gast zurück in den ursprünglichen Snapshot-Zustand und startet die Run-Loop erneut.
Das Coverage des Gasts wird mithilfe von Coverage-Breakpoints erzeugt. Eine separate Datei mit einer Liste von Adressen, an denen Breakpoints gesetzt werden sollen, kann dem Hypervisor übergeben werden. Wenn eine dieser Adressen erreicht wird, wird die Adresse zur Coverage-Datenbank hinzugefügt und die Anweisung für diese Adresse wiederhergestellt. Auf diese Weise wird der Breakpoint nicht erneut ausgelöst.
Snapchange nutzt zielspezifische Projektverzeichnisse für die Konfiguration. In diesem Verzeichnis werden Eingabe- und Ausgabedateien sowie -verzeichnisse abgelegt. Die folgenden Dateierweiterungen/-verzeichnisse werden als Eingaben verwendet:
.physmem – Die Datei, die die rohe, physische Speicherdatei enthält.regs – JSON-Registerdatei, die den Registerzustand enthält.qemuregs – Ausgabe von info registers aus qemuDie vollständige Liste der Dateien und ihrer Verwendung im Projektverzeichnis finden Sie hier
Ein vollständiges Beispiel für das Debugging-Single-Step-Trace finden Sie hier.
ITERATION 604 0x00007ffff7ecb0d5 0x11115000 | libc-2.31.so!__GI___getpid+0x5 (0x7ffff7ecb0d5)
syscall
[0f, 05]
ITERATION 605 0xffffffff83a00000 0x11115000 | entry_SYSCALL_64+0x0 (0xffffffff83a00000)
swapgs
[0f, 01, f8]
ITERATION 606 0xffffffff83a00003 0x11115000 | entry_SYSCALL_64+0x3 (0xffffffff83a00003)
mov qword ptr gs:[0xa014], rsp
[None:0x0+0xa014=0xa014]]
RSP:0x7fffffffeb78 -> example1!main+0x19 (0x55555555514e)-> 0xff8458b48f44589
[65, 48, 89, 24, 25, 14, a0, 00, 00]
ITERATION 607 0xffffffff83a0000c 0x11115000 | entry_SYSCALL_64+0xc (0xffffffff83a0000c)
nop
[66, 90]
ITERATION 608 0xffffffff83a0000e 0x11115000 | entry_SYSCALL_64+0xe (0xffffffff83a0000e)
mov rsp, cr3
RSP:0x7fffffffeb78 -> example1!main+0x19 (0x55555555514e) -> 0xff8458b48f44589
CR3:0x11115000
[0f, 20, dc]
Informationen zum Erstellen eines Snapshots über VirtualBox oder QEMU finden Sie unten:
Die Beispiele enthalten ein make_example.sh-Skript (wie Beispiel 1), das einen vollständigen Snapshot von Grund auf erstellt. Diese
Beispiele können als Vorlage für andere Ziele verwendet werden, um reproduzierbare Snapshots zu erstellen.
make all
cargo doc --open
Die Datei HACKING bietet einige übergeordnete Einstiegspunkte in die Codebasis, um das System zu verstehen.
Weitere Informationen finden Sie unter CONTRIBUTING.
Dieses Projekt ist unter der Apache-2.0-Lizenz lizenziert.