> m4rt@CTF_ARCHIVE:~$

// ATTACHMENTS

Hack The Box / Cyber Apocalypse CTF 2026 / 2026-07-29

The Corroded Crown (pwn)

Exploit a use-after-free vulnerability to leak a libc address, then perform tcache poisoning to overwrite __malloc_hook with the address of a shellcode on the stack, and finally execute the shellcode to get a shell.

We are given a zip file:

unzip -l the_corroded_crown.zip
Archive:  the_corroded_crown.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2026-05-09 04:01   challenge/
    15312  2026-05-09 04:01   challenge/corroded_crown
        0  2026-05-09 04:01   challenge/glibc/
  2029592  2026-05-09 04:01   challenge/glibc/libc.so.6
   191504  2026-05-09 04:01   challenge/glibc/ld-linux-x86-64.so.2
---------                     -------
  2236408                     5 files
file corroded_crown
corroded_crown: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter ./glibc/ld-linux-x86-64.so.2, BuildID[sha1]=41ca0dbfab753505915afb78ebf357ab3616531e, not stripped

Let's check also the libc version:

strings glibc/libc.so.6 | grep GNU
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.17) stable release version 2.31.

Let's load the binary corroded_crown in Ghidra and analyze it.

We can see that the binary is a menu-driven program that allows us to forge, inscribe, inspect, and destroy relics. The program uses dynamic memory allocation (malloc/free) to manage the relics.

Relics are basically struct with three field: - a pointer to a heap allocated buffer - a size field - a int that indicates if the relic is forged (and not destroyed) or not.

There is a use after free vulnerability. After we destroy a relic, we can still inspect the relic and read the content of the freed heap memory.

This allows us to firstly leak a libc address. We forge 8 relics of size 0x290, then we destroy all relics in reverse order. We inspect the first relic and leak the libc address from the freed chunk.

With this leak, we can compute the base address of libc.

There is also another vulnerability. The function inscribe_relic does not check if the relic is forged or not. This allows us to write to a freed chunk. We can use this to perform tcache poisoning.

Let's check the protections of the binary:

checksec corroded_crown
    Arch:       amd64-64-little
    RELRO:      Full RELRO
    Stack:      Canary found
    NX:         NX unknown - GNU_STACK missing
    PIE:        PIE enabled
    Stack:      Executable
    RWX:        Has RWX segments
    RUNPATH:    b'./glibc/'
    Stripped:   No

So the stack is executable, which is very interesting.

The idea now is to leak a stack address. We can do this using the libc variable environ, which points to a cell containing the address of the environment variables on the stack.

We can write the environ address to the freed relic 1. Then we forge two relics and malloc will return the address of the cell pointed by environ. We can then inspect the relic and leak the stack address.

Now we can perform two tcache poisoning attacks. In the first one, we overwrite the environment variables portion of the stack with a shellcode. In the second one, we overwrite the __malloc_hook with the stack address of the shellcode.

After that, when we forge another relic, malloc is called, so __malloc_hook is called, and the shellcode is executed.

See the script sol.py for the full exploit.

See the file shellcode_64.asm for the source code of the shellcode.