Description
The image is formed by combining two hex strings. Solve the key to reveal the image.
Solution
Walk me through it- Step 1View the page sourceOpen 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. - Step 2Extract the hardcoded hex stringCopy 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.
- Step 3Brute-force or derive the keyWrite 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.
- Step 4Enter the key and view the imageSubmit 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.