280 words
1 minutes
SCSC2026 Final - The Predictable Oracle - Cryptography Writeup

Category: Cryptography

Flag: scsc26{0fb_mode_is_just_a_stream_cipher_with_static_iv}

Description: flag format: scsc26{…}

The artifact was a ZIP archive. Its file metadata showed one deflated archive, and listing it showed three files: README.md, challenge.py, and output.txt.

file '/home/rei/Downloads/SCSC2026Final/Crypto_3.zip' && stat -c '%s %F %y' '/home/rei/Downloads/SCSC2026Final/Crypto_3.zip'
/home/rei/Downloads/SCSC2026Final/Crypto_3.zip: Zip archive data, made by v2.0 UNIX, extract using at least v2.0, last modified, last modified Sun, May 14 2026 22:45:36, uncompressed size 507, method=deflate
1265 regular file 2026-05-16 10:00:26.737233448 +0700
unzip -l '/home/rei/Downloads/SCSC2026Final/Crypto_3.zip'
Archive:  /home/rei/Downloads/SCSC2026Final/Crypto_3.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
      507  05-14-2026 22:45   README.md
      376  05-14-2026 23:07   challenge.py
      269  05-14-2026 23:19   output.txt
---------                     -------
     1152                     3 files

The README described AES-OFB with a fixed IV. It said one captured message was known dummy text, and the other was the flag ciphertext. The source confirmed that encrypt() creates AES in OFB mode with STATIC_IV = b"IniIVRahasia1234" for every message.

import os
from Crypto.Cipher import AES

STATIC_IV = b"IniIVRahasia1234" 

def encrypt(message):
    cipher = AES.new(KEY, AES.MODE_OFB, iv=STATIC_IV)
    return cipher.encrypt(message).hex()

dummy_text = b"This is a public dummy message to test the system encryption."
print(f"Dummy Ciphertext: {encrypt(dummy_text)}")

print(f"Flag Ciphertext: {encrypt(FLAG)}")

OFB turns AES into a stream cipher. With the same key and IV, the stream repeats. That made the dummy plaintext enough: dummy_ciphertext XOR dummy_plaintext gives the stream, and flag_ciphertext XOR stream gives the flag. The captured ciphertexts were:

Dummy Ciphertext: 86d6cf2650ba6d114b147a560ec8bcff244a4dc54d0653e26f87f303140910200a755255026bbb95f15bf831dff09ff8af476ab8e6a4728202bea6da50
Flag Ciphertext: a1ddd53642e565014c56554e03c0b0c36d5d67c2550c07d06babf316010951393a364f40197ae9beee57ac2af9f09ffcb60e6c89eca076

The final script decoded both hex strings, recovered the repeated stream from the dummy text, and XORed it with the flag ciphertext.

from binascii import unhexlify

known = b'This is a public dummy message to test the system encryption.'
dummy = unhexlify('86d6cf2650ba6d114b147a560ec8bcff244a4dc54d0653e26f87f303140910200a755255026bbb95f15bf831dff09ff8af476ab8e6a4728202bea6da50')
flagct = unhexlify('a1ddd53642e565014c56554e03c0b0c36d5d67c2550c07d06babf316010951393a364f40197ae9beee57ac2af9f09ffcb60e6c89eca076')
keystream = bytes(a ^ b for a, b in zip(dummy, known))
pt = bytes(c ^ k for c, k in zip(flagct, keystream))
print(pt.decode())
scsc26{0fb_mode_is_just_a_stream_cipher_with_static_iv}
SCSC2026 Final - The Predictable Oracle - Cryptography Writeup
https://blog.rei.my.id/posts/150/scsc2026-final-the-predictable-oracle-cryptography-writeup/
Author
Reidho Satria
Published at
2026-05-16
License
CC BY-NC-SA 4.0