online
writeups

Secure Password Database

PicoCTF2026 reverse

Pasted image 20260323162351

By analyzing the start of the main function, we notice that the program does not properly validate either the password itself or the length supplied by the user. Because the length is not verified, it is possible to provide a size greater than the actual password length.

Later in the code, the program asks for a hash and compares the parsed value with the output of make_secret.

Pasted image 20260323162423

The make_secret function reads an obfuscated string and decodes it by XORing each byte with 0xaa.

Pasted image 20260323162455

This secret is then passed to the hashing routine, which processes each character using the formula:

result = result * 0x21 + currentChar

The resulting value is returned as the expected hash.

Pasted image 20260323162757

Our first Python reimplementation failed because it used normal arbitrary-precision arithmetic, while the binary performs 64-bit arithmetic with overflow. To accurately reproduce the behavior of the program, we must mask the result with 0xffffffffffffffff after each iteration.

Pasted image 20260323162818

After validating the computation locally, we used the same hash against the remote instance and retrieved the flag.

Pasted image 20260323162832

● NORMAL 0xBlog
JetBrains Mono UTF-8 Hugo