PseudoRandom was a challenge at TeanbleCTF 2023 from the ‘Crypto’ category.
It involved a simple flaw in generating the key: instead of using a true random method of generating numbers, a pseudo-random method with a guessable seed was used.
The challenge
For this challenge, we got some code
And the output of that code
Analyzing the code, finding the flaws
It looks like the key is randomly generated by using random.randint(0,255).
For seeding the random module, the author used the current timestamp (current, at runtime).
Then, that timestamp is printed but seconds and milliseconds are omitted.
First attempt at solving this
In order to solve this, we have to:
guess the seconds value (60 possible values)
guess the milliseconds value (1000 possible values)
This means that we have to search through 60.000 keys. This is doable.
First, I wrote a function to generate all possible keys based on a given ISO-formatted string.
This should return the 60.000 possible keys for any given string (in the format used by this challenge).
Then, something to use a given key and try to decrypt our text:
Putting those together and adding a local test that would generate a ciphertext (of a fake flag) based on the current timestamp and the final script looks like this.
solve.py (click to expand)
Trying to run it in test mode
And I can confirm that it works: I could get back the flag that I put in.
Now, commenting out setup_test() and running it again on the real data
And … failure. No valid flag was retrieved.
The workaround
Timezones shouldn’t matter for timestamps like this, but I thought that I should try altering the hour anyway.
So instead of leaving in the hour from the original output, I tried using all the possible values there (24 values).
This increased the search space to 1.440.000 values (24 * 60.000). But this still runs in a reasonable time even without trying to parallelize the program.
This is how the final code looks like:
And the output that I got after running it
Flag obtained: flag{r3411y_R4nd0m_15_R3ally_iMp0r7ant}