ret2secret
Easy, 3 Solves
Last updated
Easy, 3 Solves
Last updated
This challenge is a standard "ret2win" challenge, it involves overwriting the stack buffer to overwrite the return pointer.
You are provided with a binary, and after checking the security parameters on the file.
The binary was compiled with no stack protections, and the architecture used is intel 32-bit little endian.
For the benefit of those who don't know what each protection does, here's a little breakdown.
RELRO (RELocation Read-Only)
When RELRO is enabled, the linker marks the relocation and symbol tables as read-only after they have been compiled. This prevents an attacker from modifying these tables during runtime.
Stack
The stack canary is used to detect buffer overflows by placing a random value between the buffer and return address on the stack, this is called the canary value. Before the function returns, the canary value is checked to see if it has been overwritten.
NX (No-Execute)
Memory regions are marked as non-executable by the processor during compilation, NX prevents code execution from the memory regions marked as non-executable. This prevents arbitrary code execution from memory corruption attacks.
PIE (Position Independent Executable)
PIE randomizes the base addresses of functions at each execution. This means that the initial load address of the binary is randomly selected during every run. This makes static analysis on a binary pretty useless as the exact memory location of every function changes during runtime.
RWX (Read-Write-Execute)
RWX is a permission set that determines whether a region of memory can read, written or executed from. Memory regions that are marked as non-executable can still be read and written to but will not be allowed to execute any code.
And, the binary stops executing here and exits normally. However, there's a hidden function that is never called.
And it looks like this is what we're trying to overwrite the return pointer to call to get the flag.
A quick google search shows that scanf
is a dangerous function that doesn't check input validation or boundary checking which allows a user to input a string that overflows the char buffer that it was given.
It seems like we have overwritten the buffer somewhere and crashed the program. We can now use a debugger to read the registers at the time of segfault.
I used pwndbg's cyclic to determine what part of a string overwrites the EIP (extended instruction pointer)
The EIP (Extended Instruction Pointer) was overflowed at the string "haaa" portion of the cyclic. EIP is a register that holds the memory address of the next instruction to be executed by the processor.
Anything that comes after the 28th byte is going to feed into the EIP which will tell the program which memory address to point to.
All we're left to do now is find the memory address of the secret function that we need to call.
The entry point for secret is located at "0x080491a6"
In the payload, this should be written as: "\x08\x04\x91\xa6" (hexadecimal).
However, remember the endianness mentioned earlier? The binary was compiled in 32-bit little endian, so the memory address should be represented as "\xa6\x91\x04\x08" because the bytes are reversed in little endian compared to big endian.
You can read more about endianness here.
The exploit can be generated using a python2 one-liner with:
python2 -c βprint βAβ * 28 + β\xa6\x91\x04\x08ββ > payload