← Back to Writeups
CUSTOMEasySteganography

Marker

XESXOR9/2/20264 min read
#steganography#custom#easy#alpha_channel_extraction#mask_overlay_reconstruction#selective_text_reveal#linux

Marker

Platform: hackerlab | Category: Steganography | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-04-05 | Status: Solved Techniques: alpha_channel_extraction, mask_overlay_reconstruction, selective_text_reveal

Summary

Task: two PNG files appear ordinary, but one black companion image hides a sparse alpha-channel mask instead of visible content. Solution: inspect RGBA values, threshold the nonzero alpha pixels, and use that mask to reveal selected words from the other image, which combine into the final flag.

Marker — Hackerlab

Description

Обычный текст на обычном листе :)

English summary: The task provides two PNG images. One image shows ordinary visible text, while the second looks completely black. The goal is to determine whether the black image carries a hidden selection mask and recover the CODEBY{...} flag from the marked text fragments.

Analysis

File reconnaissance

Initial triage showed two normal-looking PNG files and no obvious embedded archive or alternate payload:

bash
file msg.png msg2.png
exiftool msg.png msg2.png
pngcheck -v msg.png
pngcheck -v msg2.png

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Important observations:

  • msg.png is a normal PNG with visible text
  • msg2.png is also a valid PNG, but visually appears fully black
  • metadata and PNG chunks do not reveal an extra archive or hidden appended data

That suggested the hiding method was inside pixel data rather than metadata or file structure.

Pixel-level inspection

Opening both images as RGBA and checking channel statistics exposed the real signal in msg2.png:

  • RGB values are all zero, so the image remains visually black
  • alpha values are not all zero
  • the alpha channel only uses the tiny set {0, 1, 2, 3} ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

This is a strong indicator that the image is acting as a selection mask rather than as a visible picture. Even though the alpha values are very small, scaling or thresholding them makes the marked regions visible.

When the alpha channel is extracted and amplified, several highlighted regions appear. These regions correspond to specific words and punctuation fragments from msg.png.

Reconstruction idea

The key insight is simple:

  • msg.png contains the readable source text
  • msg2.png contains a sparse alpha mask indicating which parts of that text matter ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

So instead of trying to decode bytes or carve files, we can use the nonzero alpha pixels from msg2.png as a binary mask and copy only the marked parts from msg.png onto a clean background.

The resulting image reveals isolated words that can be read directly or passed through OCR.

Recovered fragments:

  • CODEBY
  • HackerLab is
  • platform
  • with
  • REDACTED
  • REDACTED

The mask also contains brace fragments. Normalizing the extracted text into the expected flag format gives:

CODEBY{REDACTED} ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Solution

Step 1: Confirm the files are ordinary PNGs

bash
file msg.png msg2.png
exiftool msg.png msg2.png
pngcheck -v msg.png
pngcheck -v msg2.png

This rules out the easy cases such as appended archives, malformed chunks, or obvious metadata-based hiding.

Step 2: Inspect RGBA channels

Use Python and Pillow to inspect the pixel distribution, especially the alpha channel of msg2.png.

python
#!/usr/bin/env python3
from collections import Counter
from PIL import Image

img = Image.open("msg2.png").convert("RGBA")
r, g, b, a = img.split()
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

print("Size:", img.size)
print("Unique R values:", sorted(set(r.getdata()))[:10])
print("Unique G values:", sorted(set(g.getdata()))[:10])
print("Unique B values:", sorted(set(b.getdata()))[:10])
print("Alpha distribution:", Counter(a.getdata()).most_common())

The important result is that RGB stays black while alpha contains sparse nonzero values.

Step 3: Build a binary mask and reveal the selected text

python
#!/usr/bin/env python3
from PIL import Image

base = Image.open("msg.png").convert("RGBA")
mark = Image.open("msg2.png").convert("RGBA")
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

alpha = mark.getchannel("A")
mask = alpha.point(lambda p: 255 if p > 0 else 0)

out = Image.new("RGBA", base.size, (255, 255, 255, 255))
out.paste(base, mask=mask)
out.save("masked_words.png")

This keeps only the regions selected by the alpha mask and places them on a white background. The output image clearly reveals the hidden words.

Step 4: Read or OCR the reconstructed text

At this point the message can be read manually. OCR is optional but useful:

bash
tesseract masked_words.png stdout

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

The extracted text contains the words:

text
CODEBY
HackerLab is
platform
with
REDACTED
REDACTED

Combining the fragments and normalizing spaces and punctuation yields the final flag:

text
CODEBY{REDACTED}

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍