The challenge "password generator" includes a ZIP file as well as source-code to a password-generator used to generate the password for the ZIP file. The notes state, that the author of this challenge was using Windows.
The Password-Protected ZIP-File contains a .txt file, which has a Timestamp of when it was packaged.
Examining the source code of the password generator, we can see that the seed to rand() is set doing srand(time(nullptr));
The description of the challenge mentions that the author was using windows, so we should look into the implementation of srand() / rand() in Windows' CRT.
Given you have selected the installation of the CRT source-code when setting up Visual Studio, the Implementation of rand() can be found on your machine at C:\Program Files (x86)\Windows Kits\10\Source\N.N.N.N\ucrt\stdlib\rand.cpp -- which I sadly cannot share for copyright reasons.
Looking at the aforementioned file however, reveals that the RNG is just a Linear congruential generator (LCG) with mod=2^{31}, multiplier=214013 and increment=2531011, that truncates the output of rand() to bits 30..16. Effectively locking the range of rand() to 0..32767
Luckily, this description is everything we need to fully reconstruct it. Below is a rust reimplementation of MS UCRT's RNG.
Because we do not know, whether the password has been generated prior or after the Text file inside the ZIP has been created, we should consider going both backwards and forwards in time, to do this, I chose to just use zig-zag integer ordering like this:
| Attempt | Timestamp |
|---|---|
| 1 | N + 0 |
| 2 | N + 1 |
| 3 | N - 1 |
| 4 | N + 2 |
| ... | ... |
This can be implemented as a neat iterator in rust like this:
So, to implement our guided brute-forcing, we can simply take the timestamp extracted from the ZIP file (176143200) and zig-zag around it, until we find a password to successfully decrypt the ZIP file.
let time: u32 = 1761429313;
for i in zigzag
As for our try_password() function, this will suffice:
After around 7000 attempts, you should be greeted with the correct password A655rUd3g3IkRMZX8fq1AyefYw4EfwXO which can be used to decrypt the flag.