
Fuzzing ligero de una instantánea de memoria mediante KVM
Fuzzing ligero de una instantánea de memoria usando KVM
Snapchange proporciona la capacidad de cargar un volcado de memoria en bruto y el estado de los registros en una máquina virtual (VM) de KVM para su ejecución. En un punto de la ejecución, esta VM puede restablecerse a su estado inicial restableciendo las páginas sucias encontradas por KVM o las páginas ensuciadas manualmente por un fuzzer.
LibTIFF con ASANFFmpeg con mutador personalizado$ cp -r -L fuzzer_template your_new_fuzzer
your_new_fuzzer/create_snapshot.sh para tomar una instantánea de tu objetivosrc/fuzzer.rs para inyectar datos mutados en la VM invitada#[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
Uso rápido de términos para este README:
El hypervisor comienza mapeando el archivo de memoria física para cada núcleo solicitado. De esta manera, cada núcleo tiene su propia copia única de memoria. Luego, el hypervisor crea el invitado de KVM y le proporciona a este invitado la memoria de respaldo. El estado de los registros de este invitado se inicializa con el estado de registros dado y se lanza la ejecución del invitado. El hypervisor espera hasta que el invitado sale. Cada salida es manejada por el hypervisor y algunas se pasan al fuzzer para mutación, modificación o introspección específica del objetivo. Si el manejador de la salida indica que el invitado debe restablecerse, el hypervisor sale del bucle de ejecución, restablece el invitado al estado original de la instantánea y reinicia el bucle de ejecución nuevamente.
La cobertura del invitado se genera mediante breakpoints de cobertura. Se puede proporcionar al hypervisor un archivo separado con una lista de direcciones para breakpoints. Si se alcanza alguna de estas direcciones, la dirección se añadirá a la base de datos de cobertura y se restaurará la instrucción de esa dirección. De esta manera, el breakpoint no se volverá a activar.
Snapchange aprovecha directorios de proyecto específicos del objetivo para la configuración. Este directorio es donde se colocan los archivos y directorios de entrada y salida. Las siguientes extensiones/directorios de archivo se utilizan como entradas:
.physmem - El archivo que contiene el archivo de memoria física sin procesar.regs - Archivo de registros JSON que contiene el estado de los registros.qemuregs - Salida de info registers de qemuLa lista completa de archivos y sus usos en el directorio del proyecto se puede encontrar aquí.
Un ejemplo completo de la traza de depuración de un solo paso se puede encontrar aquí.
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]
A continuación se ofrece información sobre cómo obtener una instantánea mediante VirtualBox o QEMU:
Los ejemplos incluyen un script make_example.sh (como el ejemplo 1) que realiza una instantánea completa desde cero. Estos
ejemplos se pueden utilizar como plantilla para otros objetivos con el fin de obtener instantáneas reproducibles.
make all
cargo doc --open
El archivo HACKING proporciona algunas ubicaciones de alto nivel en la base de código para comenzar a entender el sistema.
Consulta CONTRIBUTING para obtener más información.
Este proyecto está licenciado bajo la Licencia Apache-2.0.