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 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-leOn lance le "configure"Et on installe les paquets manquants si besoinCertains 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 pasOn renomme le dossier, et on recommenceCa buildEt 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 EchecOn 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 EchedLe 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 flagComme les fork n'arrêtent pas de générer des signaux (SIGCHLD), je décide de les ignorer tousArrivé à 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êmeEncore 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 traiteEt… 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 registresOn met donc 0 dans ce registre RAX, car sa valeur ira dans RBP-0x24 qui sera ensuite comparée à 0La comparaison renvoie TRUE et le JNE (JUMP NOT EQUAL) n'est donc pas prisOn procède de même soit en modifiant les autres registres, soit en modifiant directement les valeurs en mémoireOn aligne la mémoire aux registres pour le dernier JUMPCe qui permet de ne pas le prendre, ce JUMPEt on prendra bien, en revanche, le dernier JUMPEt 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 cruJe fais alors défiler, ignorant les JUMP pour rester dans ce bloc de code, et un 404 apparaitEn continuant ce forcing, le flag se dessineJusqu'à ce qu'il soit complètement lisible!En modifiant le caractère 0x00 pour un espace 0x20On a même le flag qui est affiché dans la sortie (c'est plus pratique pour le copier/coller)
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.