Description
This vault uses some complicated arrays to store the password. Can you decrypt it? The Java source code is provided.
Setup
Download VaultDoor1.java from the challenge page.
Solution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Trace the character index checks
ObservationcheckPassword() in VaultDoor1.java is a long chain of charAt(i) == 'x' comparisons. Every required character and its exact position is spelled out in the source, so the password can be extracted without running anything.Open VaultDoor1.java and inspect checkPassword(). The method checks individual characters at specific indices using charAt() - for example, password.charAt(0) == 'd', password.charAt(29) == '3', etc. Collect each required character, placing it at the index specified, to reconstruct the full password string.What didn't work first
Tried: Trying to compile and run VaultDoor1.java, then guessing passwords interactively.
Running the program only prompts for a password and tells you right or wrong; it never reveals what the password is. Static analysis means reading the source directly instead of poking at the program as a black box.
Tried: Reading the charAt() comparisons in the order they appear in the file and writing down characters in that order.
The comparisons are intentionally listed in a scrambled index order, not in sequential order from index 0 upward. Reading them top to bottom produces a garbled string. You must note the index alongside each character and sort by index before assembling.
Learn more
This challenge demonstrates static analysis - reading source code or compiled bytecode to understand a program's behavior without executing it. The
checkPassword()method validates each character of the password individually using Java'sString.charAt(index)method, which returns the character at a given zero-based position.Because the checks are written out in source code, every required character and its required position are fully visible to the reader. The "security" relies entirely on the hope that an attacker won't read the source - a strategy known as security through obscurity, which is universally considered ineffective. Once source code is available (or a binary is decompiled), this protection provides zero resistance.
This pattern is a classic example of what the OWASP Top 10 calls Insecure Design - the fundamental approach to authentication is flawed regardless of implementation details. The correct approach is to store a cryptographic hash of the password and compare hashes, never the plaintext characters directly.
Step 2Reassemble the password in order
ObservationThe charAt() comparisons are listed in scrambled index order rather than sequentially. Joining the characters in file order gives garbage, so sort the pairs by index first.Sort all the charAt index-value pairs by index and concatenate the characters. The resulting string is the flag content to put inside picoCTF{...}.What didn't work first
Tried: Submitting the raw reassembled string as the flag without wrapping it in picoCTF{}.
The checkPassword() method strips the picoCTF{ prefix and } suffix before validating, so the characters you extract are just the inner content. The full flag must be wrapped in picoCTF{...} to be accepted by the scoring system.
Learn more
Reconstructing a scrambled string from index-value pairs is a straightforward permutation reversal. If you have a list of
(index, character)pairs, sorting by index and joining the characters gives the original string. In Python this looks like:''.join(c for _, c in sorted(pairs)).In real-world security research, this type of reconstruction is common when analyzing obfuscated code. Malware authors frequently split strings across multiple assignments, reverse them, or interleave characters to defeat simple
stringsanalysis. But once the obfuscation logic is understood, reconstruction is mechanical. Tools like de4dot (for .NET) and jadx (for Android APKs) automate much of this deobfuscation.The key lesson: any password check implemented in application logic can be reversed by reading that logic, no matter how cleverly the characters are scattered. True authentication security requires cryptographic primitives (hashing, signing) that are mathematically hard to reverse - not code complexity.
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{d35cr4mbl3_tH3_cH4r4cT3r5_...}
Character-by-index scrambling provides no security - reading the source and reassembling characters in index order immediately reveals the password.