Skip to main content

vault-door-6 picoCTF 2019 Solution

Reverse a Java program that validates a password using bitwise operations on each character.

Published: April 2, 2026Updated: August 25, 2026

Description

This vault uses XOR with 0x55 to encode the password. Reverse it to find the flag.

Download the Java source file.

bash
wget <url>/VaultDoor6.java

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Find the hardcoded byte array
    Observation
    The description says the vault XORs with 0x55, so the secret must sit in the Java source as a pre-XORed byte array. Reading checkPassword in VaultDoor6.java exposes both the key and the encrypted values.
    Open VaultDoor6.java. The checkPassword method XORs each byte of the input with 0x55 and compares it to a hardcoded byte array. Extract that array.
    bash
    cat VaultDoor6.java
    What didn't work first

    Tried: Run the Java file directly with javac and java to see what the program outputs when you enter guesses

    The program only says whether a password is right or wrong; it never prints the plaintext. Brute-forcing 256^n combinations is infeasible. Extract the hardcoded byte array from the source and reverse the XOR offline instead.

    Tried: Search for a plaintext string in the source with grep or strings instead of reading the full checkPassword method

    The password is stored as XOR-encrypted integers like {0x3b, 0x65, ...}, not as readable ASCII, so grepping for printable characters finds nothing. Read the whole method to identify the byte array and the XOR key (0x55) before decrypting.

    Learn more

    0x55 in binary is 01010101. XORing with this value flips every other bit. Because XOR is its own inverse, applying 0x55 twice returns the original value.

    Single-byte XOR ciphers like this are trivially broken: there are only 256 possible keys, so even brute-force works instantly. With the key given in the source code, a single pass suffices.

  2. Step 2Decrypt using Python
    Observation
    XOR is its own inverse, so applying 0x55 again to each byte undoes the encryption. A Python one-liner over the array printing chr(b ^ 0x55) is the fastest way to the plaintext.
    XOR each byte in the hardcoded array with 0x55 to recover the original password characters.
    python
    python3 -c "
    enc = []  # paste the hardcoded byte array values from checkPassword() here
    print(''.join(chr(b ^ 0x55) for b in enc))
    "

    Expected output

    n0t_mUcH_h4rD3r_tH4n_x0r_...
    What didn't work first

    Tried: XOR each byte value with 0x55 without masking with 0xFF first, then see garbled or negative-index characters

    Java bytes are signed, -128 to 127, so a value like 0xd3 is stored as -45. In Python, chr(-45 ^ 0x55) raises a ValueError because chr() needs a non-negative integer. Mask first with & 0xFF, as in chr((b & 0xFF) ^ 0x55), to get an unsigned 0-255 value.

    Tried: XOR with 0xAA (the bitwise complement of 0x55) assuming a double-key scheme

    The source uses 0x55 as the XOR key in checkPassword, and there is no second key. 0xAA is 10101010, so XORing with it flips the opposite set of bits: b ^ 0xAA is the same as (b ^ 0x55) ^ 0xFF, the correct plaintext with every bit inverted, which prints as garbage. Use 0x55, exactly as written.

    Learn more

    In Python, the ^ operator performs bitwise XOR on integers. Since each Java byte value may be signed (range -128 to 127), you may need to apply & 0xFF first to convert to an unsigned 0-255 range before XORing.

  3. Step 3Submit the flag
    Observation
    The Python output is a readable ASCII string, which is the raw password. Wrapping it in picoCTF{} completes the flag.
    The decoded string is the password. Wrap it in picoCTF{...} to form the final flag.
    Learn more

    This challenge illustrates why XOR with a fixed single-byte key provides essentially zero security - it is equivalent to a Caesar cipher operating on individual bits rather than characters.

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.
  • XOR CipherXOR-decrypt hex or text ciphertext with a known key, or brute-force the single-byte key automatically.
Alternate Solution

Paste the hardcoded byte array as hex into the XOR Cipher tool on this site and enter 0x55 as the key - the tool XORs every byte instantly and shows the decoded password without writing any Python.

Flag

Reveal flag

picoCTF{n0t_mUcH_h4rD3r_tH4n_x0r_...}

XOR every byte in the hardcoded array with 0x55 to get the password characters.

Key takeaway

Single-byte XOR is the simplest symmetric cipher: it is its own inverse, so one operation both encrypts and decrypts. With only 256 possible keys it falls instantly to brute force, and when the key is written into the source it offers nothing at all. The same XOR primitive sits underneath stronger stream ciphers like RC4 and ChaCha20, but those derive a keystream that is never repeated and never exposed.

Related reading

Useful tools for Reverse Engineering

Where to go next