Description
This vault hides its password as an array of bytes in Java source code. The twist: each byte is written in a different number base. Some entries are plain decimal integers, some use the 0x hex prefix, some use the 0 octal prefix, and the rest are raw Java char literals. All of them encode ASCII characters. Can you decode all four formats and recover the password?
Setup
Download the Java source file and open it in a text editor.
wget <url>/VaultDoor4.javaSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1
Read the Java source and identify the four encodingsObservationI noticed the challenge description mentioned bytes written in different number bases, which suggested I needed to inspect the Java source directly to identify each literal form (decimal, hex, octal, and char) before attempting any decoding.Open VaultDoor4.java and find the checkPassword method. It builds a byte array called myBytes where each slot holds an ASCII code written in one of four Java literal forms: plain decimal (e.g. 106), hex with 0x prefix (e.g. 0x55), octal with a leading 0 (e.g. 0142), or a raw char literal (e.g. '7'). The method then compares each character of your input against the decoded value.bashcat VaultDoor4.javaWhat didn't work first
Tried: Run strings VaultDoor4.java hoping to spot the password directly in the output
strings will print the human-readable text of the source file, but the password characters are encoded as numeric literals spread across four different bases, so no contiguous ASCII password string appears. The correct approach is to parse and convert each integer literal individually rather than treating the file as raw binary.
Tried: Assume all entries in myBytes are plain decimal and convert them directly with chr()
Entries with a 0x prefix are hexadecimal and entries with a leading 0 are octal, so treating them as decimal yields wrong character values - for example 0x55 read as decimal 55 gives '7' instead of 'U'. You must detect the prefix of each literal before calling chr() on it.
Learn more
In Java (and C), an integer literal that starts with
0xis hexadecimal, a literal that starts with a lone0followed by more digits is octal, and a literal with no special prefix is decimal. A char literal like'7'is already the character itself and needs no conversion at all.The four groups in myBytes are roughly: the first 8 entries are decimal, the next 8 are hex, the next 8 are octal, and the last 8 are char literals. Each group still encodes a printable ASCII character - the difference is only in how the author chose to write the number down in source code.
This multi-base trick defeats a naive
stringssearch while remaining trivially reversible once you recognize the notation.Step 2
Decode all four groups with PythonObservationI noticed that Python shares the 0x hex prefix with Java and supports octal via the 0o prefix, which suggested it was the most natural scripting tool to convert all four literal forms to ASCII characters with a single chr() call per value.Python understands all four literal forms natively. Copy the values from the source file, paste them into a Python list exactly as written (Python uses the same 0x and 0 prefix conventions as Java, and handles single-quoted chars as strings), then call chr() on each integer to recover the password characters.pythonpython3 -c " # Paste the four groups directly from VaultDoor4.java. # Decimal group dec = [106, 85, 53, 116, 95, 52, 95, 98] # Hex group (0x prefix - Python reads these natively) hex_ = [0x55, 0x6e, 0x43, 0x68, 0x5f, 0x30, 0x66, 0x5f] # Octal group (0o prefix in Python; Java uses bare 0 prefix) oct_ = [0o142, 0o131, 0o164, 0o63, 0o163, 0o137, 0o66, 0o61] # Char-literal group (already the characters themselves) chars = list('e0f27690') # replace with the chars from your file print(''.join(chr(v) for v in dec + hex_ + oct_) + ''.join(chars)) "Expected output
picoCTF{...}What didn't work first
Tried: Paste Java octal literals with their bare leading-zero prefix directly into Python 3 (e.g. 0142 instead of 0o142)
Python 3 raises a SyntaxError on integer literals with a bare leading zero because that notation was removed after Python 2. You must manually replace each leading-zero octal like 0142 with the explicit 0o prefix form 0o142 before the interpreter will accept it.
Tried: Concatenate the four groups in the wrong order - for example alphabetical or hex-before-decimal
The myBytes array is indexed sequentially: positions 0-7 are decimal, 8-15 are hex, 16-23 are octal, and 24-31 are char literals. Reordering the groups produces a string that passes none of the character comparisons in checkPassword, because the vault checks each index individually against the corresponding decoded byte.
Learn more
Python's
chr()converts any integer (decimal, hex, or octal) to its Unicode/ASCII character. Because Python shares the0xhex prefix with Java you can paste hex literals verbatim. For octal you need to swap Java's leading-zero notation (e.g.0142) for Python's explicit0oprefix (e.g.0o142), because Python 3 treats a bare leading zero as a syntax error.The char-literal group is already decoded: just read the characters directly from the source code and concatenate them.
Step 3
Submit the passwordObservationI noticed the checkPassword method compares each myBytes index in sequential order, which confirmed that the decoded characters must be concatenated in array order (decimal, then hex, then octal, then char literals) to form the correct 32-character password.Concatenate the decoded characters in array order - decimal group first, then hex, then octal, then char literals - to form the 32-character password string. Wrap it in picoCTF{...} to submit the flag.Learn more
The flag format for vault-door challenges is
picoCTF{password}. Preserve the exact order from the myBytes array: the first 8 decoded characters come from the decimal group, the next 8 from hex, the next 8 from octal, and the final 8 from the char literals.
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.
- Base64 & Base32 DecoderDecode Base64 and Base32 strings with auto-detection. Multi-layer mode unwraps nested encodings automatically.
Alternate Solution
Use the Number Base Converter on this site to look up individual values one at a time - convert hex or octal entries to decimal first, then read off the ASCII character, without needing Python or a reference table.
Flag
Reveal flag
picoCTF{jU5t_4_bUnCh_0f_bYt3s_...}
The myBytes array mixes four literal forms: decimal, 0x hex, leading-zero octal, and char literals. Convert each to its ASCII character (Python chr() handles decimal, hex, and octal; char literals are already decoded) and concatenate in order.