PWN5 : csictf 2020 smash solution

Hello guys, this write-up for the PWN challenge named smash, and the binary named "hello".
As usual if you don't have the binary and libc downloaded, you will find them here (the full exploit too):
https://github.com/MaherAzzouzi/PWNing/tree/master/csictf

Let's go !

File :


* we're dealing with a 32 bits binary
* the binary is not stripped (make this binary easy to reverse engineer using any tool you like, for me I will be using ghidra)

Checksec :


* No PIE (we know the addresses of the binary)
* NX enabled (we can't think of shellcode)
* No canary make stack overflow easy.


Reverse engineering :

Open up ghidra, click create new project name it "smash" and import hello file.
Click analyze and wait for some seconds...
Filter for main and see what happened inside !


This is the main function all it does is :
* Read one character at a time and store it in the heap
* Then call say_hello() function using the data we provide.

Let's decompile say_hello() function :


It's easier than main, and here we can see the vulnerability:
* Use strcpy in a buffer of 128 bytes as source and our unlimited data as source.
Stack overflow !

Now we know that we can use the stack overflow to execute our ROP chain.

Let's see all functions we can jump to and use :
Open gdb and type "info func" and press "enter"


I will be using puts@plt.

Plan :

Here is the plan :

1) Find the offset to the return pointer (everyone has a method of doing this I'm gonna show mine)
2) Craft a simple ROP chain that leak the a libc address (leaks the content of malloc@got for example)
3) Return to main again, to restart the binary and get a fresh stack overflow
4) Craft a simple ROP chain that calls system("/bin/sh")

Exploit :

Now comes the exploit :

Let's find the offset first :

F







Now the ebp register begins at offset of 132 and we're dealing with 32 bits binary, so the final offset is 132+4 = 136

Now comes the part where I want to leak a libc address.
As you may now the GOT is full of them, you can choose an address and call puts to leak it 


I'm gonna choose to leak malloc.

Now how to call puts(malloc@got) or puts(0x804a020) ??
We have the offset now, our ROP chain will look like this (please remember that we're dealing with 32 bits binary the arguments to functions are passed in the stack not in registers like RDI or RSI):

"M"*136             | Just padding
puts@plt             | Address of puts 
main_address     | When puts finish it will return to this (main) and that what we want
malloc@got       |  Arguments to puts starts from here (because puts() expect one argument this is the                                 only one we will give)

This is the part of the exploit that leak malloc address :



Let's test it locally :


As you can see, the line just before "what's you name ?" is full of addresses from the GOT and puts stops when it hits a NULL character or \x00

And you can see that we have another iteration of main.

This is the code that capture just the malloc address, and calculate the libc base address :


Let's test it :


We now know the libc base address and we have another chance to do stack overflow :
What our ROP chain will look now is this :

"M" * 136             | Just padding
system                    | We have leak it's easy now to deduce system address
"MMMM"            | We don't want to return to anything now just pop a shell (just make some padding of                                     4 characters)
address to /bin/sh | Argument to system

This is the last part of the exploit :


Now let's run the exploit :

And that's all :)


Comments