H
Kembali ke Works
Writeup

Write-Up: RTR II — Cyber Competition 2026 (CTF Mode)

RTR II - Cyber Competition 2026 (Satsiber TNI)
ctfteamwebpwnreversecryptoforensics
Write-Up: RTR II — Cyber Competition 2026 (CTF Mode)

Writeup tim (Matlee Arya Sadewa, Achmad Kamal, Huga Hazimulfikri Nawawi) — 10 challenge berhasil diselesaikan dari 5 kategori: reverse engineering, cryptography, binary exploitation, digital forensics, dan web exploitation.

RTR II — Cyber Competition 2026 · Writeup

Rise The Ranger II — Cyber Competition 2026 Platform: ctf-risetheranger.satsiber-tni.mil.id · Format flag: RTRTNI26{...}

Anggota Tim

Nama
Matlee Arya Sadewa
Achmad Kamal
Huga Hazimulfikri Nawawi

Ringkasan

10 challenge berhasil diselesaikan dari 6 kategori. Poin di platform bersifat dinamis (menurun seiring bertambahnya solver); nilai di bawah adalah nilai saat challenge dikerjakan.

#ChallengeKategoriPoinKerentanan Inti
1RE EASYYYYYReverse Engineering50Overlapping stack write
2The Leaky ArchiveCryptography50ZipCrypto known-plaintext
3NoteVault v1.4Binary Exploitation50Format string → arbitrary read
4License BeaconReverse Engineering100Custom VM + FNV-1a/xorshift64
5Forensik Memory GUYSDigital Forensics200Process masquerading
6Ghost in the HandsetDigital Forensics171ADB + Redis clipboard leak
7Backup Never DiesWeb Exploitation50Exposed editor backup
8Cookie MonsterWeb Exploitation50Client-side authorization
9Confidential NotesWeb Exploitation50IDOR
10Saya AnggotaWeb Exploitation50Hidden non-contiguous IDs

Daftar Flag

RTRTNI26{p3rb4nd1ng4N_E5_0nl1}
RTRTNI26{kn0wn_pl41nt3xt_1s_4ll_y0u_n33d}
RTRTNI26{f0rm4t_str1ng_4rbitrary_r34d}
RTRTNI26{Lic3nse_VM_runT1me_traC3}
RTRTNI26{m3m0ry_f0r3ns1c_x0r_b4se64_gh1dr4_r3v_2026}
RTRTNI26{Ag3nt_L_n0nfreSh_w@rm_t34}
RTRTNI26{robots_are_not_security}
RTRTNI26{never_trust_client_side}
RTRTNI26{always_check_authorization}
RTRTNI26{66ead40b24f877734f07a9ef4a84b3b7}

1. RE EASYYYYY

Kategori: Reverse Engineering · Poin: 50 · Attachment: vault.zip

Challenge RE EASYYYYY

Langkah 1 — Identifikasi binary

Identifikasi binary

strings memberi empat fragmen yang tampak seperti potongan flag, tetapi urutannya tidak masuk akal. Yang menonjol: fragmen 2INTRTR adalah RTRTNI2 terbalik — petunjuk kuat bahwa string tersimpan dalam urutan terbalik.

Langkah 2 — Menemukan trik sebenarnya

Disassembly offset tumpang tindih

Tidak ada enkripsi sama sekali — main hanya melakukan satu strcmp. Triknya ada pada cara buffer dibangun: dua penulisan terakhir memakai offset -0x21 dan -0x19 yang bukan kelipatan 8.

Akibatnya chunk ketiga menimpa byte ke-15 milik chunk kedua (kebetulan sama-sama n, jadi tidak merusak data), sehingga panjang string menjadi 30 byte, bukan 32. Inilah sebabnya pembacaan strings biasa menghasilkan urutan yang salah.

offset:  0        8       15      23     30
         |________|_______|_______|______|
         }1ln0_5E _N4gn1d n4br3p{6 2INTRTR\0
                        ^
                        byte ke-15 ditimpa (n -> n)

Langkah 3 — Rekonstruksi dan verifikasi

Rekonstruksi buffer

buf = bytearray(48)
def w(off, val): buf[off:off+8] = val.to_bytes(8, 'little')
w(0x00, 0x45355f306e6c317d)   # }1ln0_5E
w(0x08, 0x6e64316e67344e5f)   # _N4gn1dn
w(0x0f, 0x367b70337262346e)   # n4br3p{6   <- overlap di offset 15
w(0x17, 0x525452544e4932)     # 2INTRTR\0
pw = buf.split(b'\x00')[0].decode()
print(pw[::-1])

Red herring: teks Password pertama — tidak ada tahap kedua di binary.

Flag: RTRTNI26{p3rb4nd1ng4N_E5_0nl1}


2. The Leaky Archive

Kategori: Cryptography · Poin: 50 · Attachment: soundofshire.zip

Challenge The Leaky Archive

"Pencuri yang bijak takkan membuang waktu mendobrak pintu besi raksasa milik sang naga. Ia hanya perlu mencari guratan kuno yang terpahat di sudut ambang pintu — sebuah tanda yang selalu sama sejak Zaman Pertama."

Langkah 1 — Membaca struktur arsip

Struktur arsip

Tiga fakta yang menentukan seluruh strategi:

FaktaImplikasi
csz = usz + 12ZipCrypto legacy, bukan AES-256
method = 0 (stored)plaintext = byte mentah file, tak perlu menebak hasil deflate
test_image.png ikut di arsipheader PNG-nya publik dan konstan

ZipCrypto punya kelemahan fatal: seluruh file dalam satu arsip memakai internal key (X, Y, Z) yang sama, hanya berbeda 12-byte header acak. Begitu kunci dipulihkan dari satu file, semua file lain ikut terbuka — persis seperti hint: "seluruh gembok di Erebor pun akan terbuka tanpa bersuara."

Langkah 2 — Menyiapkan known-plaintext

Known plaintext PNG

"Tanda yang selalu sama sejak Zaman Pertama" = magic bytes PNG. 16 byte kontigu di offset 0 sudah melewati minimum bkcrack (12 byte); sisanya ditambahkan sebagai sparse plaintext untuk mempersempit ruang cari.

Langkah 3 — Serangan dan dekripsi

bkcrack attack

Flag: RTRTNI26{kn0wn_pl41nt3xt_1s_4ll_y0u_n33d}


3. NoteVault v1.4

Kategori: Binary Exploitation · Poin: 50 · Target: 45.92.158.64:20001

Challenge NoteVault

Langkah 1 — Proteksi dan permukaan serangan

Proteksi binary

Binary non-PIE berarti seluruh alamat global bersifat tetap — tidak perlu leak alamat. Kombinasi getenv + dprintf langsung mengarahkan dugaan ke format string.

Langkah 2 — Menemukan lokasi flag

Lokasi g_flag

Flag dibaca dari environment variable FLAG ke g_flag @ 0x406880 — inilah "flag yang tersimpan di memori proses" yang diminta soal. Menariknya, fungsi Admin Debug pada binary justru membocorkan seluruh layout memorinya sendiri.

Struktur data catatan:

struct note {                 // total 0x170, array 16 slot @ 0x405140
    char     title[0x60];     // 0x000  <- memcpy(title_len), TIDAK null-terminated
    uint64_t title_len;       // 0x060
    char     content[0x100];  // 0x068  <- strncpy(0xff)
    int      id;              // 0x168
    int      used;            // 0x16c
};

Langkah 3 — Kerentanan format string

Format string bug

view_note menyalin 96 byte judul catatan ke stack lalu memanggil dprintf(fd, tmp) dengan eax = 0 (tanpa vararg). Judul catatan dipakai langsung sebagai format string — dan judul dikendalikan penuh oleh penyerang.

Langkah 4 — Eksploitasi

Eksploitasi

Offset buffer dikalibrasi otomatis dengan probe AAAABBBB%1$p.%2$p..., mencari nilai 0x4242424241414141. Hasilnya buffer berada di %7$, sehingga payload:

title = "%8$sAAAA" + p64(0x406880)
         └────────┘ └────────────┘
         8 byte      qword ke-1 buffer = %8$ = alamat g_flag

Red herring: fitur BULK: dan string umpan FLAG{th1s_1s_n0t_th3_r34l_fl4g}.

Flag: RTRTNI26{f0rm4t_str1ng_4rbitrary_r34d}


4. License Beacon

Kategori: Reverse Engineering · Poin: 100 · Attachment: License Beacon.zip

Challenge License Beacon

"Vendor menyatakan bahwa license VM mereka tidak dapat dianalisis tanpa activation service. Buktikan sebaliknya."

Langkah 1 — Isi paket dan perilaku awal

Isi paket

Dua kode error yang berbeda memberi informasi penting: partner.lic lolos verifikasi signature dan hanya gagal di activation, sedangkan enterprise.lic gagal lebih awal.

Langkah 2 — Membongkar license VM

License VM

Fungsi di 0x17d0 benar-benar sebuah interpreter bytecode: ia mengeksekusi 24 byte program di .rodata:0x2190 terhadap akumulator 64-bit, dengan opcode ditentukan oleh byte & 3.

opoperasi
0s = (c<<33) ^ s ^ 0x9E3779B97F4A7C15
1s = rol64(s, c%31+1) + 0x6A09E667F3BCC909
2s = (c | 0xBF58476D1CE4E5B9) * (s ^ (s>>29))
3s ^= rol64(s + 0x94D049BB133111EB, c%23+1)

Ketiga konstanta itu adalah konstanta splitmix64 — sidik jari yang membantu mengenali struktur algoritmanya.

Langkah 3 — Oracle gratis untuk validasi

Validasi dan activation

Inilah kunci penyelesaiannya. partner.lic sudah membawa signature valid (EEA9ABAA), sehingga bisa dipakai untuk membuktikan reimplementasi VM bit-exact sebelum menghitung activation. Kalau sig cocok, jalur activation dipastikan ikut benar — tidak perlu menebak.

Ini penting karena modulo 31 dan 23 di dalam VM muncul sebagai idiom magic-division di assembly, bagian yang paling rawan salah dibaca.

sig = hi32 ^ lo32  of  VM( rol64(fnv(nonce),17) ^ fnv(serial) )

act = VM( rol64(VM(rol64(fnv(region),29) ^ fnv(nonce)), 19)
          ^ VM(rol64(fnv(node),11) ^ fnv(serial))
          ^ 0xA5C31D7E29F0486B )

Langkah 4 — Verifikasi dengan binary asli

Verifikasi

sealed.dat di-XOR dengan keystream xorshift64 yang di-seed dari VM(activation ^ fnv1a("reconciliation")), di-refresh setiap 8 byte.

Red herring: enterprise.lic mustahil dipakai — binary melakukan strcasecmp(tier,"trial") dan wajib bernilai 0, sehingga tier enterprise selalu jatuh ke E23 berapa pun signature-nya. beacon.cache juga tidak dipakai sama sekali.

Flag: RTRTNI26{Lic3nse_VM_runT1me_traC3}


5. Forensik Memory GUYS

Kategori: Digital Forensics · Poin: 200 · Attachment: memory.raw.zst (1,3 GB → 13 GB)

Challenge Forensik Memory

⚠️ Dekompresi jangan ke /tmp bila itu tmpfs — 13 GB akan memakan RAM.

Langkah 1 — Identifikasi memory image

Identifikasi image

banners.Banners mengeluarkan ntkrnlmp.pdb, langsung memastikan ini image Windows, bukan Linux.

Langkah 2 — Menemukan proses yang menyamar

Proses menyamar

pslist sama sekali tidak membantu di sini — seluruh 46 svchost.exe ber-parent services.exe dengan nama yang tampak wajar. Yang membongkarnya adalah windows.cmdline.

Penyamarannya dua lapis:

  1. Homoglyph — angka nol menggantikan huruf o: svch0st bukan svchost
  2. Path — dijalankan dari C:\ctf\, bukan C:\Windows\System32\

Ditambah parent PID 6124 yang bukan services.exe — svchost asli tidak pernah demikian.

Langkah 3 — Dump binary implan

Dump PE

PE32+ 68 KB hasil kompilasi MinGW-w64. String-nya langsung membuka jalan: dua blob base64 dan literal RTRTNI.

Langkah 4 — Memulihkan konfigurasi rahasia

Dekode konfigurasi

Obfuskasinya base64 → XOR kunci berulang, dengan kunci tertinggal sebagai literal di dalam binary.

Yang membuatnya bisa dipecahkan tanpa menebak sama sekali: blob kedua diawali enam byte nol. Pada XOR kunci-berulang, byte nol berarti plaintext identik dengan kunci di posisi tersebut — jadi enam karakter pertama flag adalah kuncinya, dan panjang kunci dipastikan 6.

Flag: RTRTNI26{m3m0ry_f0r3ns1c_x0r_b4se64_gh1dr4_r3v_2026}


6. Ghost in the Handset

Kategori: Digital Forensics · Poin: 171 · Attachment: challenge.pcapng + nc 45.92.158.64 32392

Challenge Ghost in the Handset

"Agen lapangan berkode 'L' menghilang. Apa yang sebenarnya terjadi pada Agent L? Dan siapa yang membaca pesannya lebih dulu?"

Langkah 1 — Memetakan trafik

Peta trafik

Seluruh trafik adalah loopback — capture diambil dari host yang menjalankan emulator Android (Genymotion).

Port 6555 ditentukan dari protokolnya, bukan tebakan: hanya stream 0 yang memuat magic ADB (OPEN/WRTE/CLSE), sedangkan 5037 murni jalur adb-server lokal.

Langkah 2 — Kebocoran lewat Redis clipboard sync

Redis clipboard leak

Genymotion menyinkronkan clipboard melalui Redis, dan itu merekam perintah attacker apa adanya. Dari sini juga terkonfirmasi shell yang diperoleh adalah root.

Langkah 3 — Merekonstruksi database

De-chunking ADB sync

Bagian yang paling menuntut ketelitian: byte mentah TCP bukan file yang valid. adb pull membungkus payload dalam chunk DATA + panjang 32-bit little-endian, diakhiri DONE. Tanpa de-chunking, file SQLite akan korup.

Langkah 4 — Isi bukti dan penyelesaian kuis

Isi database dan kuis

Service nc mengajukan 10 pertanyaan investigasi berurutan:

#PertanyaanJawaban
1Remote debugging protocoladb
2Port adbd sisi device6555
3User shell attackerroot
4Pub/sub yang membocorkan perintahredis
5Database pertama di-pull/data/data/com.android.providers.telephony/databases/mmssms.db
6Database kedua di-pull/data/data/com.android.providers.contacts/databases/contacts2.db
7Nomor pengirim SMS(237) 230-7212
8Clue phrasenonfresh_warm_tea
9Display name kontakAgent_L
10Email kontakagent_l@ex4mpl3.com

Jawaban naratifnya: attacker-lah yang membaca pesan itu lebih dulu. Ia sudah memegang shell root dan menarik mmssms.db, sehingga SMS berisi clue sudah dibacanya sebelum sempat berarti bagi siapa pun.

Red herring: SMS keluar terenkripsi di Redis (baseband sms outbound 122 RlFLZi7OozpldM6UIw==) sama sekali tidak dibutuhkan.

Flag: RTRTNI26{Ag3nt_L_n0nfreSh_w@rm_t34}


7. Backup Never Dies

Kategori: Web Exploitation · Poin: 50 · Target: http://45.92.158.64:28491/

Challenge Backup Never Dies

Langkah 1 — robots.txt justru membocorkan lokasinya

robots.txt

Ironinya sesuai dengan flag-nya sendiri: robots.txt bukan kontrol keamanan — ia justru mempublikasikan daftar path sensitif kepada siapa pun.

Langkah 2 — Directory listing dan file backup editor

Backup file

Dua kesalahan konfigurasi bertumpuk:

  1. Directory listing aktif pada /backup/
  2. File backup editor (.bak, .old, .save, .tmp) tidak diproses PHP, sehingga source code tersaji mentah

Flag: RTRTNI26{robots_are_not_security}


8. Cookie Monster

Kategori: Web Exploitation · Poin: 50 · Target: http://45.92.158.64:37204/

Challenge Cookie Monster

Langkah 1 — Menganalisis mekanisme autentikasi

Set-Cookie role

Login mengembalikan dua cookie. PHPSESSID sudah tersedia sebagai sesi server-side — namun role justru disimpan terpisah di cookie yang sepenuhnya dikendalikan klien.

Langkah 2 — Memalsukan role

Forge admin cookie

Root cause: state otorisasi disimpan di data milik klien dan tidak diverifikasi ulang di server. Seharusnya role berada di $_SESSION.

Flag: RTRTNI26{never_trust_client_side}


9. Confidential Notes

Kategori: Web Exploitation · Poin: 50 · Target: http://45.92.158.64:19482/

Challenge Confidential Notes

"Agen K merilis sistem penyimpanan catatan rahasia yang ia klaim sepenuhnya privat. Namun rumor mengindikasikan adanya celah tipis pada arsitektur isolasi datanya."

Langkah 1 — Kredensial demo tercetak di halaman login

Demo accounts

Langkah 2 — Daftar difilter, detail tidak

IDOR enumeration

Aplikasi memfilter daftar di notes.php, tetapi note.php sama sekali tidak memeriksa kepemilikan.

idownerisi
1guestProject Meeting
2adminSalary Review — dinyatakan sendiri sebagai decoy
3guestWelcome Note
4adminAdministrator Secret → flag

Langkah 3 — Membaca catatan milik admin

Read admin note

Root cause: otorisasi diterapkan di lapisan presentasi, bukan di lapisan akses data — persis "celah tipis pada arsitektur isolasi data" yang disebut soal.

Flag: RTRTNI26{always_check_authorization}


10. Saya Anggota

Kategori: Web Exploitation · Poin: 50 · Target: http://45.92.158.64:26391/

Challenge Saya Anggota

Langkah 1 — Ketidakcocokan jumlah anggota

Jumlah anggota

Dashboard menyatakan 110 Total Anggota, tetapi enumerasi ID 1–130 hanya mengembalikan 100 record. Selisih 10 itulah "anggota yang terlibat" yang diminta soal.

Ini bukan SQL injection — input divalidasi ketat sebagai integer; 1', 1 OR 1=1, 01, 1e2, +1, 0x65 semuanya ditolak.

Langkah 2 — Enumerasi ID non-kontigu

Enumerasi ID

Record tersembunyi diberi ID non-kontigu agar tidak terlihat lewat penelusuran normal. Sapuan ID 1–9000 menemukan sembilan, tiga di antaranya berisi fragmen base64.

Langkah 3 — Menyusun ulang fragmen terbalik

Rekonstruksi fragmen

Fragmen ketiga diawali } — tanda seluruh rangkaian tersimpan terbalik. Dua jalur rekonstruksi yang independen memberi hasil identik, dan itulah yang meyakinkan:

  • C) gabung urut ID naik, lalu balik tiap fragmen
  • D) gabung urut ID turun, lalu balik keseluruhan string

Hasilnya tepat 32 karakter heksadesimal (persis panjang MD5) diikuti kurung tutup. Prefiks RTRTNI26{ sudah diberikan di deskripsi soal.

Flag: RTRTNI26{66ead40b24f877734f07a9ef4a84b3b7}


Struktur Repository

.
├── WRITEUP.md                 <- dokumen ini
├── images/
│   ├── challenges/            <- screenshot halaman soal
│   └── steps/                 <- gambar langkah pengerjaan
├── re-easyyyyy/               <- binary vault + disassembly
├── leaky-archive/             <- arsip, plain.bin, flag hasil dekripsi
├── notevault/                 <- binary + exploit.py
├── license-beacon/            <- solve.py (mandiri, tanpa binary)
├── memforensics/              <- vol3 wrapper + dump proses 1348
└── ghost-handset/             <- extract_db.py, ask.py, database rekonstruksi

Tooling

volatility3 · bkcrack · tshark / capinfos · objdump / readelf / pefile · sqlite3 · Pillow · curl · Python 3


Matlee Arya Sadewa · Achmad Kamal · Huga Hazimulfikri Nawawi