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}