
Obfuscateur binaire x64 pour fichiers PE avec aplatissement du flux de contrôle, anti-désassemblage, obfuscation des importations et mutation d'instructions pour entraver l'ingénierie inverse.
Alcatraz est un obfuscateur binaire x64 capable d'obfusquer différents fichiers PE, notamment :
Installation : https://vcpkg.io/en/getting-started.html
asmjit : vcpkg.exe install asmjit:x64-windows
Zydis : vcpkg.exe install zydis:x64-windows
1.) Chargez un binaire en cliquant sur file en haut à gauche.
2.) Ajoutez des fonctions en développant l'arborescence Functions. (Vous pouvez rechercher en saisissant le nom dans la barre de recherche en haut.)
3.) Appuyez sur compile (note : l'obfuscation de nombreuses fonctions peut prendre quelques secondes).
Dans la démonstration suivante, toutes les fonctionnalités (sauf celle présentée) sont désactivées.
Si une valeur immédiate est déplacée dans un registre, nous l'obfusquons en appliquant plusieurs opérations binaires. Regardons la fonction populaire _security_init_cookie.
Avant :
Après :

En supprimant la structure de programme ordonnée générée par le compilateur et en plaçant notre code dans de nouveaux blocs générés, nous augmentons la complexité du programme. Prenons cette simple fonction main comme exemple (l'optimisation pour ce programme est désactivée) :

Si nous la passons dans IDA 7.6, le décompilateur l'optimisera :

Maintenant, aplatissons son flux de contrôle et laissons IDA l'analyser à nouveau :

Comme vous pouvez le voir, la complexité a considérablement augmenté même si je ne montre qu'une petite partie du code généré. Si vous voulez voir à quoi ressemble le graphe de flux de contrôle (CFG) :

Si un registre (par ex. RAX) est ajouté à un autre registre (par ex. RCX), nous allons muter l'instruction. Cela signifie que la syntaxe change mais pas la sémantique.
L'instruction ADD RCX, RAX peut être mutée en :
push rax
not rax
sub rcx, rax
pop rax
sub rcx, 1
Si vous voulez en savoir plus sur la mutation, jetez un œil à perses.
Si le fichier PE est un .exe (le support .dll sera ajouté), nous créerons un point d'entrée personnalisé qui déchiffre le vrai au démarrage (!!! ne fonctionne pas lorsqu'il est mappé manuellement).

L'obfuscation LEA est assez simple mais efficace. Nous déplaçons un emplacement différent dans le registre et le déchiffrons ensuite. Ainsi, les ingénieurs en rétro-ingénierie ne peuvent pas faire de références croisées à certaines données/fonctions.
Supposons que nous trouvions l'instruction suivante : lea rcx, [0xDEAD]
Nous allons la muter en :
pushf
lea rcx, [1CE54]
sub rcx, EFA7
popf
rcx -> 0xDEAD
Si nous trouvons une instruction qui commence par l'octet 0xFF, nous placerons un 0xEB devant.
Nous faisons cela car 0xEB 0xFF s'encode en jmp rip + 1 qui, finalement, saute vers notre premier 0xFF. Cela déroutera les outils qui décodent les instructions de manière linéaire.
Avant :

Après :

De temps en temps, nous pouvons insérer :
jz 3
jne 1
0xE8
IDA essaiera de décoder le 0xE8 (call) mais n'y parviendra pas :

Il n'y a pas d'obfuscation IAT « propre » pour le moment. L'astuce anti-désassemblage 0xFF s'en charge pour l'instant. Une implémentation correcte est prévue ici :
iat.cpp
Voici un extrait de notre fonction main avec tout sauf l'anti-désassemblage activé (afin qu'IDA puisse créer une fonction) :
