Renverse la tour 1/2 (Reverse) - 404CTF 2022

Renverse la tour 1/2 (Reverse) - 404CTF 2022

Fichiers du challenge Principe:
Brute-forcer (même s'il y a plus subtil) les entrées de 3 étapes de chiffrement pour retrouver le mot de passe original

Le challenge

Il va falloir retrouver un mot de passe "ultra secret" à partir d'un script python (dispo ici)

Essayons

Essayons d'abord ce script avec un mot de passe bidon: lexluthorCORP

N'hésitez pas à ajouter des print un peu partout pour débogguer facilement le script (même si un vrai débogger serait mieux mais bon)

Ayez un IOC bien à vous (comme "lexluthor") et utilisez-le dans tous les cas de ce style. Ainsi, vous vous habituerez à ce "token", et vous saurez l'identifier au fil des mois/ans dans des dumps, des registres mémoire, etc.

Prenez un IOC qui n'ait que très peu de risques d'apparaitre quelque part et qui soit assez long: "chat" serait trop court et trop courant, "kruxx" sera trop court, et "cybersecurite" est un terme trop courant.

En essayant un mot de passe court, puis de plus en plus long, on voit que le script ne fait pas juste une substition de caractères

On voit qu'un pattern "UlÔ" est commun aux essais 1 et 3, mais on ne va pas vraiment plus loin. Il semble donc difficile de ne pas reverse le script entièrement

Reverse

Tour 3

Le mot de passe est "malaxé" par 3 morceaux de script avant d'être comparé à un résultat attendu: on va donc devoir reverse en partant de la fin, du "Tour 3"

Dans l'algorithme de mélange, on s'aperçoit que le dernier caractère du "password" (c'est à dire de ce qui sortira du tour2) influencera le dernier caractère de "mdp" (la sortie). On connaît la sortie en question, on va donc benêtement brute-forcer le dernier caractère, puis remonter un à un.

On trouve le dernier caractère
Puis on remonte
Et on se retrouve avec 34 caractères ASCII qui forment le "password", c'est à dire l'entrée du tour 3 (et la sortie du tour 2)
On fait une petite vérification en forçant le "password" à la valeur trouvée (quelque soit l'entrée de l'input) et on confirme qu'on a juste

Tour 2

On pourrait s'amuser à reverse le tour 2… mais c'est chiant:
on va se contenter de brute-forcer caractère par caractère

Au regard de l'algo, on voit que pour 1 caractère de "password" (l'entrée du tour 2), on aura deux élément rajoutés à "new" (la sortie du tour 2). On sait donc que le "password" fait 2 fois moins de caractères que "new". D'après notre tour3, "new" fait 34 caractères donc "password" en fait ici 17 (de 0 à 16)

Le brute-force caractère par caractère (en partant du début cette fois) marchera car le 2*i-eme caractère de "new" est définiti uniquement par le i-eme caractère de "password", au regard de la ligne new.append(password[password.index(password[i])])

Le brute force est vite fait et on a 17 caractères trouvés
De même que précédemment, en forçant la valeur de "password" à ces 17 caractères, on obtient un "bravo", ce qui confirme qu'on a la bonne entrée du tour2

Tour 1

Le tour 1 n'est en fait qu'une conversion ASCII -> int (via ord) précédé par l'inverse de l'inverse de l'inverse ([::-1]) de la string. Donc, aisé à reverse.

Il suffit donc de transformer notre "password" en ASCII et de l'inverser (lecture de droite à gauche)
On vérifie, avec le challenge original, qu'on a le bon flag et on confirme donc notre réussite:
404CTF{P4sS1R0bUst3Qu3C4}

C'est un des rares challenges que j'ai donc "réellement" reverse (même si une bonne partie consiste à faire de la force brute caractère par caractère, sans grande subtilité)

Fichiers du challenge

↩ Retour à la liste des challenges

⇇ Retour à l'accueil