Freeflag - reverse

- 3 mins read

Freeflag

Difficulté : Facile
Catégorie : Reverse Engineering

Compréhension du programme

Avant toute chose, il est essentiel de comprendre le fonctionnement du programme ainsi que ce que nous devons modifier pour obtenir le flag.

Exécution du binaire

Lorsqu’on exécute le binaire, on observe qu’il affiche un caractère supplémentaire du flag à intervalle régulier. Le premier caractère s’affiche après une seconde, puis le temps est multiplié par 3 à chaque itération.

Dans le cadre d’un CTF limité à 7 heures, il aurait été impossible d’obtenir l’intégralité du flag à temps en laissant simplement tourner le programme en arrière-plan.

Objectif : contourner le mécanisme de temporisation afin d’accélérer l’affichage du flag.

Analyse statique du binaire

Après décompilation dans Ghidra, trois fonctions attirent mon attention dans le Symbol Tree :

  • main : la fonction principale contenant la logique du programme.
  • wait : probablement responsable du délai entre l’affichage des caractères.
  • decrypt_char : semble déchiffrer les caractères du flag.

Analyse de la fonction main

La fonction contient les caractères chiffrés du flag, qui sont ensuite déchiffrés un par un dans une boucle de 33 itérations (0x21 en hexadécimal). Cela correspond probablement à la longueur totale du flag.

Pour chaque itération :

  1. Le caractère est déchiffré via la fonction decrypt_char.
  2. Il est affiché.
  3. Un délai est introduit via la fonction wait.

La variable local_c est initialisée à 1 et est multipliée par 3 à chaque itération. Elle sert de base pour le temps d’attente.

Analyse de la fonction wait

La fonction wait utilise la valeur de local_c pour exécuter une boucle de temporisation. Chaque itération de cette boucle dure une seconde, ce qui allonge progressivement le délai total d’affichage.

Analyse de la fonction decrypt_char

Faire du reverse engineering complet de cette fonction aurait pu être une piste, mais ce n’est visiblement pas la méthode attendue pour résoudre le challenge.

Exploitation

Tentative 1 : Suppression de l’appel à wait

Une première approche consiste à supprimer l’appel à la fonction wait pour éliminer le délai entre l’affichage des caractères.

Avant patch :

Après patch :

Exécution :

Cependant, cette modification provoque un crash du programme. Elle ne permet donc pas de récupérer le flag.

Tentative 2 : Désactivation de la multiplication par 3

Plutôt que de supprimer l’appel à wait, on peut empêcher local_c d’être multipliée par 3 à chaque itération. Cela permet de maintenir un délai constant de 1 seconde par caractère.

Avant patch :

Après patch :

Exécution :

Le programme affiche désormais un caractère toutes les secondes, ce qui permet de récupérer le flag en un temps réduit.

Résultat

Flag : interiut{P4tCh1Ng_C4n_B3_uS3ful}

Conclusion

Le patch d’instructions est efficace dans certains challenges CTF, notamment lorsque le temps d’exécution est manipulé. Le contenu du flag confirme que cette approche était bien celle attendue par le créateur du challenge.