← Back to Writeups
CUSTOMMediumSteganography

Миша любит CTF

XESXOR9/2/20264 min read
#steganography#custom#medium#bit_offset_alignment#bit_plane_extraction#lsb_extraction#msb_first_repacking#printable_string_search

Миша любит CTF

Platform: TaipanByte | Category: Steganography | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-02-14 | Status: Solved Techniques: bit_offset_alignment, bit_plane_extraction, lsb_extraction, msb_first_repacking, printable_string_search

Summary

Task: a local MP4-like container with H.264 video, AAC audio, and a visibly corrupted region suggested hidden content in the media stream. Solution: ignore the repair rabbit hole, extract byte LSBs as a bitstream, shift by the correct offset, repack MSB-first, and recover the flag text.

Миша любит CTF — TaipanByte

Overview

This was a local-only challenge built around the file ready.tb. Initial inspection showed that it was an MP4 container carrying H.264 video and AAC audio. A corrupted P-slice around 5.52 seconds produced decoder errors and strong visual glitches, which made codec damage look like the intended path.

That turned out to be a red herring. The flag was recovered by treating the file bytes as a raw bitstream, extracting the least significant bit of each byte, applying the correct bit offset, repacking bits into bytes in MSB-first order, and searching the reconstructed stream for printable text. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Recon

No organizer description was preserved locally; the available artifacts were ready.tb, plus derived analysis files raw.h264 and bad_packet.bin.

The useful starting observations were:

  • ready.tb is an MP4 container.
  • The video stream is H.264 and the audio stream is AAC.
  • There is a corrupted H.264 P-slice around 5.52s.
  • FFmpeg emitted errors such as:
text
Reference 4 >= 4
error while decoding MB 182 40, bytestream 73913

Those messages strongly suggested that a broken packet or damaged reference chain might hide the payload. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Dead Ends

Most of the time went into investigating the corruption itself.

I examined the glitched region, isolated the bad packet, extracted raw.h264, and checked whether the broken slice or visual artifacts concealed an image or secondary payload. I also looked for standard embedded-file signatures such as PNG, JPEG, GIF, WEBP, TIFF, and common archives. No genuine embedded file was present. One apparent BMP signature was only a false positive.

I also tried image-style processing on glitch frames, including PCA-oriented inspection and mean/median/std style aggregation. Those experiments did not reveal any hidden image or message. In hindsight, the H.264 corruption was only a very convincing distraction. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

bad_packet.bin was also tested with the same extraction idea later, but it did not produce an equivalent hit.

Actual Solve

The successful approach was fully byte-oriented.

Method

  1. Read the file as raw bytes.
  2. Treat every byte as a source of one candidate hidden bit.
  3. Extract bit-plane 0, i.e. the least significant bit of each byte.
  4. Apply a bit offset.
  5. Repack every 8 bits into bytes using MSB-first order.
  6. Scan the reconstructed byte stream for printable text and flag-like substrings. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Working parameters

  • ready.tb: bit 0, bit offset 4, packing MSB-first
  • raw.h264: bit 0, bit offset 2, packing MSB-first
  • bad_packet.bin: no equivalent result

Running the method against ready.tb produced a stream containing:

text
vstgCTF{REDACTED}

The accepted flag is the meaningful substring:

text
CTF{REDACTED}

Applying the same bit-plane extraction idea to raw.h264 independently revealed the same flag region. That duplicate hit is a strong validation that the stego signal lived in the video byte stream itself, not in an unrelated container artifact. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Script

python
#!/usr/bin/env python3
import re
from pathlib import Path


def extract_plane(data: bytes, bit: int = 0, offset: int = 4) -> bytes:
    bits = [(b >> bit) & 1 for b in data]
    bits = bits[offset:]

    out = bytearray()
    for i in range(0, len(bits) - 7, 8):
        value = 0
        for j in range(8):
            value = (value << 1) | bits[i + j]
        out.append(value)
    return bytes(out)


def printable_runs(buf: bytes, min_len: int = 8):
    return re.findall(rb"[ -~]{%d,}" % min_len, buf)
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍


def main() -> None:
    data = Path("ready.tb").read_bytes()
    recovered = extract_plane(data, bit=0, offset=4)

    for s in printable_runs(recovered):
        text = s.decode("ascii", errors="ignore")
        if "CTF{" in text:
            print(text)
            m = re.search(r"CTF\{[^}]+\}", text)
            if m:
                print("FLAG:", m.group(0))
                break


if __name__ == "__main__":
    main()

Expected output includes the recovered text region:

text
vstgCTF{REDACTED}
FLAG: CTF{REDACTED}

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

Takeaways

  • A visibly corrupted media stream can be a red herring rather than the payload location.
  • If container carving, signature checks, and frame analysis all fail, try direct bit-plane extraction on the raw bytes.
  • Re-testing the same method on both the container and the demuxed elementary stream is a good validation step.
  • Bit offset and bit packing order matter; one wrong alignment is enough to hide otherwise obvious text. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍