Principe:
Forger un syscall dans un bufferoverflow pour contourner la protection NX
Infos (cf menu latéral):
🚩 Flaggué! +316 points gagnés —
💾 Téléchargez les fichiers du challenge
FCSC{e3752da07f2c9e3a0f9ad69679792e5a8d53ba717a2652e29fb975fcf36f9258}
Le challenge
Overflow
edb et celui-ci nous renvoie une addresse (qui change)On tente donc un overflow avec une longue entrée
Ne tenez pas compte du "whoami" et "exit", ce sont des essais random précédents.
RET…
NX: "No Execute", flag Linux interdisant l'exécution de code depuis la stack (l'équivalent Windows serait le DEP, Data Execution prevention)
Impossible donc d'utiliser l'overflow pour changer l'EIP/RIP (RIP = EIP 64 bits) et le faire pointer sur un payload sur la stack
On s'aperçoit qu'on est aussi en "Full RELRO", mais puisque le programme nous leak gentillement une adresse, on devrait pouvoir s'en servir pour retomber sur nos pattes.
Gadget chain
syscall
MOV $0x3b, %rax
POP RAX qu'on a trouvé
Ab6Ab7Ab)
3b
3b dans le registre RAXlea str_addr, %rdi
POP RDI
/bin/bash (la commande qu'on souhaite exécuter via syscall) dans la stack (un peu n'importe où), et faire pointer l'élément suivant de la stack dessus (à la main)
/bin/bashmov $0, %rsi
Les screen n'ayant pas été prises dans la même exécution, les adresses ont changé, mais le principe reste le même
mov $0, %rdx
POP RDX
POP RDX, et on met 0 dans la stack
RDX=0syscall
syscall à la main
syscall
Assemblage
baseAddr), on calcule les adresses vers lesquelles on doit pointer, et on construit notre payload
Le $payload est donc constitué de:
- quelques caractères bidons pour l'overflow
- l'adresse trouvée permettant, une fois le RET atteint, d'avoir RSI = 0
- l'adresse POP RAX
- la valeur qui sera mise dans RAX (0)
- l'addresse de POP RDI
- la valeur qu'on va mettre dans RDI (basée sur l'offset de la stack)
- l'adresse du POP RDX
- la valeur à mettre dans RDX
- l'adresse du syscall
- quelques caractères bidon (de la marge, dont on pourrait éventuellement se passer)
- la commande à exécuter (/bin/bash)
- d'autres caractères bidons (de la marge encore)
On pourrait se passer des caractères bidons de "marge", mais cela obligerait à recalculer les offsets et pourrait, parfois, amener d'autres changement de comportement. Donc, je les ai conservés.
Livraison
Comme d'habitude, ma plus grosse galère consiste à livrer le payload.
cat|./program (à gauche) et laisser un script PHP tourner (à droite) pour livrer le payload: le shell apparait alors (à gauche)
Le script PHP attend qu'on lui copie/colle l'adresse donnée par le programme, puis il cherche le programme dans les process en cours, et lui envoie le payload.
On pourrait sans doute faire plus élégant, mais bon…
Flag
Apparemment, certains ont utilisé l'approche ret2libc mais bon, je trouvais celle-ci plus adéquate, puisqu'elle exploite un bout du binaire gentillement laissé ici par les organisateurs du CTF!
Flag: FCSC{e3752da07f2c9e3a0f9ad69679792e5a8d53ba717a2652e29fb975fcf36f9258}