
Outil d'instrumentation binaire statique pour exécutables Windows x64
peafl64 est un outil d'instrumentation statique pour les PE x64 sous Windows.
L'instrumentation statique consiste à modifier des fichiers exécutables en ajoutant du code à des emplacements précis.
L'instrumentation ajoute du code au début de chaque bloc de base du binaire, enregistrant le flux d'exécution d'une manière compatible avec AFL.
Elle permet de fuzzer des binaires en mode utilisateur (avec WinAFL) et en mode noyau (avec kAFL) sans avoir accès à leur code source.
Il existe d'autres méthodes pour fuzzer les binaires Windows ; dans ce projet, nous avons choisi de nous concentrer sur l'instrumentation statique car c'est la méthode la plus rapide.
Ce projet s'appuie sur l'outil pe-afl de wmliang, avec l'ajout du support x64.
Le script d'instrumentation nécessite une sortie d'analyse IDA.
Pour la créer, exécutez le script ida_dumper.py fourni dans IDA.
Le script requiert IDA 7+ et python3.8+.
usage: pe_afl.py [-h] [-n] [-cb] [-tf] [-te THREAD_ENTRY] [-nt NTOSKRNL] [-e ENTRY] [-l ENLARGE] [-v] [-lf] pefile ida_dump
positional arguments:
pefile Target PE file for instrumentation
ida_dump dump.json from IDA (created by ida_dumper.py)
optional arguments:
-h, --help show this help message and exit
-n, --nop Instrument with NOPs for testing
-cb, --callback Instrument with a callback, which is in the helper driver that's written in C
-tf, --thread-filter Driver instrumentation that filters only on thread ID (must use "-te" with this option)
-te THREAD_ENTRY, --thread-entry THREAD_ENTRY
The address (RVA) of the thread's initialization function
-nt NTOSKRNL, --ntoskrnl NTOSKRNL
ntoskrnl.exe path for offset extraction (non-optional if instrumenting a driver)
-e ENTRY, --entry ENTRY
Inject code on entry point, ie. -e9090
-l ENLARGE, --enlarge ENLARGE
Enlarge factor for sections, default=4
-v, --verbose Print debug log
-lf, --logfile Print log to pe-afl64.log rather than stream
Instrumentation d'un binaire en mode utilisateur avec des NOPs
PS pe-afl-64> python .\pe_afl.py -n C:\Work\cmd.exe C:\Work\cmd.exe.dump.json
[*] User-mode binary is being instrumented
[*] Single-thread instrument is on
[*] Preparing new sections
[*] Added section .text^
[*] Added section .cov
[*] Expanding relative jumps
[*] Expanded 3874 of 14353 branches
[*] Building address map
[*] Updating relative instructions
[*] Updating relocations...
[*] Updating Export table
[*] Updating load config
[*] Updating exception records
[*] Updating the PE headers
[*] Finalizing...
[*] Creating instrumented code
[*] Writing address mapping to C:\Work\cmd.exe.mapping.txt
[*] Updating jump tables
[*] Updated .text
...
[*] Removing temporary PE files
[*] Fixing PE checksum
[*] Instrumented binary saved to: C:\Work\cmd.instrumented.exe
Instrumentation d'un binaire en mode noyau avec filtrage par ID de processus
python .\pe_afl.py -l 6 -nt "C:\Work\ntoskrnl.exe" "C:\Work\driver.sys" "C:\Work\driver.sys.dump.json"
Instrumentation d'un binaire en mode noyau avec filtrage par ID de thread et sortie détaillée
python .\pe_afl.py -v -tf -te 0x40000 -l 6 -nt "C:\Work\ntoskrnl.exe" "C:\Work\ntoskrnl.exe" "C:\Work\ntoskrnl.exe.dump.json"
D'abord, vous devez vérifier si votre machine démarre avec BIOS ou UEFI.
Pour les machines Hyper-V : les machines de génération 1 utilisent le BIOS, et les machines de génération 2 utilisent l'UEFI.
Si votre machine utilise le BIOS, vous devez patcher winload.exe :
ImgpValidateImageHashmov eax, edi par xor eax, eax dans le dernier bloc de code de la fonctionbcdedit /set path \Windows\system32\winload2.exeSi votre machine démarre avec UEFI, utilisez l'utilitaire EfiGuard pour patcher winload.efi.
Aide-mémoire des commandes si vous utilisez le Gestionnaire Hyper-V :
FS1:
cd EFI/Boot
Load EfiGuard.Dxe.efi
FS0:
\EFI\Boot\bootx64.efi
Instrumentez ensuite le pilote de votre choix. Pour charger un pilote instrumenté sur une machine Windows, il doit être signé, et un certificat auto-signé suffit pour satisfaire aux exigences de l'OS :
# In elevated powershell terminal
$c = New-SelfSignedCertificate -Type CodeSigningCert -KeyUsage DigitalSignature -Subject 'CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US'
Set-AuthenticodeSignature .\driver.instrumented.sys -Certificate $c -Force
Si le pilote que vous avez instrumenté est déjà utilisé par le système, utilisez ces commandes (en tant qu'administrateur) pour remplacer le fichier du pilote :
set NAME=mydriver.sys
icacls %NAME% /save C:\windows\temp\%NAME%.icacls
takeown /F %NAME%
icacls %NAME% /grant Everyone:F
move %NAME% %NAME%.bak
move instrumented_driver.sys %NAME%
icacls . /restore C:\windows\temp\%NAME%.icacls
Puis exécutez :
bcdedit /set recoveryenabled no
bcdedit /set nointegritychecks on
shutdown -t 0 -r
L'intégration avec WinAFL se fait en compilant un harnais à l'aide des en-têtes fournis.
En plus des en-têtes, il y a example.c, un programme d'exemple qui montre comment les utiliser.
Les en-têtes fournis sont une légère modification des en-têtes déjà fournis par WinAFL pour intégrer un autre outil d'instrumentation statique de binaires appelé Syzygy.
La manière dont nous nous intégrons avec kAFL est assez simple.
Normalement, un harnais kAFL s'exécute sur une machine virtuelle et communique avec le frontend du fuzzer via des « hypercalls » spéciaux.
Ces hypercalls indiquent au fuzzer de faire de nombreuses choses, parmi lesquelles charger les données de couverture d'IntelPT et les analyser sous forme de bitmap AFL.
Parce que peafl64 rend le traçage IntelPT obsolète, nous devons préparer une méthode pour transmettre les données de couverture au fuzzer.
Par conséquent, nous avons étendu qemu et kvm avec des « hypercalls » qui permettent au harnais (en mode utilisateur) exécuté dans une VM d'envoyer les données de couverture qu'il a collectées via le pilote auxiliaire.
Ceci concerne spécifiquement la configuration sur ESXi, mais devrait être pertinent pour d'autres plateformes de virtualisation comme AWS.
La configuration est assez simple :
install.sh qemu, exécutez install.sh qemu_sbi