496 отличий (496 differences)
496 отличий (496 differences)
Platform: bug-makers | Category: Steganography | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-01-01 | Status: Solved Techniques: image_difference_decoding, green_channel_lsb_extraction, zsteg_bitplane_identification, overlooked_asset_favicon
Summary
Task: a 'spot the 496 differences' web page with two near-identical anime images and a favicon; the flag is hidden in an image. Solution: the pixel diff decodes to a decoy hint message; the real flag is green-channel LSB steganography in the overlooked favicon.png, found with zsteg (b1,g,lsb,xy).
496 отличий (496 differences) — bug-makers (БАГодельня 2026)
Description
Найдите 496 отличий. Флаг внутри картинки. (Find 496 differences. The flag is inside the picture.)
A "spot the differences" web page at https://496-differences.t1.bug-makers.ru
shows two visually identical anime-style images side by side:
/images/pixie-1.png and /images/pixie-2.png (both 1024×1365 8-bit RGB PNG).
The page also references /images/favicon.png (100×100 RGB PNG). The girl wears
a "BugCTF" cap and a ladybug ("bug") necklace. Goal: recover the BugCTF{...} flag.
Analysis
The number 496 is the key structural hint: 496 = 62 × 8, i.e. 62 ASCII characters at 8 bits per character.
Diffing the two main images pixel-by-pixel reveals exactly 496 differing
pixels, all located on the last row (y=1364) at even x positions
0, 2, 4, …, 990 (496 positions). In pixie-2.png those pixels are set to pure
black (0,0,0) or pure white (255,255,255); everything else is byte-identical
between the two images.
Mapping white=1, black=0, MSB-first, 8 bits/char decodes the full 496 bits to:
Great! All differences have been found, and now find the flag.
This is exactly 62 bytes and consumes the entire diff — but it is only a decoy / hint, NOT the flag.
Exhaustive analysis of pixie-1/pixie-2 (single- and multi-channel LSB, 2-bit
LSB, reversed bit order, all 8 bit-planes, row/column order, PNG chunks, trailing
data, filter bytes, high-pass visual enhancement, exiftool, binwalk,
strings) found nothing else — they are clean AI-generated images apart from the
painted hint row.
The hint "the flag is inside the picture" points at the overlooked third
image: the favicon. Running zsteg -a favicon.png flagged the channel
b1,g,lsb,xy (1-bit, green channel, LSB, row-major xy order).
Solution
Stage 1 — Decode the decoy hint from the image diff
python read-only • copy allowed#!/usr/bin/env python3 from PIL import Image import numpy as np a = np.array(Image.open('pixie-1.png').convert('RGB')) b = np.array(Image.open('pixie-2.png').convert('RGB')) row = 1364 xs = [x for x in range(1024) if (a[row, x] != b[row, x]).any()] # 0,2,...,990 (496) bits = ''.join('1' if (b[row, x] == 255).all() else '0' for x in xs) msg = ''.join(chr(int(bits[i:i+8], 2)) for i in range(0, len(bits), 8)) print(msg) # -> Great! All differences have been found, and now find the flag.
Stage 2 — Extract the real flag from the favicon (green-channel LSB)
python read-only • copy allowed#!/usr/bin/env python3 from PIL import Image import numpy as np a = np.array(Image.open('favicon.png').convert('RGB')) ch = a[:, :, 1].flatten() & 1 # green channel LSB, row-major bs = np.packbits(ch.astype('uint8')).tobytes() # MSB-first packing print(bs.split(b'\x00')[0].decode()) # -> BugCTF{REDACTED}
zsteg setup and confirmation:
bash read-only • copy allowedgem install --user-install zsteg ~/.gem/ruby/2.6.0/bin/zsteg -a favicon.png # flags channel b1,g,lsb,xy
The flag text _tREDACTED self-confirms the result and
explicitly contrasts with the decoy hint.