Snapchange (by AWS) é um framework Rust para fuzzing baseado em snapshot. Fuzzers tradicionais reiniciam o alvo para cada input, que é fatalmente lento quando o código interessante fica atrás de setup caro — um aperto de rede, um login, uma config parseada, um banco de dados carregado. Snapchange em vez disso pega um snapshot de memória do alvo no momento exato de interesse, então restaura aquele estado e muta a partir daí usando KVM, alcançando taxas de iteração muito altas contra código que fuzzing convencional dificilmente consegue alcançar.
Fuzzing baseado em snapshot requer KVM e root. Execute em um ambiente isolado.
Requisitos
| Requisito | Nota |
|---|
| Linux com KVM | /dev/kvm acessível |
| Toolchain Rust | Snapchange é uma biblioteca Rust |
| QEMU | Usado para tirar o snapshot |
| Root | Para KVM e acesso de memória |
O Modelo
| Fase | O que acontece |
|---|
| 1. Snapshot | Execute o alvo em QEMU até o ponto de interesse, dump memória + registros |
| 2. Harness | Escreva um fuzzer Rust descrevendo onde input vai e quando parar |
| 3. Fuzz | Snapchange restaura o snapshot por iteração e muta o input |
| 4. Triagem | Crashes são registrados com o estado exato de registrador/memória |
O insight crítico: todo o custo de setup é pago uma vez, no snapshot. Cada iteração subsequente começa a partir daquele estado em microsegundos.
Tirando um Snapshot
# Conceitual: execute o alvo sob QEMU, quebre na função de interesse,
# então dump memória física e estado de registrador
./snapchange/qemu_snapshot/take_snapshot.sh --target ./my-server
| Artefato | Contém |
|---|
fuzzvm.physmem | Memória física do guest completa |
fuzzvm.qemuregs | Estado do registrador de CPU |
*.symbols | Tabela de símbolo para cobertura/breakpoints |
vmlinux / binary | Para simbolização |
Escrevendo um Fuzzer
// Forma conceitual — veja exemplos Snapchange para código 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<()> {
// Escreve o input mutado na memória do guest onde o alvo o lê
fuzzvm.write_bytes_dirty(VirtAddr(BUFFER_ADDR), CR3, input)?;
Ok(())
}
fn reset_breakpoints(&self) -> Option<&[AddressLookup]> { /* condições de parada */ }
fn crash_breakpoints(&self) -> Option<&[AddressLookup]> { /* sites de crash */ }
}
| Elemento | Propósito |
|---|
START_ADDRESS | Onde execução retoma cada iteração |
set_input | Injeta o fuzz input na memória do guest |
reset_breakpoints | Onde uma iteração termina normalmente |
crash_breakpoints | Endereços que indicam um crash (ex. panic, abort) |
Executando
| Comando | Descrição |
|---|
cargo run -r -- fuzz -c 8 | Fuzz com 8 cores |
cargo run -r -- project translate | Simboliza/inspeciona o snapshot |
cargo run -r -- coverage | Gera cobertura do corpus |
cargo run -r -- trace <input> | Single-step rastreia um input |
cargo run -r -- minimize <input> | Encolhe um input travando |
Por que Fuzzing de Snapshot Vence Aqui
| Característica do alvo | Fuzzing convencional | Snapchange |
|---|
| Startup caro | Paga a cada iteração | Paga uma vez |
| Requer auth/handshake | Difícil de alcançar | Snapshot passou disso |
| Protocolo stateful | Difícil | Snapshot mid-session |
| Código de kernel/hypervisor | Muito difícil | Natural fit |
Cobertura & Triagem
| Capacidade | Nota |
|---|
| Cobertura de breakpoint | Cobertura via breakpoints em blocos básicos |
| Dedup de crash | Agrupado por endereço/estado de falha |
| Rastreamentos single-step | Rastreamento de instrução completo para um dado input |
| Inspeção de memória | Leia memória do guest no tempo de crash |
Snapchange vs Outros Fuzzers
| Aspecto | Snapchange | AFL++ | LibAFL (Nyx) | syzkaller |
|---|
| Execução | Restauração de snapshot KVM | Fork de processo | Snapshot (Nyx) | VM + syscalls |
| Custo de setup | Pago uma vez | A cada iteração | Uma vez | Por VM |
| Alvo | Qualquer coisa em um snapshot de VM | Binários userspace | Configurável | Kernels SO |
| Esforço | Alto (escreva um fuzzer Rust) | Baixo | Alto | Médio |
Compare com LibAFL (que também oferece backends de snapshot) e syzkaller para fuzzing de syscall de kernel.
Recursos