XORDECRYPT
XORDECRYPT
Platform: CUSTOM | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: per_channel_state_recovery, row_wise_processing, xor_feedback_decryption
Summary
Walkthrough of the CUSTOM Crypto XORDECRYPT. Task: a noisy PNG hides the flag behind a custom XOR-based image transform. Solution: treat 0x67 as the initial state and decrypt each row independently with per-channel XOR feedback to reveal the ove
Description
I feel CHAINED to my desk, looking for some positive FEEDBACK.
We are given a PNG image named 0x67.png that appears heavily corrupted. The goal is to reverse the image transform and recover the hidden flag.
Challenge Summary
The image metadata is unhelpful: it is just a 1050x1050 RGB PNG with no useful embedded information. The real hints are in the challenge name, the clue text, and the filename.
XORDECRYPTsuggests the image bytes were transformed with XOR.CHAINEDandFEEDBACKsuggest a stateful mode rather than a fixed repeating key.0x67.pngstrongly suggests the initial state or IV is0x67.
Testing simple XOR variants does not cleanly recover the image, but a row-wise feedback construction does.
Recon / Hint Interpretation
The visible image looks like structured XOR corruption: noisy, but not randomly destroyed. That usually means the original data is still present under a reversible bytewise transform.
The successful interpretation is:
- Process the image row by row.
- Treat each RGB channel independently.
- Initialize the running state for each row and each channel with
0x67. - Decrypt pixels from left to right using XOR feedback.
This matches the wording of the clue very well: the decryption is both chained and feedback-based.
Analysis
For a ciphertext byte c and current state state, the plaintext byte is:
text read-only • copy allowedp = c XOR state
Then the state evolves using the recovered plaintext byte:
text read-only • copy allowedstate = state XOR p
Substituting the first equation into the second shows that the next state becomes the previous ciphertext byte, but the formulation above is the clearest way to implement the intended feedback process.
Applying this rule independently to each row and each color channel reconstructs a noisy but recognizable landscape image. The recovered image contains overlaid text with the flag:
text read-only • copy allowedUDCTF{REDACTED}
Solution
- Open the PNG and convert it to RGB.
- For each row, reset three channel states to
0x67. - For each pixel from left to right, decrypt
R,G, andBwith the feedback rule. - Save the resulting image and read the text shown in the recovered picture.
python read-only • copy allowed#!/usr/bin/env python3 from pathlib import Path from PIL import Image SRC = Path("tasks/BlueHens CTF 2026/XORDECRYPT/0x67.png") DST = Path("tasks/BlueHens CTF 2026/XORDECRYPT/xordecrypt_decrypted.png") IV = 0x67 def decrypt_row(rgb_row): state = [IV, IV, IV] out = [] for pixel in rgb_row: plain_pixel = [] for ch in range(3): c = pixel[ch] p = c ^ state[ch] state[ch] ^= p plain_pixel.append(p) out.append(tuple(plain_pixel)) return out img = Image.open(SRC).convert("RGB") w, h = img.size src_pixels = img.load() out = Image.new("RGB", (w, h)) out_pixels = out.load() for y in range(h): row = [src_pixels[x, y] for x in range(w)] dec = decrypt_row(row) for x in range(w): out_pixels[x, y] = dec[x] out.save(DST) print(f"saved decrypted image to {DST}") print("flag: UDCTF{REDACTED}")
Running the script reveals the hidden text in the image and prints the same flag.
Key Takeaways / Lessons
- Mastering per_channel_state_recovery, row_wise_processing, xor_feedback_decryption was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-04-22 • CUSTOM • XORDECRYPT • Difficulty: Easy