Description
A harder key-based image challenge. The key setup is more complex than part 1.
Solution
Walk me through it- Step 1View and analyze the JavaScriptView page source on the challenge. The JavaScript has a more complex key combination scheme than part 1. Carefully read how the key maps to XOR offsets in the ciphertext.
Learn more
In part 2, the key bytes may be used non-linearly or the mapping between key digits and ciphertext positions may be shuffled. Read the JS logic precisely before writing your solver.
Tools like Chrome DevTools' Sources panel let you set breakpoints in the JavaScript and step through it, making it easier to understand the key-to-XOR mapping.
- Step 2Extract and replicate the XOR logicTranscribe the JavaScript XOR logic into Python. The key insight remains: the output must start with valid PNG magic bytes (89 50 4E 47 0D 0A 1A 0A).python
python3 << 'EOF' hex_str = 'PASTE_HEX_FROM_JS' ciphertext = bytes.fromhex(hex_str) png_magic = bytes([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]) # Replicate JS key logic here # Then brute-force key and check bytes EOFLearn more
If the key is longer or has more combinations to test, consider constraining the search by checking all PNG structural requirements: magic bytes at offset 0, IHDR chunk at offset 8, and valid chunk CRCs. Each additional constraint dramatically reduces the valid key space.
- Step 3Render the decoded imageOnce the correct key is found, write the XOR-decoded bytes to a .png file and open it to read the flag.python
python3 -c " with open('flag.png', 'wb') as f: f.write(decoded_bytes) "bashxdg-open flag.pngLearn more
If the image does not open, verify the bytes are correct by running
pngcheck flag.pngor examining the first bytes withxxd flag.png | head. A valid PNG must have correct chunk lengths and CRC32 values throughout.
Flag
picoCTF{...}
Replicate the JS XOR logic in Python, brute-force the key using PNG magic bytes as an oracle, and render the image.