Forensic detection and extraction of steganographic payloads. Format-driven tool selection (PNG/BMP → zsteg, JPEG/WAV/AU → steghide, all → binwalk + exiftool + strings). Steghide cracking with stegseek. Verified against Kali: steghide 0.5.1, binwalk 2.4.3, exiftool. zsteg via gem install zsteg; stegseek via apt install stegseek or release binary.
Side: blue
Triage workflow
Run these four commands first on any suspect media file. ~1 minute, narrows the search before you reach for format-specific tools.
file suspect # real file type — extension can lie
exiftool suspect # metadata, comments, GPS, author, software
strings -n 8 suspect # readable text >= 8 chars (flags, base64, paths)
binwalk suspect # embedded file signatures inside the carrierIf any of these flag something unusual, pivot to the format-specific tool below.
Format triage
| Carrier | First reach | Why |
|---|---|---|
| PNG / BMP | zsteg | lossless formats preserve LSB; bit-plane analysis is viable |
| JPEG | steghide info | lossy DCT; steghide is the dominant JPEG steg tool |
| WAV / AU | steghide info + spectrogram | steghide supports both; audio also hides images in frequency domain |
| MP4 / MKV | ffmpeg frame extract → image steg per frame | data may live in frames, audio track, metadata, or appended bytes |
| TXT / DOCX | whitespace + unicode + zip inspect | DOCX is a zip; check for embedded objects |
steghide
Most-seen JPEG/WAV/AU steg tool. Passphrase-protected. Optional encryption.
steghide info file.jpg # check if data is embedded
steghide extract -sf file.jpg -p passphrase # extract with known passphrase
steghide extract -sf file.jpg -p "" # try empty passphrase first
steghide embed -cf cover.jpg -ef secret.txt -p pwd # embed (analyst rebuild / reproduction only)-sf = stego file (input). -cf = cover file. -ef = embed file (payload). -p = passphrase.
stegseek (steghide passphrase brute force)
Fastest known steghide cracker. Targets steghide’s specific passphrase derivation.
stegseek file.jpg /usr/share/wordlists/rockyou.txt # brute force, stops on first hit
stegseek --crack file.jpg wordlist.txt # same; prints passphrase
stegseek --threads 8 file.jpg rockyou.txt # cap thread countRecovered payload is written to file.jpg.out and the passphrase to file.jpg.txt in the working directory by default. Both go into your evidence record.
zsteg (PNG / BMP LSB)
Primary tool for LSB-based steg in lossless images. Ruby gem (gem install zsteg).
zsteg suspect.png # default scan (most common bit/channel/order combos)
zsteg -a suspect.png # all methods (slower, broader)
zsteg -b 1 suspect.png # specific bit plane (1-8)
zsteg -E "b1,rgb,lsb,xy" suspect.png # extract one specific payloadOutput decoder for b1,r,lsb,xy notation: bit plane 1, red channel, LSB-first, row-by-row scan order. Each unique line in zsteg output is a candidate payload to extract.
binwalk (embedded files in any carrier)
binwalk suspect # scan signatures only
binwalk -e suspect # extract embedded files to _suspect.extracted/
binwalk --dd='.*' suspect # extract every recognised type, no filtering
binwalk -B suspect # also run signature scan against extracted
binwalk -A suspect # opcode analysis (architecture detection)Pair binwalk extracted output with file * to triage what came out. Frequent finds: zip-in-image, JPEG-in-MP3, executables prepended or appended to media.
PNG-specific forensic checks
pngcheck suspect.png # corruption, extra chunks, bad CRC
xxd suspect.png | grep -i 'iend' # PNG ends with IEND - bytes after that are suspicious
pngcheck -v suspect.png # list all chunks, including ancillaryRed flags in PNG:
- bytes appended after the
IENDchunk (carve them out withdd skip=<offset>) - non-standard ancillary chunks (
tEXt,zTXt,iTXt) containing payloads - IHDR width/height that doesn’t match visible content (image cropped to hide bottom rows; fix in hex editor)
- bad CRC on chunks (intentional corruption to confuse parsers)
Audio carriers
exiftool file.wav # metadata first
strings file.wav # readable text, base64
binwalk file.wav # embedded files
# steghide on WAV / AU
steghide info file.wav
steghide extract -sf file.wav -p passphrase
stegseek file.wav /usr/share/wordlists/rockyou.txtFor frequency-domain steg, open in Sonic Visualiser (Layer > Add Spectrogram) or Audacity (Analyze > Plot Spectrum then switch to spectrogram view). Visible images, text, or DTMF tones in the spectrogram are common payload patterns.
Metadata fields worth pulling
exiftool -a -u -g1 file # all tags, unknown tags, grouped
exiftool -GPSLatitude -GPSLongitude -GPSPosition file # location
exiftool -Comment -UserComment -XPComment file # common payload-bearing comment fields
exiftool -Author -Creator -Software file # provenance
exiftool -all= file # strip all metadata (for size-comparison test)
diff <(exiftool -a a.jpg) <(exiftool -a b.jpg) # compare two suspect imagesDocument carriers
unzip suspect.docx -d extracted/ # DOCX is a zip - inspect contents
strings suspect.pdf
pdfid suspect.pdf # scan for /JS, /JavaScript, /AA, /OpenAction
pdf-parser suspect.pdf # walk PDF objects
# whitespace steganography in plain text
stegsnow -C file.txt # extract trailing-whitespace payload
stegsnow -C -p passphrase file.txt # passphrase-protected variant
# zero-width unicode steg
xxd file.txt | grep -i 'e2 80 8[bcd]' # ZWSP, ZWNJ, ZWJ in UTF-8Pitfalls
-ofor foremost requires fresh dir; same convention for any extraction. Make a clean working directory first.steghide extractwrites the payload silently with the original filename if found — checklsbefore and after.stegseekwrites to the source file’s directory by default; use a copy if you want the original untouched.zsteg -ais slow on large PNGs; default scan first.binwalk -eextracts to_suspect.extracted/(note the underscore prefix); don’t lose track of where output landed.- Cracked passphrases and recovered payloads both go into the evidence record. Hash both.