Sthack 2022 — Pwn, Reverse Write-Ups

Dans la nuit du 20 au 21 mai 2022, s’est déroulé le CTF de la Sthack. Notre équipe a fini 9ème au classement général sur 18 équipes.

Pour ce write-up, je vous expliquerai comment j’ai pu résoudre l’unique challenge pwn ainsi que deux challenges de reverse proposé durant le CTF.

Reverse — JeanLouis

En ouvrant le binaire dans Ghidra et après avoir renommé les variables, on tombe sur une sorte de boucle qui réalise un memcpy like. Cette boucle copie un shellcode dans une variable qui sera ensuite XORé avec une clé statique plus loin dans le programme.

Figure 1: Copie du shellcode et XOR de celui-ci.

Pour comprendre les instructions exécutées, il suffit de prendre le shellcode hardcodé, le XORer et récupérer la valeur hexa (comme présenté dans le code ci-dessus). La valeur hexa peut ensuite être envoyé sur un site comme defuse.ca pour retrouver les instructions.

Une fois les instructions en notre possession, nous pouvons les placer dans un fichier afin de les compiler :

Une fois compilé à l’aide de la commande nasm -f elf32 shellcode.asm -o shellcode.o && ld -i elf_i386 shellcode.o -o shellcode. Le binaire généré peut être envoyé dans Ghidra pour comprendre ce qu’il fait.

Bien évidemment la condition saute aux yeux et permet de récupérer le flag.

Figure 2: Condition de vérification du flag.

flag: STHACK{Yeyeye33}

Reverse — ghozt

Ce challenge propose un binaire ARM. L’ARM est un langage que je ne connais pas très bien. Donc, après avoir découvert la fonction qui permet de faire la vérification du flag, j’ai décidé de le bruteforcer. Je ne voulais pas reverse la fonction permettant de faire le calcul sur la chaîne passée en argument, j’aurais sans aucun doute passé trop de temps à essayer de la comprendre.

Pour son fonctionnement, dans un premier temps, le binaire récupère notre entrée, affiche quelques messages et encode notre input.

Figure 1: Read, Puts, Encode.

Une fois ces actions effectuées, le flag encodé est placé sur la stack et comparé avec notre input caractère par caractère.

Figure 2: Set encoded flag et check du flag avec notre input.

Si on regarde le code assembleur de cette fonction on remarque l’instruction cmp r2,r3 qui compare deux registres entre eux. Je vais pouvoir lancer un gdb-multiarch et placer un breakpoint sur cette instruction pour checker à chaque fois les deux registres qui correspondent à un caractère de mon input et du flag.

Figure 3: Code assembleur de la boucle de vérification.

Bruteforce goes brrrrrrrrrrrrrrru

Pour le bruteforce, je vais lancer dans un terminal le binaire avec qemu et je vais lui passer le flag -g qui permet de debug le binaire en remote.

Maintenant, il ne reste plus qu’à boucler caractère par caractère et vérifier la sortie de gdb pour s’assurer que les registres sont égaux.

Voici le code python :

Pour chaque caractère le programme, va lancer la commande gdb-multiarch, se connecter sur le binaire taget remote:8090 placer un breakpoint sur 0x000107cc continuer l’exécution du programme tant qu’on connait le caractère et lorsque qu’on ne le connait pas on regarde la valeur des deux registres i r pour enfin faire notre comparaison et quitter q.

Petit à petit le flag se dessine sur notre terminal.

Pour obtenir :

flag: STHARMK{th1s_1s_t00_3asy_F0R_M3}

Pwn

Ce challenge propose un binaire dans un docker qui contient quelques fichiers .pw . Les fichiers .pw ont l’air de contenir les mots de passe des utilisateurs. Le nom du fichier lui a l’air d’être le nom de l’utilisateur à qui appartient le mot de passe.

Une fois le binaire récupéré sur notre poste, on peut l’ouvrir dans Ghidra pour comprendre son fonctionnement.

Dans un premier temps, le binaire va récupérer notre choix puis va exécuter une fonction dynamique en fonction de cela.

Figure 1: Choix de l’utilisateur.

La liste des fonctions est la suivante :

Figure 2: Liste des fonctions possibles en fonction du choix.

Path to flag

En regardant de plus près la fonction choice_auth, on remarque qu’il va regarder si des utilisateurs ont été enregistrés dans le programme, si c’est le cas, alors le programme demande un nom d’utilisateur et un mot de passe. Il vérifie ensuite les identifiants avec ceux du compte admin. Si les identifiants sont bons alors le flag est affiché sinon un message d’erreur est affiché.

Figure 3: Code de la fonction choice_auth.

Le fichier contenant le mot de passe du compte admin et guest étant lisible il n’y a rien de plus simple pour arriver jusqu’au flag.

Il suffit de se laisser guider par le programme.

Je ne pense pas que ce soit comme ça qu’il fallût résoudre ce challenge. Typiquement au vu du mot de passe admin cela aurait du ressembler à un Use After Free.

flag: ri3n_n3_Se_P4s5e_C0mm3_pRevU

Contactez-moi :
Site Web personnel
Twitter de l’équipe : LesPiresHat

--

--

French CTF team

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store