Going in Reverse

  Challenge Progession:
Act II
Difficulty:
  Location:
Retro Emporium
Going In Reverse
Back to the Past

Speaking with Kevin in the Retro Emporium, he tells us about how much he enjoys retro computing. He came accross some old 5.5in floppies and gives us a snippet of a BASIC program that appears to be some sort of login security system.

The Program

The BASIC program is very short and very simple...

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
To reverse this program, we just have to go step by step and understand what it is doing. There are 2 variables, one called ENC_PASS$ and ENC_FLAG$. These 2 values are likely the encrypted password and encrypted flag text.

Line Summary
10 This line only contains a comment, it can be ignored.
20 Declares a variable ENC_PASS$, likely the encrypted password
30 Declares a variable ENC_FLAG$, likely the encrypted flag text
There is an inline comment here that says this variable has an older value
40 Prompts the user to enter the password
50 Checks the length of the user-provided password. If it is not the same length as the ENC_FLAG$ string, go to line 90 (ACCESS DENIED).
60 Starts a "for" loop. The loop has a variable of "I" that starts at 1 and ends at the length of the ENC_PASS$ variable.
70 Goes character by character, converting that character to its ASCII value, XOR that value by 7, then convert it back to a character.
It does the same for the character in the same position of the ENC_PASS$ variable.
If these characters do not match, go to line 90 (ACCESS DENIED).
80 Boundry of the for loop started on line 60.
85 There are many statements made on this one line. It essentially does the same thing as line 70, but only for the ENC_FLAG variable.
  • Declares an empty string named FLAG$
  • Begins a for loop with variable I that runs from 1 to the length of ENC_FLAG
  • Goes character by character converting it to its ASCII value, XOR it by 7, then converting it back to a character.
  • It appends this character to the end of the newly declared FLAG$
  • Prints the FLAG$ variable
90 Just prints the text "ACCESS DENIED". Ironically, this will get printed even if the user enters the "correct" password.
100 END statement, just denotes the end of the program.

The Program

This process of going character by character and performing an XOR on it is more of an obfuscation technique than encryption. It has a very big weakness: XOR is its own inverse. This means that if you XOR a number A by number B, you can get the original number A back by performing the operation again!

Knowing this, we can get the clear text FLAG by going character by character and performing an XOR 7 on its ASCII value, then converting it back to a character. You can do this easily with most programming languages. I did it with python:

FLAG_ENC = "DSA|auhts*wkfi=dhjwubtthut+dhhkfis+hnkz"
FLAG = ""
for x in range(len(FLAG_ENC)):
    FLAG += chr(ord(FLAG_ENC[x]) ^ 7)
print(FLAG)  

Running this script produces the text "CTF{frost-plan:compressors,coolant,oil}". Enter this string in your badge to complete the challenge!

Bonus!

There are 3 values here that were encrypted: the password, the current flag, and the old flag. I used the code below to decrypt all 3:

# Going in reverse!
ENC_PASS = "D13URKBT"
ENC_FLAG = "DSA|auhts*wkfi=dhjwubtthut+dhhkfis+hnkz"
ENC_OLD_FLAG = "DSA|qnisf`bX_huXariz"

def reverse(enc_text):
    result = ""
    for x in range(len(enc_text)):
        result += chr(ord(enc_text[x]) ^ 7)
    return result

password = reverse(ENC_PASS)
flag = reverse(ENC_FLAG)
old_flag = reverse(ENC_OLD_FLAG)

print(f"Clear text password: {password}")
print(f"Clear text flag: {flag}")
print(f"Clear text old flag: {old_flag}")

All 3 Reversed