Description
A Python script decrypts flag.txt.enc after checking a password. The password is plainly stored inside the code-use it to reveal the flag.
Open patchme.flag.py (or just grep for the assignment) and note the password hard-coded inside the function (e.g., ak98-=90adfjhgj321sleuth9000).
Run python3 patchme.flag.py, enter the password, and the script prints the flag.
grep -E 'password\s*=' patchme.flag.pypython3 patchme.flag.pySolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1
Read the functionObservationI noticed patchme.flag.py was provided as plain Python source, which suggested that the password used in the decryption check could be read directly from the code without patching or bypassing anything.fstores the password in clear text. Nothing needs to be patched; just use that string when prompted.What didn't work first
Tried: Trying to bypass the password check by editing the script to skip the comparison entirely.
The challenge title says 'PatchMe', so many beginners assume they need to modify the source. Patching works, but it is unnecessary - the password is stored in plain text in the function, so you can just read it out and use it directly without touching the code.
Tried: Searching for the password in flag.txt.enc instead of the Python file.
Beginners sometimes open the .enc file hoping to spot the password near the encrypted data. The .enc file contains only ciphertext and is not human-readable. The password lives in patchme.flag.py, not in the encrypted output.
Learn more
Hardcoded secrets are credentials, passwords, or keys embedded directly in source code. This is a critically common vulnerability - developers sometimes store secrets in code for convenience during development, then accidentally ship those files.
The challenge title "PatchMe" implies you would need to modify the script to bypass the check, but reading the source reveals there's nothing to patch at all. The password is stored in plain sight inside a Python function. Tools like
grep,strings, or even a simple text editor are all you need.In real security assessments, hunting for hardcoded credentials in source code is a standard step. Tools like truffleHog, gitleaks, and semgrep automate this across entire repositories and git history. Secrets committed to git remain retrievable even after deletion via
git log.The reason hardcoded secrets persist is partly cultural: during development it's faster to put a password directly in the code than set up a proper secrets management system. Once hardcoded, the secret often gets checked into version control and then propagates - into build artifacts, container images, deployed binaries, and third-party audit logs. By the time someone realizes it's there, rotating the secret requires tracking down every location it was copied to.
Pre-commit hooks are the most effective automated prevention. Tools like detect-secrets scan each diff before it is committed and block any commit containing high-entropy strings or known secret patterns (AWS access key prefixes, private key headers, connection strings). Integrating this check into CI/CD pipelines as well ensures that secrets don't slip through even if the pre-commit hook is bypassed locally.
Step 2
Get the flagObservationI noticed the script accepts a password at runtime and then decrypts flag.txt.enc using it, which meant running the script with the hardcoded password in hand would produce the plaintext flag directly.Run the script alongside flag.txt.enc, enter the password, and copy the picoCTF output.What didn't work first
Tried: Running patchme.flag.py from a different directory without flag.txt.enc present.
The script tries to open flag.txt.enc relative to the current working directory. If only the Python file is in the folder, the script throws a FileNotFoundError. Both files must be in the same directory before running the script.
Tried: Entering the password with extra whitespace or quotes copied from the source code.
When copying the password string from the assignment in Python, beginners sometimes include the surrounding quote characters or a trailing newline. The input prompt expects the raw string value - no quotes, no extra spaces - exactly as it appears between the quote characters in the source.
Learn more
The script uses the password to decrypt
flag.txt.enc- a file that has been encrypted, likely with a symmetric cipher like AES. This is a legitimate decryption workflow; the flaw is that both the key and the ciphertext are distributed together.This pattern mirrors real-world mistakes where developers encrypt sensitive files but bundle the decryption key alongside them - in the same repository, Docker image, or binary. Encryption only provides security when the key is kept separate from the ciphertext.
The lesson: encryption protects data in transit or at rest, but only if key management is done correctly. Symmetric keys should live in environment variables, secret managers (AWS Secrets Manager, HashiCorp Vault), or hardware security modules - never in code.
An alternative approach to this challenge - consistent with its "PatchMe" title - is to modify the Python script directly. You could replace the password comparison with a no-op (
if True:), patch the condition to always return True, or simply call the decryption function directly with any argument. This patching technique mirrors real-world software cracking and license bypass scenarios.If this were a compiled binary instead of a Python script, you'd patch at the instruction level: locate the conditional jump (
JZ,JNZ) guarding the password check and flip it to its complement, or replace it with aNOP(opcode0x90) to make the check unconditional. Tools like radare2 and Binary Ninja support interactive binary patching. None of that is needed here because the source is right in front of you.
Interactive tools
- Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
- Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.
Flag
Reveal flag
picoCTF{p47ch1ng_l1f3_h4ck_f01e...}
This is a reminder to never ship secrets in client-side code-anyone can read them.