Snapchange - Fuzzing Basato su Snapshot con KVM Cheatsheet
Snapchange (di AWS) è un framework Rust per snapshot fuzzing. I fuzzer tradizionali riavviano il target per ogni input, che è fatalmente lento quando il codice interessante siede dietro una setup costosa — un handshake di rete, un login, una configurazione analizzata, un database caricato. Snapchange invece scatta una memoria snapshot del target esattamente nel momento di interesse, poi ripristina quello stato e muta da lì usando KVM, conseguendo tassi di iterazione molto alti contro il codice che il fuzzing convenzionale fa fatica a raggiungere.
Il snapshot fuzzing richiede KVM e root. Esegui in un ambiente isolato.
Requisiti
| Requisito | Nota |
|---|
| Linux con KVM | /dev/kvm accessibile |
| Toolchain Rust | Snapchange è una libreria Rust |
| QEMU | Usato per scattare lo snapshot |
| Root | Per KVM e accesso alla memoria |
Il Modello
| Fase | Cosa succede |
|---|
| 1. Snapshot | Esegui il target in QEMU al punto di interesse, dumpa memoria + registri |
| 2. Harness | Scrivi un fuzzer Rust descrivendo dove va l”input e quando fermarsi |
| 3. Fuzz | Snapchange ripristina lo snapshot per iterazione e muta l”input |
| 4. Triage | I crash sono registrati con lo stato esatto di registro/memoria |
L”insight critico: tutto il costo di setup è pagato una volta, nello snapshot. Ogni iterazione successiva inizia da quello stato in microsecondi.
Scattare Uno Snapshot
# Concettuale: esegui il target sotto QEMU, interrompi alla funzione di interesse,
# poi dumpa la memoria fisica e lo stato di registro
./snapchange/qemu_snapshot/take_snapshot.sh --target ./my-server
| Artefatto | Contiene |
|---|
fuzzvm.physmem | Memoria fisica guest completa |
fuzzvm.qemuregs | Stato di registro CPU |
*.symbols | Tabella di simboli per copertura/breakpoint |
vmlinux / binario | Per simbolizzazione |
Scrivere Un Fuzzer
// Forma concettuale — vedi esempi di Snapchange per codice completo
impl Fuzzer for MyFuzzer {
type Input = Vec<u8>;
const START_ADDRESS: u64 = 0x555555555000;
const MAX_INPUT_LENGTH: usize = 1024;
fn set_input(&mut self, input: &Self::Input, fuzzvm: &mut FuzzVm<Self>) -> Result<()> {
// Scrivi l''input mutato in memoria guest dove il target lo legge
fuzzvm.write_bytes_dirty(VirtAddr(BUFFER_ADDR), CR3, input)?;
Ok(())
}
fn reset_breakpoints(&self) -> Option<&[AddressLookup]> { /* condizioni di stop */ }
fn crash_breakpoints(&self) -> Option<&[AddressLookup]> { /* siti di crash */ }
}
| Elemento | Scopo |
|---|
START_ADDRESS | Dove l”esecuzione riprende ogni iterazione |
set_input | Inietta l”input di fuzz nella memoria guest |
reset_breakpoints | Dove un”iterazione termina normalmente |
crash_breakpoints | Indirizzi che indicano un crash (es. panic, abort) |
Esecuzione
| Comando | Descrizione |
|---|
cargo run -r -- fuzz -c 8 | Fuzz con 8 core |
cargo run -r -- project translate | Simbolizza/ispeziona lo snapshot |
cargo run -r -- coverage | Genera copertura dal corpus |
cargo run -r -- trace <input> | Traccia single-step di un input |
cargo run -r -- minimize <input> | Restringi un input che crasha |
Perché Snapshot Fuzzing Vince Qui
| Caratteristica target | Fuzzing convenzionale | Snapchange |
|---|
| Startup costoso | Lo paga ogni iterazione | Lo paga una volta |
| Richiede auth/handshake | Difficile da raggiungere | Snapshot oltre |
| Protocollo stateful | Difficile | Snapshot mid-session |
| Codice kernel/hypervisor | Molto difficile | Fit naturale |
Copertura & Triage
| Capacità | Nota |
|---|
| Copertura di breakpoint | Copertura via breakpoint su blocchi di base |
| Dedup di crash | Raggruppato per indirizzo di fallo/stato |
| Tracce single-step | Traccia di istruzione completa per un dato input |
| Ispezione della memoria | Leggi la memoria guest al momento del crash |
Snapchange vs Altri Fuzzer
| Aspetto | Snapchange | AFL++ | LibAFL (Nyx) | syzkaller |
|---|
| Esecuzione | Ripristino snapshot KVM | Fork di processo | Snapshot (Nyx) | VM + syscall |
| Costo di setup | Pagato una volta | Ogni iterazione | Una volta | Per VM |
| Target | Qualsiasi cosa in uno snapshot VM | Binari userspace | Configurabile | Kernel del sistema operativo |
| Sforzo | Alto (scrivi un fuzzer Rust) | Basso | Alto | Medio |
Confronta con LibAFL (che offre anche backend di snapshot) e syzkaller per fuzzing syscall del kernel.
Risorse