keygenme-py Solution
This is the solution for picoCTF's keygenme-py challenge revese engineeering problem.
This problem was taken from the picoCTF 2021 and the solution will be discussed below. So proceed with caution.
Let's download the keygenme-trial.py
Then after downloading we can quickly view the Python file by running:
vim keygenme-trial.py
Looking at the contents of the file we determine that it is used for some calculation and it appears to be safe.
Let's investigate more by making the file an executable and running it:
chmod +x keygenme-trial.py
python keygenme-trial.py
From experimenting with the program we find that our aim is to unlock the program by entering a license key.
Looking at the source code keygenme-trial.py
we find the following variables that are related to the license key.
key_part_static1_trial = "picoCTF{1n_7h3_|<3y_of_"
key_part_dynamic1_trial = "xxxxxxxx"
key_part_static2_trial = "}"
key_full_template_trial = key_part_static1_trial + key_part_dynamic1_trial + key_part_static2_trial
These variables are used in the validation functions executed by menu choice c
.
As we can see in the variables above it follows the picoCTF flag format.
The function we are interested in is check_key
uses these variables.
If we analyze the check_key(key, username_trial)
, we see that it is first comparing the length of key_part_static1_trial = "picoCTF{1n_7h3_|<3y_of_"
to the key
provided by the application's user.
Once it validates that both variables have have the same length, it then proceeds to checking each character in key_part_stati1_trial
has the same character in key
at the same index i
. This is the static part of the key.
Next the check_key
function moves on to the dynamic part. The signifcant code here is hashlib.sha256(username_trial).hexdigest()
.
Here the program compares the key[i]
to specific character index of hashlib.sha256(username_trial).hexdigest().
See code below:
# Check dynamic part --v
if key[i] != hashlib.sha256(username_trial).hexdigest()[4]:
return False
else:
i += 1
if key[i] != hashlib.sha256(username_trial).hexdigest()[5]:
return False
else:
i += 1
if key[i] != hashlib.sha256(username_trial).hexdigest()[3]:
return False
else:
i += 1
if key[i] != hashlib.sha256(username_trial).hexdigest()[6]:
return False
else:
i += 1
if key[i] != hashlib.sha256(username_trial).hexdigest()[2]:
return False
else:
i += 1
if key[i] != hashlib.sha256(username_trial).hexdigest()[7]:
return False
else:
i += 1
if key[i] != hashlib.sha256(username_trial).hexdigest()[1]:
return False
else:
i += 1
if key[i] != hashlib.sha256(username_trial).hexdigest()[8]:
return False
So we need to determine what value hashlib.sha256(username_trial).hexdigest() is equivalent to.
To do this let's copy the original keygenme-trial.py
to another file in order to modify it.
cp
keygenme-trial.py
keygenme-trial2.py
Let's insert hashlib.sha256(username_trial).hexdigest()
in the check_key function before the static key check.
Running python
keygenme-trial2.py
We get the string: 31250184996c31741ab6ae8452c205deb7dbf431c5bdba21dea5f1289b646bfa
Now we can print every character equivalent for the dynamic part of the key
. Insert the following in the check_key
functhon:
print(hashlib.sha256(username_trial).hexdigest()[4], hashlib.sha256(username_trial).hexdigest()[5], hashlib.sha256(username_trial).hexdigest()[3], hashlib.sha256(username_trial).hexdigest()[6],hashlib.sha256(username_trial).hexdigest()[2],hashlib.sha256(username_trial).hexdigest()[7],hashlib.sha256(username_trial).hexdigest()[1],hashlib.sha256(username_trial).hexdigest()[8])
Running python
keygenme-trial2.py
again.
The program prints 0 1 5 8 2 4 1 9
We know that the key formula is
key_full_template_trial = key_part_static1_trial + key_part_dynamic1_trial + key_part_static2_trial
So basing on what we have derived
key_full_template_trial = "picoCTF{1n_7h3_|<3y_of_" + "01582419" + "}"
key_full_template_trial = "picoCTF{1n_7h3_|<3y_of_01582419}"
Now let's run the original python
keygenme-trial.py
and enter the derived key picoCTF{1n_7h3_|<3y_of_01582419}
to check if we are able to unlock the program.
Flag: picoCTF{1n_7h3_|<3y_of_01582419}
Until next time. Keep learning.
Stay stoked and code. :)
I hope you can voluntarily Buy Me A Coffee if you found this article useful and give additional support for me to continue sharing more content for the community. :)
Thank you very much. :)