Seal’s Pwn Zero2Hero Stack Challenges - Ret2libc Canary
This was challenge #6 from Seal’s Pwn Zero2Hero.
A source file was provided for this challenge.
It’s a binary that prints the contents of user input and then asks for more input.
Vulnerabilities
There’s a format string vuln on line 17
. The printf should be printf("%s ", buffer);
There’s also a buffer overflow on line 21
.
It’s using gets()
which is a weak function and it lets us put in whatever input we want without checking the length of it.
Mitigations and Bypasses
This binary has a lot mitigations such as DEP, Full RELRO, PIE, a stack canary, and ASLR. To bypass these we will need to leak a libc address and the stack canary using the format sring vulnerability and then rop to call libc’s system function.
Exploitation
Leaking Data
Using this script we were able to leak out some addresses and the stack canary.
The stack canary was at the 9th index.
We can use GDB to see which addesses we leaked out belongs to libc. To do this I printed out offsets 1, 3, and 7.
It looks like offset 3 is a libc address. To confirm this I just used vmmap
in GDB and look for what range the address fell into.
The address belongs to the cmp instruction in __GI__libc_read
which is 18 bytes away from the start of the function.
We can get the libc base offset by substracting the leaked address from the libc base at runtime, which gives us 0x1147e2
. Now that we have the base address we can do a Ret2libc
Finding the Offset
Now we can look for the offset we need to overwrite the return address. We’ll need to use pwntools and gdb to do this because the stack canary will currrently prevent us from controling RIP.
First, we’ll need to parse the leak and save the libc address and the stack canary.
Next, we need to take a look at the stack. By examining the stack we can see that the canary is 0x18 (24) bytes from the start of our buffer.
We can confirm this by using a cyclic pattern and making sure that the canary is at the 24th byte. If everything is correct we shouldnt see the stack smashing error.
When we sent the pattern we got a normal segfault.
Now we can search for the pattern that is at RSP and get the offset which is 25.
This doesn’t account for the canary though so it’s really 25 + length(canary)
which is 33 since the canary is 8 bytes.
Now that we have control of the instrunction pointer, we can continue developing our exploit.
Exploit Development
To do the Ret2libc, we will need a pop rdi
gadget which we can get using ROPGadget this will pop the /bin/sh
string into the RDI
register so that it can be used as an argument for system. We may also need to use a ret
gadget if the stack gets misaligned.
We could grab the gadgets from the challenge binary, but that would involve using another leak to bypass PIE so instead we’ll rop using the libc.
To use these addresses we will need to add them to the libc base we found earlier.
Now we just need to grab the addresses of the /bin/sh
string and system()
which is easy since libc is now based correctly.
The stack gets misaligned when it gets to the pop rdi
gadget so we need to add a ret
gadget right before we use the pop gadget.
Solution
After all that running our script gives us a shell and the flag.