Souk (Reverse) - FCSC 2022
Principe:
Tester puis placer les caractères du flag en comptant les JMP pris
Le challenge
Mot de passe
Mot de passe ou flag?
Ici, j'ai remplacé les instructions de JMP avant cette string par des "nop": les jumps n'existant plus, ils ne seront pas pris et j'arriverai dans la suite de l'exécution
Cette première étape marche parfois différemment: en accédant à la partie après vérification du mot de passe, le challenge aurait pu déchiffrer le flag et nous le donner. Il est donc utile de faire toujours ce genre de vérification.
Brute force
Tout brute-forcer est impossible: 64 caractères, 16 possibilités par caractères, 64**16 combinaisons…
Un brute force caractère par caractère (64 * 16) est en revanche plausible
Char par char
D'ailleurs, on voit que le jump JE esquivant le "Bravo" est pris si DWORD RBP-0x38 vaut zéro, ce qui arrive si le jump précédemment trouvé JE 0x55...bd est pris: on peut postuler que si ce jump est pris, le caractère est mauvais
Par exemple, on a mis le flag FCSC{0...0}, et le JUMP a été non-pris 4 fois: c'est que le flag contient 4 "0", qui sont à la bonne place dans le flag mélangé (03 35 40 45), Mais comme le flag a été mélangé, on ignore leur position dans le flag d'origine
Master mind
Vous vous rappelez de ce jeu? Où il faut deviner la place de pions de couleurs sur une grille? On va un peu procéder pareil, mais de manière très simpliste, même si peu efficace
Breakpoints
L'ASLR sera remis au prochain reboot, donc, pas besoin de penser à le ré-activer. On peut aussi faire:
echo 0|sudo tee /proc/sys/kernel/randomize_va_space
Si c'était à refaire, je le ferai maintenant via gdb: j'écrirai un fichier du type:
b *0x555...\nr < flag-guess.txt et on compte le nombre d'arrêts
(c pour continue)
Un décalage progressif
Impossible de connaitre facilement la position des "bien placés" dans le flag d'origine car "Souk" a en fait mélangé les lettres du flag d'abord, et retrouver cet ordre me semblait…compliqué
Toutefois, je pense qu'on pouvais retrouver le mapping de ce mélange en entrant un flag où tous les caractères sont uniques, et en regardant dans quel ordres ils sont testés par le JUMP. Mais je n'ai pas appliqué cette piste
Pour ne pas polluer inutilement ma liste de "bien placéss", j'ai remplacé le FCSC{} par zzzzzz ce qui est forcément "mal placé"
A partir de la différence pos:0a 0f 12 41 (avant décalage) et pos:0a 12 41 44 (après décalage),
j'en déduis que pos:0f n'est plus bien placé, et que pos:44 est maintenant bien placé.
Or, pos:0f est un char:e et pos:44 est un char:7
Alors, je cherche un char:e qui est devenu autre chose ("bien placé" perdu),
et un char:X qui aurait changé pour être remplacé par un char:7 ("bien placé" gagné)
J'en déduis sont la valeur de 2 caractères du flag e et 7
On peut sans doute déduire plus d'informations à chaque décalage, mais bon, tant pis
Flag
Je pense que après l'expérience de ce CTF et du 404CTF, je ferai autrement: je scripterai gdb ./souk|tee scanme.log pour tester chacund des 64x16 caractères possibles, un à un. En comptant les JUMP pris/non pris dans la sortie de GDB, j'en aurai déduis si mon N-eme caractère est bon et j'aurai brute-forcé le flag char par char automatiquement
PS