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!}