ctf-stego

Original🇺🇸 English
Translated

Steganography techniques for CTF challenges. Use when data is hidden in images, audio, video, or other media files.

1installs
Added on

NPX Install

npx skill4agent add ramzxy/ctf ctf-stego

Tags

Translated version includes tags in frontmatter

CTF Steganography

Quick Start — Try These First

bash
# Basic analysis
file image.png
exiftool image.png          # EXIF metadata (flags hide here!)
strings image.png | grep -iE "flag|ctf"
binwalk image.png           # Embedded files
xxd image.png | tail        # Data appended after EOF

# Steganography tools
steghide extract -sf image.jpg          # JPEG stego (tries empty password)
steghide extract -sf image.jpg -p ""    # Explicit empty password
zsteg image.png                         # PNG/BMP LSB analysis
stegsolve                               # Visual bit-plane analysis (GUI)

Image Steganography

LSB (Least Significant Bit)

The most common image stego technique. Data hidden in the least significant bits of pixel values.
python
from PIL import Image

img = Image.open('image.png')
pixels = list(img.getdata())

# Extract LSB from each channel
bits = ''
for pixel in pixels:
    for channel in pixel[:3]:  # R, G, B
        bits += str(channel & 1)

# Convert bits to bytes
flag = bytes(int(bits[i:i+8], 2) for i in range(0, len(bits), 8))
print(flag)
Tools:
  • zsteg
    — Automated LSB analysis for PNG/BMP (try
    zsteg -a image.png
    )
  • stegsolve
    — Visual analysis, toggle bit planes
  • Stegano
    — Python library:
    pip install stegano

Pixel Value Encoding

python
# Values ARE the data (not hidden in LSB)
from PIL import Image
img = Image.open('image.png')
pixels = list(img.getdata())

# Each pixel R value is an ASCII char
flag = ''.join(chr(p[0]) for p in pixels if 32 <= p[0] < 127)

# Or pixel coordinates encode data
# Or specific color pixels spell out a message

Image Format Tricks

PNG chunks:
bash
pngcheck -v image.png        # Validate and list chunks
python3 -c "
import struct
with open('image.png', 'rb') as f:
    data = f.read()
# Look for custom chunks (tEXt, zTXt, iTXt)
idx = data.find(b'tEXt')
if idx > 0:
    print(data[idx:idx+100])
"
JPEG markers:
bash
# Data after JPEG EOF marker (FF D9)
python3 -c "
with open('image.jpg', 'rb') as f:
    data = f.read()
eof = data.find(b'\xff\xd9')
if eof > 0 and eof + 2 < len(data):
    print(f'Data after EOF: {data[eof+2:eof+102]!r}')
"
BMP:
bash
# BMP has a data offset field — gap between header and pixel data can hide data
xxd image.bmp | head -5
GIF:
bash
# GIF frames may contain hidden data
ffmpeg -i image.gif frame_%03d.png  # Extract all frames
identify -verbose image.gif          # Frame details

Image Dimension Tricks

Wrong dimensions in header:
python
# PNG: Fix height to reveal hidden rows
import struct, zlib

with open('image.png', 'rb') as f:
    data = bytearray(f.read())

# PNG IHDR chunk starts at offset 16 (width at 16, height at 20)
# Try increasing height
struct.pack_into('>I', data, 20, 1000)  # Set height to 1000

with open('fixed.png', 'wb') as f:
    # Recalculate IHDR CRC
    ihdr_data = data[12:29]
    crc = zlib.crc32(ihdr_data) & 0xffffffff
    struct.pack_into('>I', data, 29, crc)
    f.write(data)

Steghide (JPEG/WAV/BMP/AU)

bash
steghide extract -sf file.jpg -p "password"
steghide info file.jpg                      # Check if data is embedded

# Brute force password
stegcracker file.jpg wordlist.txt
# Or use stegseek (much faster)
stegseek file.jpg wordlist.txt

Visual Steganography

  • Flags as tiny/low-contrast text in images
  • Black text on dark background, white on light
  • Check ALL corners and edges at full resolution
  • Profile pictures and avatars are common hiding spots
  • Zoom in on what looks like solid color areas

Audio Steganography

Spectrogram Analysis

bash
# Generate spectrogram image
sox audio.wav -n spectrogram -o spectrogram.png

# Or use Audacity: View → Spectrogram
# Look for text/images drawn in frequency domain

SSTV (Slow-Scan Television)

bash
# Decode SSTV signal from audio
qsstv                    # GUI decoder
# Or sstv Python package
pip install sstv
sstv -d audio.wav -o output.png

DTMF Tones

bash
# Phone keypad tones
multimon-ng -t wav -a DTMF audio.wav
# Or via sox + multimon-ng:
sox audio.wav -t raw -r 22050 -e signed-integer -b 16 -c 1 - | multimon-ng -t raw -a DTMF -

Audio LSB

python
import wave
import struct

wav = wave.open('audio.wav', 'rb')
frames = wav.readframes(wav.getnframes())
samples = struct.unpack(f'<{len(frames)//2}h', frames)

# Extract LSB from samples
bits = ''.join(str(s & 1) for s in samples)
data = bytes(int(bits[i:i+8], 2) for i in range(0, len(bits), 8))
print(data[:100])

Morse Code

bash
# Visual: look at waveform for long/short patterns
# Audio: listen for dots and dashes
# Automated: use online morse decoder or:
pip install morse-audio-decoder

Text/Data Steganography

Whitespace Stego

bash
# Zero-width characters in text
python3 -c "
with open('text.txt', 'rb') as f:
    data = f.read()
# Zero-width space: U+200B, Zero-width joiner: U+200D
for b in data:
    if b in [0xe2]:  # Start of multi-byte UTF-8
        print(f'Found zero-width char at position')
"

# snow tool for whitespace stego
snow -C -p "password" stego.txt

Unicode Stego

  • Homoglyph substitution (Cyrillic а vs Latin a)
  • Invisible Unicode characters between visible text
  • Variation selectors and combining characters

File Concatenation / Polyglots

bash
# Multiple files concatenated
binwalk suspicious_file        # Find embedded files
foremost suspicious_file       # Carve out files

# ZIP at end of image
unzip image.png                # Works if ZIP appended after image data

# PDF + ZIP polyglot
# File is valid as both PDF and ZIP

Network Steganography

PCAP Hidden Data

  • DNS queries encoding data in subdomain labels
  • ICMP payloads carrying hidden messages
  • TCP sequence numbers encoding data
  • HTTP headers with encoded data
  • TLS certificate fields

DNS Exfiltration

bash
tshark -r capture.pcap -Y "dns.qry.name" -T fields -e dns.qry.name | \
    sed 's/\.example\.com//' | tr -d '\n' | base64 -d

Common Patterns

ClueTechnique
"Look closer" / "More than meets the eye"LSB or visual stego
Image looks normal but file is hugeEmbedded/appended data
Audio with static/noise sectionsSpectrogram or SSTV
"Password protected"Steghide with password
PNG with wrong colors or glitchesBit plane analysis
Text file with trailing whitespaceWhitespace stego
Challenge says "nothing to see here"Definitely stego