groppling-hook
Category: Pwn
Description
Gropple to safety?
nc tjc.tf 31080
Attachments: main.c, out, Dockerfile
Write-up
From the provided files, it appears that the Dockerfile
does not contain any particularly interesting information, and the out
file seems to be the compiled version of main.c
.
This is the file
output of out
:
Text Only | |
---|---|
And this is the checksec
output of out
:
Text Only | |
---|---|
Let's focus on examining main.c
:
In the main()
function, we can observe that it executes pwnable()
, which reads user input, performs some assembly instructions, and then returns to main()
. It seems that our ultimate goal is to call win()
, but the normal execution flow does not reach that point.
Upon closer inspection of the pwnable()
function, we can identify a stack overflow vulnerability. It allows reading up to 56
bytes, while the buffer can only hold a maximum of 10
bytes.
If we analyze the assembly instructions that are executed before pwnable()
returns, we notice that it checks our return address and redirects to laugh()
if our return address falls outside the range of 0x0401262
to 0x040128a
. Therefore, our return address must be within that range. In Ghidra, we can see that this range covers the entire main()
function.
Considering that the main()
function contains a ret
instruction, which essentially performs "pop rip" followed by "jmp rip", we can make pwnable()
return to 0x040128a
, and the ret
instruction at 0x040128a
will return to win()
at 0x004011b3
.
Thus, our input should consist of:
1. 18
bytes of nops
to overflow the entire buffer and overwrite the saved rbp
.
2. The address 0x040128a
, which corresponds to the ret
instruction in main()
where pwnable()
will return to.
3. The address 0x004011b3
, which marks the beginning of win()
and is the location where the ret
instruction in main()
will return to.
The above input has been written as a pwntool script, which can be found here.
When running the script, we obtain our flag:
Flag: tjctf{this_i#-my-questsss}