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 carrier

If any of these flag something unusual, pivot to the format-specific tool below.


Format triage

CarrierFirst reachWhy
PNG / BMPzsteglossless formats preserve LSB; bit-plane analysis is viable
JPEGsteghide infolossy DCT; steghide is the dominant JPEG steg tool
WAV / AUsteghide info + spectrogramsteghide supports both; audio also hides images in frequency domain
MP4 / MKVffmpeg frame extract → image steg per framedata may live in frames, audio track, metadata, or appended bytes
TXT / DOCXwhitespace + unicode + zip inspectDOCX 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 count

Recovered 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 payload

Output 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 ancillary

Red flags in PNG:

  • bytes appended after the IEND chunk (carve them out with dd 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.txt

For 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 images

Document 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-8

Pitfalls

  • -o for foremost requires fresh dir; same convention for any extraction. Make a clean working directory first.
  • steghide extract writes the payload silently with the original filename if found — check ls before and after.
  • stegseek writes to the source file’s directory by default; use a copy if you want the original untouched.
  • zsteg -a is slow on large PNGs; default scan first.
  • binwalk -e extracts 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.

Field Manual | Steganography | Data Recovery | File Carving