Category | Difficulty | Solves | Author |
---|---|---|---|
reverse |
easy |
20 | sudoBash418 |
Description
We’ve found a password verifier made by
0ph10n
, one of thet3l0s
operatives. Rumor has it, this password controls access to some of their monitoring services, which would be very valuable to our efforts.Can you figure out what the correct password is?
Players are given a file to download: password_checker.py
.
Analysis
The script we’re given is a basic password checker: it asks for the password and tells you if it’s correct or not.
Here’s the entire script, unedited:
|
|
The main loop is pretty boring: it just calls check_password
with our input and responds according to the return value.
check_password
is the where the interesting logic happens.
Solution
Let’s break this check_password
function down, step by step.
|
|
First, it checks each character against a whitelist of values.
The flag must contain only lowercase letters, digits, curly brackets, and underscores.
|
|
Next, it does a few checks confirming that the flag follows the standard clubeh{}
format.
|
|
chr(95)
is _
, and flag[7:-1]
returns the inner part of the flag (excluding the clubeh{}
part).
So p
is assigned a list of the “words” in the flag, split by underscores.
|
|
This part tells us there must be 7 words in the flag.
|
|
Here we have a couple of checks on the 1st and 2nd words.
Both words are 5 characters long, so we can just put their prefixes and suffixes together to reconstruct the words.
Word 1 must be t3l0s
and word 2 must be m4k35
.
|
|
Word 3 is th3
and word 4 is m05t
.
|
|
The last 3 words are encoded with a “rot18” cipher: each character is assigned an integer and rotated by 18, then converted back to a character.
Each word must match with the corresponding entry in the w
list:
|
|
We could work this out by hand, or we could be lazy and copy-paste the rot18
function to use ourselves:
>>> import string
>>> ALPHABET = string.ascii_lowercase + string.digits
>>> def rot18(data: str) -> str:
... s = ''
... for n in data:
... try:
... s += ALPHABET[(ALPHABET.index(n) + 18) % len(ALPHABET)]
... except ValueError:
... s += n
... return s
...
>>> rot18('aluc9l')
's3cur3'
>>> rot18('7mnnei9vn')
'p455w0rd5'
>>> rot18('njwmqwiw')
'51e48e0e'
Putting all the pieces together reveals the flag:
>>> "clubeh{" + '_'.join(["t3l0s", "m4k35", "th3", "m05t", "s3cur3", "p455w0rd5", "51e48e0e"]) + "}"
'clubeh{t3l0s_m4k35_th3_m05t_s3cur3_p455w0rd5_51e48e0e}'
Author’s Notes
This challenge was made at 5 AM on the day of the competition as a last-minute addition to our reverse
category.
We realized we didn’t really have any beginner-friendly reverse engineering challenges, so I quickly put together a basic “crackme” that only required a basic understanding of Python.
Looking back, I’m really glad Meaghan bugged me to we added this challenge.
It got 20 solves, double that of kAjfehg n
which was the next most-solved challenge in the reverse engineering category.