Its been a while since my last update in this blog, I finally have some time to make another write up of pwn CTF challenge.
Thanks to my classmate Christos for sharing this challenge, I hope this blog can help you to understand how to approach this challenge.
The challenge was named BabyStack. It was a 64 bit ELF executable and it's expected us to change the flow of program execution in order to spit out the flag
At first, if you try to run the app it will show read() open error function this indicates that this binary needs to have some additional file in order to run properly.
Since this is a CTF challenge I just try to create like a dummy file called flag to see if this the correct file to be prepared.
It turns out it was a correct file and we can see that the binary give us two input first is the "size" and the "data"
next, let's try to load the binary to ghidra so we have more detail information about the binary. Examining the pseudocode we could determine that the program use "size" to determine how big is the size of the input "data"
this is certainly a good sign for an attacker since we can control how big is the space of our input we can overflow the stack of the program to gain control of the execution flow
But notice before the program give us two previous prompts it called function init(). let's have a quick look at what is happening inside the function init()
I think it is pretty straightforward, this function was used to get the content of the "flag" file that we just created and if the file does not exist it will show an error that we just saw at the first time we run the program
let's load the program in gdb-peda to debug the program and see if we got anything interesting
as you can see I try to allocate 100 bytes in the memory and insert a long string pattern to see if it caused any segmentation fault.
If we take a look at the crashed register in order to overwrite the RIP register we need to supply 40 bytes of data
The next question will be how do we able to obtain the flag inside the program?
still, remember the init() function that loads the flag file?
practically any program that loads a file and retrieves the content will be stored in the memory of the program. We can check this by putting a breakpoint at open() function and read() function in init() function
run the program and try to take a look at the argument passing in each of the functions
at the first breakpoint we can see that it passed the "./flag" string file to the open function
next at the second breakpoint, we can see that the loaded file "flag" content will be stored at 0x6010c0
we can check this location manually using this command:
so we know the location of the "flag" content knows its time to create the exploit.
we need to construct a ROP gadget since NX protection is on and we want to chain it with puts() function located in 0x400700
also, we need to have the required gadget to load the parameter to the puts() function we can use ROPgadget tools
from the result, we got a suitable gadget which is pop rdi; ret. remember rdi register is considered as the first parameter.
from all of this information, we can create the following exploit like the above and once we run it we got the flag :)
That's all guys I hope you enjoy this blog and if there is something that I missed leave a comment below
Comments
Post a Comment