
Fuzzing leggero di uno snapshot della memoria tramite KVM
Fuzzing leggero di uno snapshot di memoria tramite KVM
Snapchange offre la possibilità di caricare un dump di memoria grezzo e lo stato dei registri in una macchina virtuale (VM) KVM per l'esecuzione. A un certo punto dell'esecuzione, questa VM può essere ripristinata al suo stato iniziale resettando le pagine dirty trovate da KVM o le pagine marcate manualmente come dirty da un fuzzer.
LibTIFF con ASANFFmpeg con mutatore personalizzato$ cp -r -L fuzzer_template your_new_fuzzer
your_new_fuzzer/create_snapshot.sh per creare uno snapshot del proprio targetsrc/fuzzer.rs per iniettare dati mutati nella VM guest#[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
Termini usati brevemente in questo README:
L'hypervisor inizia mappando il file di memoria fisica per ogni core richiesto. In questo modo, ogni core ha una propria copia unica della memoria. L'hypervisor crea poi il guest KVM e fornisce al guest questa memoria di supporto. Lo stato dei registri del guest viene quindi inizializzato con lo stato dei registri fornito e viene avviata l'esecuzione del guest. L'hypervisor attende finché il guest non esce. Ogni uscita viene gestita dall'hypervisor e alcune vengono passate al fuzzer per mutazioni, modifiche o introspezioni specifiche del target. Se il gestore dell'uscita indica che il guest deve essere resettato, l'hypervisor esce dal run loop, ripristina il guest allo stato originale dello snapshot e riavvia il run loop.
La copertura del guest viene generata usando breakpoint di copertura. Un file separato con un elenco di indirizzi su cui impostare i breakpoint può essere fornito all'hypervisor. Se uno qualsiasi di questi indirizzi viene raggiunto, l'indirizzo viene aggiunto al database di copertura e l'istruzione per quell'indirizzo viene ripristinata. In questo modo, il breakpoint non verrà più attivato.
Snapchange si basa su directory di progetto specifiche per il target per la configurazione. Questa directory è dove vengono collocati file e directory di input e output. Le seguenti estensioni/directory di file vengono usate come input:
.physmem - Il file contenente il file di memoria fisica grezza.regs - File dei registri JSON contenente lo stato dei registri.qemuregs - Output di info registers da qemuL'elenco completo dei file e dei loro usi nella directory del progetto si trova qui
Un esempio completo del trace di debug a passo singolo si trova qui.
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]
Di seguito le informazioni su come ottenere uno snapshot tramite VirtualBox o QEMU:
Gli esempi includono uno script make_example.sh (come nell'esempio 1) che crea uno snapshot completo da zero. Questi
esempi possono essere usati come modello per altri target per snapshot riproducibili.
make all
cargo doc --open
Il HACKING fornisce alcuni punti di partenza di livello più alto nel codebase per iniziare a comprendere il sistema.
Vedere CONTRIBUTING per maggiori informazioni.
Questo progetto è concesso in licenza con la Apache-2.0 License.