Principe:
Jouer sur des JUMP (ou sur les registres) pour amener l'exécution d'un programme jusqu'au déchiffrement du flag, et forcer ce déchiffrement à continuer jusqu'à être complet
Le challenge
Le challenge demande
de lancer un programme (fichier dispo ici)
qui nous donnera le flag
Le zip ci-dessus est restreint aux fichiers utiles.
le reste est
dans mon archive complète du challenge
Le challenge nous prévient que le binaire peut crasher la machine.
On prendra donc soin de ne pas avoir de truc critique ouvert pendant ce challenge.
Explorons
D'abord, on va voir un peu ce que ce binaire contient… pas mal de protections
(donc probablement pas d'overflow) et une libc spécifique
Glibc
Commençons par aller récupérer glibc et compilons-le
On lance le "configure"
Et on installe les paquets manquants si besoin
Certains seront optionnels, on peut s'en passer
Le chemin
Au lancement, paf, plantage: la commande cd semble tronquée. Apparemment, les espaces
dans le chemin du challenge ne plaisent pas
On renomme le dossier, et on recommence
Ca build
Et c'est installé: on va pouvoir lancer le programme
J'ai préférer compiler glibc car au vu du nom du challenge ("fourchettes", soit "fork" en anglais),
je ne serai pas étonné que le fork des process dans la libc soit utilisé. La compiler pourra permettre
de hooker des choses si besoin
Lancement
On lance et… c'est assez étrange comme comportement! On stoppe (ctrl+c)
En regardant ps je vois que l'ID du process est monstrueux! Fourchette semble
donc générer des millions de forks de lui-même…
edb
En lançant le programme dans edb et en défilant instruction par instruction,
on s'approche du Echec
On va faire une première tentative, et mettre en nop toutes les instructions précédentes
pour prendre le JUMP qui nous permettra d'éviter ce Eched
Le JUMP est pris et on arrive près d'un "Succ"
(sous-entendu Succès mais l'accent tronque l'affichage d'edb)
On pouvait aussi ne pas mettre de nop et forcer manuellement le flot à prendre le JUMP
via le clic droit
Et l'appli segfault alors
C'est moi le chef!
On recommence l'exécution, et je vais tenter de forcer le programme à ignorer les différents
checks qu'il tente de faire, pour le forcer à me cracher son flag
Comme les fork n'arrêtent pas de générer des signaux (SIGCHLD), je décide de les ignorer tous
Arrivé à un premier JUMP, que le flot devrait prendre, je décide le contraire: le JUMP ne sera pas pris!
Le JUMP ignoré (cf les options dans le clic droit), l'exécution continue selon mon bon gré
Un second JUMP existe, et je l'ignore de nouveau (sinon, il m'emmènera au Echec )
Je poursuis l'exécution, croisant un peu les doigts quand même
Encore un JUMP, qui ne devrait pas être pris cette fois-là et que je force donc à prendre
(sinon, on finirait sur le Echec là encore)
On arrive alors au bout de ce qui ressemble aux checks du programme,
on peut continuer l'exécution d'une traite
Et… Le message semble un peu saboté, et potentiellement, je me fais troller
"T'as cru" est lisible, ce qui laisse à penser que le challenge nous troll un peu, mais
des morceaux de flag semblent lisibles j3S_…tKs_…h?}
Changer les registres
On va donc refaire de même, et prendre les JUMPs qui nous intéresse (ou esquiver les mauvais)
mais cette fois, en changeant à la volée les valeurs dans les registres
On met donc 0 dans ce registre RAX, car sa valeur ira dans RBP-0x24
qui sera ensuite comparée à 0
La comparaison renvoie TRUE et le JNE (JUMP NOT EQUAL) n'est donc pas pris
On procède de même soit en modifiant les autres registres,
soit en modifiant directement les valeurs en mémoire
On aligne la mémoire aux registres pour le dernier JUMP
Ce qui permet de ne pas le prendre, ce JUMP
Et on prendra bien, en revanche, le dernier JUMP
Et on se fait troller sec!
À troll, troll et demi
En relançant l'exécution et en procédant de même,
j'ai repéré un bloc de code manipulant des textes et,
dans la mémoire associée, on retrouve le début du T'as cru
Je fais alors défiler, ignorant les JUMP pour rester dans ce bloc de code, et un 404 apparait
En continuant ce forcing, le flag se dessine
Jusqu'à ce qu'il soit complètement lisible!
En modifiant le caractère 0x00 pour un espace 0x20
On a même le flag qui est affiché dans la sortie (c'est plus pratique pour le copier/coller):
404CTF{SyMp4_l3S_f0rKs_N0n?}
J'ai patché un peu le fichier binaire au cours de cette exploration, pour inverser certains jumps
et on supprimer d'autres. Cela évite de refaire manuellement ce processus à chaque exécution.
⇇ 404CTF 2022