Java Script Kiddie picoCTF 2019 Solution

Published: April 2, 2026

Description

The image is formed by combining two hex strings. Solve the key to reveal the image.

  1. Step 1View the page source
    Open the challenge URL and view page source (Ctrl+U). Find the JavaScript that combines a user-supplied key with a hardcoded hex string to produce the bytes of a PNG image.
    Learn more

    The JavaScript XOR-combines a hardcoded hex string (the scrambled image bytes) with a user-supplied numeric key. The result is rendered as an image. If you supply the correct key, a valid PNG appears.

    A PNG always starts with the magic bytes: 89 50 4E 47 0D 0A 1A 0A. This known plaintext lets you brute-force or derive the key.

  2. Step 2Extract the hardcoded hex string
    Copy the hardcoded hex string from the JavaScript source. Each pair of hex digits is one byte of the XOR'd PNG.
    Learn more

    The key is typically short (1 byte per character, with up to 10 digits). Since you know the first 8 bytes of a valid PNG, you can determine what values the key bytes must be to produce those bytes after XOR.

  3. Step 3Brute-force or derive the key
    Write a script to try all possible key values (0-9 for each digit). For each candidate key, XOR the ciphertext and check if the result starts with the PNG magic bytes. Display the valid image.
    python
    python3 -c "
    # Minimal brute-force skeleton
    import itertools
    hex_str = 'PASTE_HEX_HERE'
    ciphertext = bytes.fromhex(hex_str)
    png_magic = bytes([0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A])
    # Key length determined from JS source
    for key_digits in itertools.product('0123456789', repeat=<KEY_LENGTH>):
        key = ''.join(key_digits)
        # XOR logic from JS
        # Check first 8 bytes
        pass
    "
    Learn more

    Known-plaintext attacks exploit knowledge of part of the original data. Since every valid PNG starts with the same 8 magic bytes, XORing the first 8 ciphertext bytes with the expected plaintext bytes reveals the first 8 bytes of the keystream. If the key is short and repeating, this may reveal the entire key.

  4. Step 4Enter the key and view the image
    Submit the discovered key in the input field on the challenge page. The image rendered will contain the flag.
    Learn more

    Alternatively, use Python Pillow or the browser's Canvas API to render the resulting bytes as an image and save it as a PNG file for reading.

Flag

picoCTF{...}

Brute-force the numeric key by checking which value produces valid PNG magic bytes after XOR with the hardcoded hex string.

Want more picoCTF 2019 writeups?

Useful tools for Web Exploitation

Related reading

What to try next