Post

Going in Reverse

Kevin in the Retro Store needs help rewinding tech and going in reverse. Extract the flag and enter it here.

Going in Reverse

Going in Reverse

Difficulty: ❄ ❄ ❄ ❄ ❄
Kevin in the Retro Store needs help rewinding tech and going in reverse. Extract the flag and enter it here.

Hints

Going in Reverse

It looks like the program on the disk contains some weird coding.

Going in Reverse

Maybe it is encrypted OR encoded?

Going in Reverse

Holy cow! Another retro floppy disk, what are the odds? Well it looks like this one is intact.

Items

Just a BASIC Program

00_basic_2.png
You’ve stumbled upon an old Commodore 64 floppy disk containing a mysterious BASIC program.

1
2
3
4
5
6
7
8
9
10
11
10 REM *** COMMODORE 64 SECURITY SYSTEM ***
20 ENC_PASS$ = "D13URKBT"
30 ENC_FLAG$ = "DSA|auhts*wkfi=dhjwubtthut+dhhkfis+hnkz" ' old "DSA|qnisf`bX_huXariz"
40 INPUT "ENTER PASSWORD: "; PASS$
50 IF LEN(PASS$) <> LEN(ENC_PASS$) THEN GOTO 90
60 FOR I = 1 TO LEN(PASS$)
70 IF CHR$(ASC(MID$(PASS$,I,1)) XOR 7) <> MID$(ENC_PASS$,I,1) THEN GOTO 90
80 NEXT I
85 FLAG$ = "" : FOR I = 1 TO LEN(ENC_FLAG$) : FLAG$ = FLAG$ + CHR$(ASC(MID$(ENC_FLAG$,I,1)) XOR 7) : NEXT I : PRINT FLAG$
90 PRINT "ACCESS DENIED"
100 END

Solution

I literally just ran the script with qbjs.org: qbjs

And then I submitted the flag CTF{frost-plan:compressors,coolant,oil}.

What happened

To make the code compatible with qbjs.org interpreter, I stripped out the line numbers. This inadvertently broke the GOTOs logic. Instead of jumping to the ACCESS DENIED section upon a failed password check, the interpreter executed the code sequentially. It fell right through to line 85, decoding and printing the flag automatically.

What the program actually does

The encryption used is a simple XOR cipher with the key 7. The script compares the user input against an encrypted password string and, if successful, decrypts the flag using the same operation.

I wrote a script to demonstrate the intended decryption logic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ENC_PASS$ = "D13URKBT"
ENC_FLAG$ = "DSA|auhts*wkfi=dhjwubtthut+dhhkfis+hnkz" 
ENC_OLD_FLAG$ = "DSA|qnisf`bX_huXariz"

PRINT "ENCODED PASS: "; ENC_PASS$
PRINT "DECODED PASS: "; DecodeString(ENC_PASS$, 7)
PRINT
PRINT "ENCODED FLAG: "; ENC_FLAG$
PRINT "DECODED FLAG: "; DecodeString(ENC_FLAG$, 7)
PRINT
PRINT "ENCODED OLD FLAG: "; ENC_OLD_FLAG$
PRINT "DECODED OLD FLAG: "; DecodeString(ENC_OLD_FLAG$, 7)

END

FUNCTION DecodeString (Encoded AS STRING, XorValue AS INTEGER)
    Result = ""    
    FOR i = 1 TO LEN(Encoded)
        CharCode = ASC(MID$(Encoded, i, 1))
        DecodedCharCode = CharCode XOR XorValue
        Result = Result + CHR$(DecodedCharCode)
    NEXT i
    DecodeString = Result
END FUNCTION

02_decode

Dissecting the attack

graph TD
    subgraph Analysis [1. Static Analysis]
        A["Source Code Extraction
        (Read login.bas)"]
        B["Algorithm Identification
        (XOR Cipher)"]
        style A fill:#7f1d1d,stroke:#ef4444,stroke-width:2px,color:#fff
        style B fill:#7f1d1d,stroke:#ef4444,stroke-width:2px,color:#fff
    end

    subgraph Crypto [2. Cryptanalysis]
        C["Weak Cryptography
        (Single-Byte XOR Key: 7)"]
        D["Hardcoded Secrets
        (Encrypted Flag & Password)"]
        style C fill:#9a3412,stroke:#f97316,stroke-width:2px,color:#fff
        style D fill:#9a3412,stroke:#f97316,stroke-width:2px,color:#fff
    end

    subgraph Exploitation [3. Exploitation]
        E["Logic Bypass / Decryption
        (Run Script / Remove GOTO)"]
        F["Flag Extraction
        (Recover Plaintext)"]
        style E fill:#7f1d1d,stroke:#ef4444,stroke-width:2px,color:#fff
        style F fill:#7f1d1d,stroke:#ef4444,stroke-width:2px,color:#fff
    end

    %% Flow Connections
    A -->|Find ENC_PASS$| B
    B -->|Identify Key '7'| C
    C -->|Decrypt ENC_FLAG$| E
    D -->|Decrypt ENC_PASS$| E
    E -->|Output| F
PhaseVulnerability (CWE)Mitigation
1. Analysis
CWE-312
Cleartext Storage of Sensitive Information
(Source Code Disclosure)
Obfuscation
(Compile/Pack Binary)
2. Credentials
CWE-798
Use of Hard-coded Credentials
(Stored Password String)
Hashing
(One-Way Hash Functions)
3. Crypto
CWE-327
Use of a Broken or Risky Cryptographic Algorithm
(Simple XOR)
Strong Cryptography
(AES / NaCl)

Fixing the Weak Cryptography (CWE-327)

Vulnerability: The application uses a simple XOR cipher with a single-digit key (7) to “encrypt” the password and the flag. XOR is symmetric and trivially reversible, providing no real security against reverse engineering.
Fix: Use robust encryption algorithms. For a retro system like C64, options are limited, but in a modern context, you would use authenticated encryption (like AES-GCM) or simply not store the secret locally.
Vulnerable Code (BASIC):

1
70 IF CHR$(ASC(MID$(PASS$,I,1)) XOR 7) <> MID$(ENC_PASS$,I,1) THEN GOTO 90

Secure Concept (Modern Python):

1
2
3
4
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
# FIX: Use strong encryption if reversibility is required
aesgcm = AESGCM(key)
decrypted_pass = aesgcm.decrypt(nonce, ciphertext, aad=None)

Impact: Prevents trivial decryption of the secrets by simply guessing the key or analyzing the algorithm.

Fixing the Credential Storage (CWE-798 and CWE-312)

Vulnerability: The password is stored in a reversible format (ENC_PASS$). This allows anyone who decompiles the script to recover the original password.
Fix: Use Cryptographic Hashing. Store only the hash of the password (e.g., SHA-256 or Argon2), which allows verification without revealing the original plaintext.
Vulnerable Code:

1
20 ENC_PASS$ = "D13URKBT" ' XOR encrypted, but reversible

Secure Concept:

1
2
3
4
5
import hashlib
# FIX: Store hash, compare input hash to stored hash
stored_hash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
if hashlib.sha256(user_input.encode()).hexdigest() == stored_hash:
    grant_access()

Impact: Even if the code is analyzed, the attacker cannot reverse the hash to find the original password, protecting the credential.

Funsies

Basic

Basic was my first programming language, and this book was the beginning of that:
90_libro

…And I still remember trying to run my first program, which was an attempt at coding an address book, all well written in Windows Notepad as a txt and not understanding why it wasn’t just “running” before discovering I also needed QBasic to run it (spoiler alert: it didn’t work at all 😁) 91_childhood_trauma.jpg

This post is licensed under CC BY 4.0 by the author.