Patchwork (Exp. Binaires) - 404CTF 2022

Patchwork (Exp. Binaires) - 404CTF 2022

Fichiers du challenge Principe:
Exploiter un overflow via ret2libc pour obtenir un shell et lire le flag

Le challenge

Le challenge nous demande de trouver les bonnes entrées d'un binaire (dispo ici) pour accéder au flag

Exploration

On lance le binaire dans edb et on regarde un peu ce qui se passe: on doit d'abord donner notre "profession"

Profession

En avançant dans l'exécution, on trouve facilement la valeur attendue: scientifique

C'est raccord avec l'énoncé du challenge, qui dit qu'Hallebarde veut entrer en contact avec des scientifiques français

On essaie cette valeur…
Et ça passe: l'exécution continue

Seconde entrée

On nous demande ensuite une seconde entrée, qui, là, semble toujours acceptée: peut-être est-ce l'entrée vulnérable (à un overflow)?

Checksec

On vérifie d'abord quelles sécurités sont actives sur le binaire: NX, donc la stack ne sera pas exécutable

Overflow

On essaie un long input…
…et on obtient un segfault: on a trouvé un oveflow
Comme d'habitude, on cherche l'emplacement de l'EIP dans notre payload, et on le "marque" (ici, avec ZXXXXXXY histoire d'avoir explicitement l'endian)

Confirmation du NX

Pour la curiosité, je change cette valeur à la volée pour un emplacement dans la stack (…5e60)
L'EIP est bien suivi…
…et on a une exception car la stack n'est pas exécutable, vu que NX (no execute) est actif

ret2libc

Comme la stack n'est pas exécutable, un ret2libc serait envisageable

C'est d'autant plus crédible que le challenge nous fournit une libc!

gdb-peda

Pour faciliter les choses, on va installer une petite extension de GDB qui nous aidera: gdb-peda
Ca a foiré au premier coup (et on appréciera ma joie d'utiliser Python)
On trouve une proposition de solution d'une très grande finesse et subtilité
Et cela finit par marcher

System

On cherche d'abord l'adresse de la commande system (syscall 0x7ffff7e0b860) et de exit (0x7ffff7e01100) pour faire propre
On la prendra en note, et on testera deux fois, histoire de voir s'il n'y a pas de random qui traine

/bin/bash

On cherche ensuite l'adresse de /bin/bash histoire de pouvoir ouvrir un shell et on l'inject dans le payload

Dans la stack, il nous faudra, dans l'ordre, syscall ; exit ; /bin/bash

Un test intermédiaire
On teste et ca passe plutôt bien: un process enfant est lancé (le shell)
On script ce test, mais impossible d'obtenir réellement un shell pour l'instant
64 bits
Je tombe alors sur un autre writeup du PicoCTF: en 64bits, il manque un tuc!
En pratique, il nous faut un POP RDI avant notre payload

POP RDI

On le cherche donc via ROPGadget et on garde l'adresse de côté
Ce qui nous permet de mettre notre script à jour

Vous savez quoi? Pour une fois, on va le faire en Python (car le package pwn va nous faciliter la vie)

On lance et… wow, ça marche! Shell obtenu en local!
Je décide donc, histoire d'apprendre des choses, de reproduire toutes les étapes manuelle précédentes en automatique, dans ce script
Je relance, et ça fonctionne de nouveau en local!

Et arriva le serveur…

Mais en essayant avec le challenge en ligne, c'est l'échec critique et le foirage total :c

Comme j'ai tout automatisé dans le script, j'ai bien pensé à changer le chemin vers la libc à utilliser, le challenge se servant de la libc qu'il fournit

Ubuntu "ret"

En continuant la lecture de l'article, je m'aperçois que le même problème avait été rencontré par la personne à cause d'Ubuntu
On cherche donc un ret pour réaligner la stack
J'en prends un au pif, je reteste et… nope!
Je refait un test local, ça marche…

Leak the libc

En reprenant l'article, il s'avère que l'adresse de base de la libc est manquante! En effet, jusqu'ici, je me basais sur celle de ma machine, mais ce n'est pas nécessairement celle du serveur (surtout avec des versions différentes)

On va donc modifier le script pour leaker cette addresse de base, puis retourner au main

Avez-vous notez que j'ai oublié de mettre le chemin de la libc à jour?

Une étourderie

Je lance et… fail!
En local pourtant, ça marche bien
Mais pas en ligne
Je m'aperçois alors que j'avais commenté le pop_ret! Je décommente, recommence, et foirage partiel

Foirage "partiel" car j'ai quand même une erreur du shell qui me dit qu'une commande est introuvable. Donc, d'une manière ou d'une autre, j'ai pu exécuter une commande. Reste à exécuter la bonne

Une autre étourderie

Je tente alors avec une autre commande, /sh
Et je m'aperçois alors que la version de ma libc n'est pas correcte!
Une fois la bonne version utilisée, ça se passe mieux, et le flag est lisible:
404CTF{C3_r3CrU73M3N7_N357_P45_53CUr153!}

Fichiers du challenge

↩ Retour à la liste des challenges

⇇ Retour à l'accueil