
Fuzzing léger d'un instantané de mémoire à l'aide de KVM
Fuzzing léger d'un instantané mémoire avec KVM
Snapchange offre la possibilité de charger un dump mémoire brut et l'état des registres dans une machine virtuelle (VM) KVM pour exécution. À un moment donné de l'exécution, cette VM peut être réinitialisée à son état initial en réinitialisant les pages modifiées trouvées par KVM ou les pages manuellement modifiées par un fuzzer.
LibTIFF avec ASANFFmpeg avec mutateur personnalisé$ cp -r -L fuzzer_template your_new_fuzzer
your_new_fuzzer/create_snapshot.sh pour prendre un instantané de votre ciblesrc/fuzzer.rs pour injecter des données mutées dans la VM invitée#[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
Aperçu rapide des termes utilisés dans ce README :
L'hyperviseur commence par mapper le fichier de mémoire physique pour chaque cœur demandé. De cette façon, chaque cœur possède sa propre copie unique de la mémoire. L'hyperviseur crée ensuite l'invité KVM et fournit à l'invité cette mémoire de support. L'état des registres de cet invité est ensuite initialisé avec l'état des registres donné et l'exécution de l'invité est lancée. L'hyperviseur attend que l'invité sorte. Chaque sortie est gérée par l'hyperviseur et certaines sont transmises au fuzzer pour une mutation, une modification ou une introspection spécifiques à la cible. Si le gestionnaire de la sortie indique que l'invité doit être réinitialisé, l'hyperviseur quitte la boucle d'exécution, réinitialise l'invité à l'état d'instantané d'origine et redémarre la boucle d'exécution.
La couverture de l'invité est générée en utilisant des points d'arrêt de couverture. Un fichier séparé contenant une liste d'adresses sur lesquelles placer des points d'arrêt peut être fourni à l'hyperviseur. Si l'une de ces adresses est atteinte, l'adresse sera ajoutée à la base de données de couverture et l'instruction correspondant à cette adresse sera restaurée. De cette façon, le point d'arrêt ne sera plus déclenché.
Snapchange s'appuie sur des répertoires de projet spécifiques à la cible pour la configuration. Ce répertoire est l'endroit où sont placés les fichiers et répertoires d'entrée et de sortie. Les extensions de fichiers/répertoires suivantes sont utilisées comme entrées :
.physmem - Le fichier contenant la mémoire physique brute.regs - Fichier de registres JSON contenant l'état des registres.qemuregs - Sortie de info registers de qemuLa liste complète des fichiers et de leurs utilisations dans le répertoire du projet se trouve ici.
Un exemple complet du traçage de débogage pas à pas peut être trouvé ici.
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]
Vous trouverez ci-dessous des informations sur l'obtention d'un instantané via VirtualBox ou QEMU :
Les exemples incluent un script make_example.sh (comme l'exemple 1) qui construit un instantané complet à partir de zéro. Ces exemples peuvent être utilisés comme modèle pour d'autres cibles afin de créer des instantanés reproductibles.
make all
cargo doc --open
Le document HACKING fournit quelques points de niveau supérieur dans la base de code pour commencer à comprendre le système.
Voir CONTRIBUTING pour plus d'informations.
Ce projet est sous licence Apache-2.0.