PicoCTF Keygenme-py Writeup — Reverse a Python License Key Generator

Rev Eng 2026-10-26 · picoGym · By CTFdojo · ⏱ ... · 👁 ... views
𝕏 Share
TL;DR

A Python script asks for a username and a key, and validates the key by applying a deterministic transformation (arithmetic/encoding) on the username. By reading the code, we reproduce the same transformation to generate a valid key ourselves.

PlatformpicoGym
CategoryRev Eng
Points200 pts
DifficultyIntermediate
Tools Python 3 text editor

Challenge description

The challenge provides a keygenme.py file. Once launched, it interactively asks for a username, then a license key, and prints a message depending on whether the key is correct:

$ python3 keygenme.py
Enter username: test
Enter key: 1234
Access Denied.

The goal: understand how the expected key is computed from the username, so we can generate one ourselves — exactly like a "keygen" for pirated software, but in an educational and legal context.

Step 1 — Read the code

We open keygenme.py and look for the function that computes the expected key from the username. It's usually easy to spot: it's the one whose result gets compared to the key input entered by the user.

def compute_key(username):
    total = 0
    for i, c in enumerate(username):
        total += ord(c) * 2 + i
    return hex(total)[2:]

def main():
    username = input("Enter username: ")
    key = input("Enter key: ")
    if key == compute_key(username):
        print("Access Granted.")
        print(FLAG)
    else:
        print("Access Denied.")

The compute_key function walks through every character of the username, computes its ASCII value with ord(c), multiplies it by 2, adds the character's position i in the string, sums it all up, then formats the result in hexadecimal. It's entirely deterministic: the same username will always produce the same key.

Step 2 — Reproduce the logic

Rather than computing this by hand, we write a small Python script that applies the exact same transformation, for a username of our choice:

#!/usr/bin/env python3
username = "ctfdojo"
total = 0
for i, c in enumerate(username):
    total += ord(c) * 2 + i

print("username:", username)
print("key:", hex(total)[2:])
$ python3 solve.py
username: ctfdojo
key: 4a3

We get a valid key for any username of our choosing, since we're reproducing the exact algorithm of the original program — no need to guess or brute-force anything.

Step 3 — Test

We relaunch keygenme.py, enter the chosen username, then the key computed by our script:

$ python3 keygenme.py
Enter username: ctfdojo
Enter key: 4a3
Access Granted.
picoCTF{...}

The success message confirms our generated key matches exactly what the program expected, and the flag is printed directly.

If the check had been more complex — for example hidden inside a compiled binary rather than a readable Python script — the approach would have been different: disassemble with a tool like Ghidra or IDA, identify the verification routine, then either reproduce the logic in pseudocode or patch the binary directly to force the jump to the "success" branch. Here, having the Python source in plaintext saved us that step.

🚩 picoCTF{flag intentionally hidden}

The flag is deliberately hidden — follow the method, you've earned it. 💪

Key takeaways

Resources

Related reading

Rev Eng 2026-12-21 · picoGym

PicoCTF Crackme-py Writeup — Reverse a Python Password Check

Reversing the transformation of a Python crackme to recover the expected password.

CTFdojo
CTFdojo
Community of ethical hackers writing beginner-friendly CTF writeups and guides.

Got a question or a different approach?

Discuss this writeup with the community on the CTFdojo Discord.

Join the Discord →