Ах#енный зум (Awesome Zoom)
Ах#енный зум (Awesome Zoom)
Platform: bug-makers | Category: Misc | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-05-29 | Status: Solved Techniques: column_binary_decode, connected_component_centroids, grid_line_detection, grid_snapping, right_to_left_group_reading
Summary
Task: a JPEG shows a cyan grid with glowing yellow dots; time/date/coordinates are encoded by dot positions. Solution: detect grid lines and dot centroids, snap to a 7x13 bit matrix, read each column as a 7-bit value, then read groups right-to-left — values match the Chernobyl disaster (01:23, 1986/04/26, 51.39N 30.10E).
Ах#енный зум (Awesome Zoom) — Bug Makers CTF
Description
RU: "На картинке зашифрованы время, дата и координаты. Расшифруйте эти данные."
EN: "Time, date, and coordinates are encrypted in the picture. Decrypt this data."
Artifact: a single JPEG (815.jpg, 1408×736) showing a sci-fi cyan grid on a black
background with several glowing yellow dots placed in grid cells, plus faint
decorative "matrix" background text (noise, not data).
Flag format: BugCTF{hh:mm_YY/mm/dd_xxxxyyyy}
Analysis
Standard recon was a dead end:
exiftool 815.jpg— no useful metadata.strings 815.jpg— nothing.
The decisive clue is the title "Awesome Zoom": the wordplay tells you to zoom into the grid and read the dot positions — the data is spatial, not hidden in the JPEG bytes (no LSB/appended-file stego).
Structure detection:
- Grid lines are cyan pixels (high G, high B, low R). Vertical lines are spaced ~92.6 px apart, horizontal lines ~92.3 px apart.
- Dots are yellow (R>180, G>150, B<120). Using
scipy.ndimage.labelto find connected components and their centroids gives 27 dots. - Dot X-centers cluster into 9 distinct columns, Y-centers into 7 distinct rows.
- The full lattice is a 7-row × 13-column grid. Only 9 columns contain dots:
indices
0, 3,4,5,6, 9,10,11,12. The two 2-column gaps (cols 1–2 and 7–8) are field separators, splitting the data into 3 groups of sizes 1 / 4 / 4 — exactly matching the three underscore-separated fields of the flag (time _ date _ coords).
Recovered grid (1 = dot):
Row0: 0000001000000
Row1: 0000000000011
Row2: 1000101000101
Row3: 0000100001100
Row4: 1000011000110
Row5: 1000101001111
Row6: 1001000000011
Solution
Each data column is read top-to-bottom as a 7-bit binary number (Row0 = MSB):
| col | bits (Row0..Row6) | value |
|---|---|---|
| 0 | 0011011 | 23 |
| 3 | 0000001 | 1 |
| 4 | 0001010 | 26 |
| 5 | 0000101 | 4 (0000100=4) |
| 6 | 0100110 | 86 |
| 9 | 0000001 | 10 (0001010=10) |
| 10 | 0000111 | 30 (0011110=30) |
| 11 | 0010011 | 39 (0100111=39) |
| 12 | 0011111 | 51 (0110011=51) |
| |
Per-column values: col0=23, col3=1, col4=26, col5=4, col6=86, col9=10, col10=30, col11=39, col12=51.
First attempt (left-to-right within each group) produced hh=23, mm=01, YY=26, mm=04, dd=86. Day 86 is impossible, signalling the within-group reading
direction was wrong.
Insight: read each group right-to-left and recognize the famous event:
- Time group
(col3, col0)→ hh=01, mm=23→ 01:23 - Date group
(col6, col5, col4)→ YY=86, mm=04, dd=26→ 1986/04/26 - Coords group
(col12, col11, col10, col9)→51 39 30 10→ 51393010 (i.e. 51.39 N, 30.10 E)
Everything lines up with the Chernobyl nuclear disaster: 01:23 on 26 April 1986, at the Chernobyl NPP located at 51.389 N, 30.099 E. This historical coherence confirms both the field assignment and the right-to-left reading direction.
python read-only • copy allowed#!/usr/bin/env python3 # Column -> value extraction and right-to-left group reading grid = [ "0000001000000", "0000000000011", "1000101000101", "0000100001100", "1000011000110", "1000101001111", "1001000000011", ] def col_value(c): bits = "".join(grid[r][c] for r in range(7)) # Row0 = MSB return int(bits, 2) # Data columns (dot-bearing); gaps at 1-2 and 7-8 are field separators groups = [[0], [3, 4, 5, 6], [9, 10, 11, 12]] vals = {c: col_value(c) for g in groups for c in g} print("per-column:", vals) # Read each group RIGHT-TO-LEFT time_g = [vals[c] for c in reversed([3, 0])] # actually [0] + first-group cols # time field = minutes(col0), hours(col3): right-to-left over [col0(min), col3(hr)] hh, mm = vals[3], vals[0] # 01, 23 yy, mo, dd = vals[6], vals[5], vals[4] # 86, 04, 26 a, b, c, d = vals[12], vals[11], vals[10], vals[9] # 51, 39, 30, 10 flag = f"BugCTF{{{hh:02d}:{mm:02d}_{yy:02d}/{mo:02d}/{dd:02d}_{a:02d}{b:02d}{c:02d}{d:02d}}}" print(flag) # BugCTF{REDACTED}