HTB Cyber Apocalypse 2023: Void
The room goes dark and all you can see is a damaged terminal. Hack into it to restore the power and find your way out.
Last updated
The room goes dark and all you can see is a damaged terminal. Hack into it to restore the power and find your way out.
Last updated
Simple GOT overwrite with one_gadget via a write-what-where gadget.
Void is a simple binary that takes in user input and terminates right after that.
The binary does not come with a canary and PIE, meaning we would require only a LIBC info leak if we were to perform an ROP-based attack.
On the other hand, Partial RELRO indicates that we may be able to overwrite the Global Offset Table (GOT). However, there is only a single entry of read@GLIBC
in the GOT, and nothing interesting like puts()
or write()
that we can use to leak the LIBC address.
The binary has an obvious buffer overflow in the vuln
function. But other than that, the binary is very minimal, containing only a read()
function, and nothing else; not even a ret2win function. This is a very typical textbook scenario for ret2dlresolve attack.
Since the binary is a 64-bit program, there are known issues with exploiting ret2dlresolve with huge page sizes as described in this redpwnCTF 2021 writeup.
Inspecting the available ROP gadgets shows that there is a write-what-where
gadget that is well-known in GCC-compiled binaries. If we can control both ebx
and rbp
values, we can leverage this gadget to overwrite the GOT.
NOTE: Ropper uses the Intel-syntax flavor, so ebx
corresponds to WHAT; whereas rbp
corresponds to WHERE. At the same time, rbp
needs to account for the -0x48.
Luckily for us, pop rbp
and pop rbx
are both present in the binary as well. This means that we can now overwrite the read@GLIBC
entry in the GOT with something like system()
and pop a shell via /bin/sh
as the same as this writeup.
Ropper limits the maximum count of instructions in a gadget to 6 by default. Turns out there's a better gadget to pop all 6 registers at once altogether. This option can be overridden via the --inst-count
flag.
Alternatively, we can also overwrite the GOT with a one_gadget. We can satisfy all the constraints for the first one_gadget since we have the pop r12, pop r13, pop r14, pop r15
gadget at our disposal as well.
With ASLR disabled, we can calculate the actual address of the one_gadget by adding its offset to the base address of LIBC.
Flag: HTB{r3s0lv3_th3_d4rkn355}