The Word Hidden Across Five Channels | Isodata Seven | GaianSpace CTF 2026
đ ä¸ćçďźçšéŤä¸ć
Third post in the series. After the demodulator got its skeleton in True Color Is a Lie, this one swaps in new parameters (implicit header) and upgrades the stego trick from subtracting two copies to clustering across multiple channels.
Rest of the series: Channel HopăSubsidy ClaimăTwo VoicesăNo Name on the DoorăHopscotch
What the challenge is about

Since dawn the tractor has stopped listening to the mast and started listening to a different, unknown transmitter. The Johnripper terminal receives tiles under the dealerâs proprietary settings, and the dealer wonât publish those settings. Babb only has photocopies of pages 14 and 16 of the service manual. Page 15, in between, is missing.
The shared SDR was moved into the tractor shed and recorded that channel. What the stranger sends to the tractor is a whole tile (all channels), and it looks real, except for one patch in the north field that Babb canât explain.
In the margin of the course notes, double-underlined: âcount what actually grows here.â
Goal: find what the stranger planted in the tile. The files given are a ~213 MB .sigmf-data, manual pages 14/16, and the remote-sensing course notes.
Flag format: GAIANSPACE{...}.
This time itâs an implicit header
The radio parameters (manual page 14) are 433.4 MHz, SF7, BW500k, CR4/5, sync word 0x2C, 10-symbol preamble, and no RF header (fixed-length frames).
The missing page 15 holds the frame-length table, so weâll have to infer it from the data.
Reusing the demodulator skeleton from the last post, the difference here is the implicit header: the first 8 symbols are a low-rate block (CR4/8), after which every 5 symbols form a block; the length is inferred from how many symbols the packet spans in the air.
Once all 779 frames pass the CRC-16 check from manual page 16, they reconstruct into five 128Ă128 grayscale images:

Looked at one channel at a time, that patch looks like random noise in every one, unlike the previous challenge. Thatâs probably exactly what the challenge means by âno band leaks anything.â
First, understand what this âimageâ is
A satellite doesnât take an ordinary RGB camera photo. It records different wavelengths of light separately, storing each wavelength as its own channel (band).
This challenge uses three kinds:
- Visible light: the red/green/blue your eyes can see. A healthy plantâs chlorophyll absorbs red light, so vegetation looks dark in visible light while bare soil looks bright.
- Near-infrared (NIR): a bit longer in wavelength than red, invisible to the eye. Healthy leaf tissue reflects NIR strongly, so âhigh NIRâ is almost the same as âthis is a living plant.â
- Short-wave infrared (SWIR): longer still, and especially sensitive to water. More water (wet soil, after irrigation, moist leaves) absorbs SWIR and looks dark; dry ground looks bright in SWIR.
So every pixel carries a little fingerprint: bright or not in visible light, high or low in NIR, high or low in SWIR. Feed those fingerprints to a clustering algorithm and pixels with similar fingerprints get grouped together.
ISODATA / k-means: count what grows here
The course notes hint at using ISODATA with 7 classes (ISODATA is a common unsupervised clustering method in remote sensing, conceptually just k-means).
Running k-means on the 5-dimensional pixels of the noisy patch, the error drops sharply at k=4 (adding more classes beyond that only lowers it slowly), which says the patch really has only 4 true classes. And those 4 arenât random. Theyâre exactly the combinations of two switches, each with only two values:
| Class | Visible | NIR | SWIR |
|---|---|---|---|
| vegetation-like + SWIR low | dark | high | low |
| vegetation-like + SWIR high | dark | high | high |
| soil-like + SWIR high | bright | low | high |
| soil-like + SWIR low | bright | low | low |
Read the table as two switches and itâs clear:
- Switch A: does this patch âlook like vegetationâ or âlook like soilâ (decided by visible dark/bright and NIR high/low).
- Switch B: is SWIR âhighâ or âlow.â
A Ă B = 2 Ă 2 = 4, which lines up perfectly with k=4.
Hereâs the key. Normally these two switches pair up naturally (real vegetation shows the combination youâd expect for A and B). But the strangerâs trick is to secretly flip switch B only on the pixels that âdraw the text.â The result:
- Looking at NIR alone: the text pixels and the background are both âvegetationâ (same A), so thereâs no visible difference â nothing leaks.
- Looking at SWIR alone: the text pixels just happen to have SWIR flipped, but SWIR is high and low all over the place anyway, so it looks like noise â nothing visible there either.
- Only by comparing âwhether A and B agreeâ does the text appear. In digital terms, you XOR the two switches: agree = 0, disagree = 1, and the text is painted exactly on the pixels where XOR = 1.
Thatâs why you must cluster rather than look at a single channel: clustering considers all channelsâ fingerprints at once, so it naturally groups the self-contradictory pixels (âA says vegetation but B is flippedâ) into their own small classes, and those small classes are the text. Running k=7 clustering over the whole image, those two âcontradictoryâ small classes each show part of the text:

Merge those two classes and draw them, and three lines of text clearly emerge:

Reading the last line
The font is a âboldâ variant: each character is a 5Ă6 base glyph plus a copy shifted 1 pixel to the right.
I used the already-known letters in the first two lines (GAIANSPACE{, 7TH-CLASS-) as a reference and confirmed the last line cell by cell. I hesitated between W/V here; W turned out to be correct.
Flag
1 | GAIANSPACE{7TH-CLASS-XHTXWX} |
Takeaways
- The âimplantâ here isnât painted into one channel. Itâs the text split into two noisy halves (XOR) spread across different bands. Any single channel is just noise; it only appears when you look at all channels at once (clustering), echoing the noteâs line, âthe computer only knows which pixels look alike in all channels at once.â
- The k-means error curve tells you how many classes really exist. The error plunges at k=4 and only crawls down afterwards, which is the implementation of the noteâs âcount what actually grows here.â
- You donât need the missing manual page. Frame length, channel, and row number can all be inferred directly from the field layout in the data.
- For a tiny font, figure out the drawing rule before reconstructing the glyphs. This one is âbold, shifted 1 pixel rightâ. Once you know the rule, cell-by-cell comparison is more reliable than just eyeballing a zoomed image.

