Suspicious Python Script - Reverse Engineering

In this challenge we get a simple Python script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import base64
import hashlib
import time


CACHE_VERSION = "2026.06"

DECOY_NOTE = "VGhpcyBpcyBqdXN0IGEgZGVjb3kgc3RyaW5nLg=="

_DATA = [
    10, 7, 111, 82, 7, 113, 93, 84, 6, 121,
    5, 122, 77, 14, 113, 83, 64, 3, 5, 111,
    77, 113, 77, 111, 66, 117, 99, 122, 7, 101,
    77, 110, 77, 97, 89, 109, 94, 117, 77, 111,
    66, 117, 115, 86, 7, 91, 127, 84, 0, 109,
    114, 97, 115, 14, 91, 99, 115, 101, 97, 97,
]


def _checksum(text: str) -> str:
    return hashlib.sha256(text.encode()).hexdigest()[:8]


def _decode_cache_key() -> str:
    buffer = "".join(chr(value ^ 0x37) for value in _DATA)
    return base64.b64decode(buffer[::-1]).decode()


def _fake_update_check() -> str:
    time.sleep(0.1)
    return "no-updates"


def main() -> None:
    print("[*] Checking local grade cache...")
    status = _fake_update_check()
    cache_key = _decode_cache_key()

    if _checksum(cache_key) == "00000000":
        print(cache_key)

    print(f"[*] Cache version: {CACHE_VERSION}")
    print(f"[*] Status: {status}")


if __name__ == "__main__":
    main()

How the script works: _decode_cache_key() XORs every byte in _DATA with 0x37, joins the results into a string, reverses it, and base64-decodes it — that’s the actual flag, fully computed every time the script runs. The catch is the if _checksum(cache_key) == "00000000": gate: it only prints cache_key when the first 8 hex characters of its SHA-256 hash equal "00000000", which practically never happens. So the flag is decoded internally but never revealed — the checksum is just a decoy to discourage casual reading of the code.

To get the flag, we just print cache_key before that checksum check:

1
2
3
4
    print(cache_key)

    if _checksum(cache_key) == "00000000":
        print(cache_key)

Running it:

1
2
3
4
5
$ python3 grades.py
[*] Checking local grade cache...
UTCN_CTF{pyth0n_0bfusc4t10n_1s_n0t_s3cur1ty}
[*] Cache version: 2026.06
[*] Status: no-updates

Exam - Crypto

We have 3 files: a plain announcement.txt, the encrypted version of the announcement, and the encrypted flag.

1
2
$ ls
announcement.txt  encrypted_announcement.hex  encrypted_flag.hex

announcement.txt:

1
The exam starts at 09:00 in room A101. Bring your student ID.

encrypted_announcement.hex:

1
db197a2fff5fb3f78eaf5c546da9144dbfb6eb5393b8e8cb2075a7bc69c65c682a2f332ee9e7ef867f8f512421453227faa312ddcb8b00e09cdc4bd4a0

encrypted_flag.hex:

1
da255c41c56486dcd5b21b432caf381fedb7b850f5b2ac8b5f77ace568d4

The vulnerability here is a simple key reuse (two-time pad). Both files were encrypted by XORing with the same keystream — a classic OTP/stream-cipher misuse. XOR has a property that breaks this:

1
2
enc_ann  = plaintext XOR key
enc_flag = flag      XOR key

XOR the known plaintext/ciphertext pair together to recover the key:

1
enc_ann XOR plaintext = key

After recovering the keystream bytes, I XOR-ed them with the encrypted flag to get the plaintext flag:

1
UTCN_CTF{n3v3r_r3us3_0tp_keys}

Leaked Keys - Crypto

In this challenge we get 3 files: one ciphertext, one encrypted RSA private key, and one Windows password hash:

1
2
$ ls
cipher.txt  mykey.pem  windows_password_hash.txt

The first thing we need to do is crack the hashed password, which uses the Windows NT hashing algorithm. This gives us the password:

1
abracadabra

Now we can use that passphrase to decrypt the RSA private key and get the unencrypted one. I used this command:

1
$ openssl rsa -in mykey.pem -out key.pem

With the decrypted private key, I opened CyberChef and used the RSA Decrypt operation with key.pem on cipher.txt to reveal the flag:

flag

Idle Agent 1 - Forensics

This is a very simple forensics challenge, in which we have a Windows crash dump. I resolved it very quickly by just using strings and grepping for the malicious executable, which is obvious:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(m9suu㉿kali)-[~/Desktop/utcn/idle_agent1]
└─$ ls
MEMORY.DMP

┌──(m9suu㉿kali)-[~/Desktop/utcn/idle_agent1]
└─$ file MEMORY.DMP
MEMORY.DMP: MS Windows 64bit crash dump, version 15.7601, 4 processors, DumpType (0x1), 130942 pages

┌──(m9suu㉿kali)-[~/Desktop/utcn/idle_agent1]
└─$ strings MEMORY.DMP | grep ".exe"
.....
C:\Users\user\Desktop\utcn4g3nt.exe
utcn4g3nt.exe
utcn4g3nt.exe
utcn4g3nt.exe
utcn4g3nt.exe
utcn4g3nt.exe
.....

Professor Laptop - Forensics

I opened the professor_laptop folder and looked through all the files:

1
2
3
4
5
6
7
8
9
10
11
12
┌──(m9suu㉿kali)-[~/Desktop/utcn/professor_laptop]
└─$ ls -lah
total 36K
drwxrwxr-x 7 m9suu m9suu 4.0K Jun 19 03:40 .
drwxrwxr-x 4 m9suu m9suu 4.0K Jun 29 03:07 ..
-rw-rw-r-- 1 m9suu m9suu   30 Jun 19 03:40 .bash_history
-rw-rw-r-- 1 m9suu m9suu  231 Jun 19 03:39 .browser_history.txt
drwxrwxr-x 2 m9suu m9suu 4.0K Jun 19 03:39 Desktop
drwxrwxr-x 2 m9suu m9suu 4.0K Jun 19 03:39 Documents
drwxrwxr-x 2 m9suu m9suu 4.0K Jun 29 03:07 Downloads
drwxrwxr-x 3 m9suu m9suu 4.0K Jun 19 03:39 .local
drwxrwxr-x 2 m9suu m9suu 4.0K Jun 19 03:39 .ssh

At first I didn’t find anything important, until I checked .browser_history and realized it pointed to some deleted files. I found a file in the trash containing the flag, encoded in base64:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cd .local
$ ls
share

$ cd share
$ ls
Trash

$ cd Trash
$ ls
files  info

$ cd files
$ ls
deleted_notes.txt

$ cat deleted_notes.txt
Old private notes:

Final encoded note:
VVRDTl9DVEZ7ZDNsMzczZF9kMDM1X24wN19tMzRuX2cwbjN9

Weird Data - Misc

We have a .gpx file, which I uploaded to gpsvisualizer.com to plot the route defined by its coordinates. The resulting route is a graphical representation of the flag:

gps

Broken University Logo - Misc

We have a PNG file, so the first thing I did was use exiftool to check all the metadata, where we can find the flag in a comment field:

1
2
3
4
5
6
7
8
9
┌──(m9suu㉿kali)-[~/Desktop/utcn]
└─$ exiftool utcn.png
ExifTool Version Number         : 13.50
File Name                       : utcn.png
Directory                       : .
File Size                       : 119 kB
.......
Comment                         : 'UTCN_CTF{c0mpr3553d_m374d474_b3475_57r1ng5}'
....