When to Use / When Not to Use
- Use: steganography suspicion (CTF challenge/forensic target), abnormal end-of-file, image/audio anomalies (size/noise/file structure mismatch)
- Use: abnormal file structure (data still present after IEND/EXIF segment oversized/pixel count and file size mismatch)
- Use: multi-carrier combinations (common in challenges/forensic scenarios—multiple files each hiding a part)
- Use: forensic scenarios unallocated space/file system residual scanning (in conjunction with [[re-disk-forensics]])
- Do not use: normal file analysis (each belongs to its own domain skill); encrypted data decryption (ciphertext ≠ steganography, payload decryption goes to [[re-crypto-decrypt]]); unknown file type identification ([[re-triage]] first)
- Do not use: aimless scanning with no carrier clues (have suspicious characteristics first before acting, see [[decision-tree]])
Tool Preparation
zsteg (image LSB scanning)
- Multi-platform:
gem install zstegor source code (GitHub) - Verify:
zsteg -horgem list zsteg - Coverage: PNG/BMP support is good, GIF support is limited—for GIF carriers switch to the python script path
steghide (image/audio steganography)
- Linux:
apt install steghide/dnf install steghide;macOS:brew install steghide - Verify:
steghide --version;steghide info file.jpg(check whether data is embedded, no password needed)
binwalk (trailing scan)
- Installation and verification see [[re-fw-extract]] Tool Preparation
Other detection/extraction tools
- exiftool (EXIF/metadata): Linux
apt install libimage-exiftool-perl/dnf install perl-Image-ExifTool;macOSbrew install exiftool; verifyexiftool -ver - pngcheck (PNG structure validation/anomalies): Linux
apt install pngcheck;macOSbrew install pngcheck; verifypngcheck -v - sox (audio processing/spectrogram): Linux
apt install sox;macOSbrew install sox; verifysox --version - foremost (data carving, forensic scenarios):
apt install foremost/brew install foremost - stegsolve (bit-plane by bit-plane viewing, Java GUI): download jar from GitHub (
java -jar stegsolve.jar) - outguess (JPEG DCT domain, old tool): Linux
apt install outguess - ffmpeg (audio format conversion, optional):
apt install ffmpeg/brew install ffmpeg - python3 (bit manipulation/verification scripts + PIL): installation see [[re-python]];
pip install pillow; verifypython3 -c "from PIL import Image"
Procedure
Execute in order, archive each step's output (path + sha256, see [[re-triage]]).
-
End-of-File Appending Detection:
binwalk sample.png | tail -20 # 附加数据扫描 hexdump -C sample.png | tail -10 # 尾部目检- Trailing appending: file is normal but there is extra data at the end (connect with trailing appending experience ([[re-patching]] patch creation approach))
- Structure check:
pngcheck -v sample.pnglook at the gap between the IEND position and the end of file (the difference ≈ amount of appended data) - Quick scan for weak clues:
strings -a sample.png | grep -iE 'flag|ctf|http' - Size check: clearly inconsistent with the claimed content (e.g., a 3MB "small image") is a weak clue
- Extraction: binwalk automatic splitting or dd extraction by offset (
dd if=sample.png of=tail.bin bs=1 skip=<偏移>) → magic check ([[re-triage]]) - EXIF viewing:
exiftool -a sample.jpg(list all segments, abnormal fields/large comment blocks are suspicious) - Other file redundant areas: EXIF metadata (view with exiftool), file header reserved areas, unused space in compressed files
-
Image LSB:
zsteg sample.png # 全通道 LSB 扫描 zsteg -E 'b1,rgb,lsb,xy' sample.png # 指定通道/位平面提取- Channels: lowest bit of each RGB/alpha channel; bit planes: b1/b2 (lowest 2 bits)—the alpha channel is also often used for hiding
- Common zsteg parameters:
-afull-channel scan,-vverbose output,-Especify extraction; output interpretation:b1,rgb,lsb,xyline = extraction result for that plane, allfailed≈ no steganography in that plane - Order: row order/bit order affects extraction results (see Pitfall 1; for enumerated combinations see the extraction failure branch in [[decision-tree]])
- Script path when no tool is available: python3 + PIL traverse pixels to extract the bit sequence (
getpixeltake channel low bit → concatenate bit sequence → convert to bytes; refer to the order pitfall in [[gotchas]]) - Script enumeration template: triple loop over row order × bit order × channel, output a file for each combination and check them one by one with
filecheck - stegsolve bit-plane-by-bit-plane viewing (GUI): compare multiple plane images, look for visual patterns (common in LSB image steganography)
-
Other carriers:
- Audio: spectral steganography (sox spectrogram:
sox in.wav -n spectrogram -o out.pngthen visually inspect frequency-domain patterns), steghide extraction (steghide extract -sf file.wav), phase/echo steganography - Audio branch: first look at the waveform/spectrum (frequency-domain patterns shaped like text/QR codes → spectral steganography), then handle separately by time domain (LSB type, steghide) and frequency domain (phase/echo, requires specialized tools)
- Image DCT domain (JPEG): outguess-type tools (old tools, limited support for new formats, see [[gotchas]])
- File redundant areas: EXIF, file header reserved areas, unused space in compressed files (CRC/unused space in ZIP)
- Other carriers: text (whitespace characters/line spacing), web pages (comments/hidden tags) — extend according to the scenario
- Multi-carrier combinations (commonly used in challenges): concatenate fragments from each file (by order/by feature association, refer to the metadata preliminary survey in [[re-triage]])
- Audio: spectral steganography (sox spectrogram:
-
Extraction verification:
- magic check (header features of the extracted artifact)
- Readability verification (strings/file)
- Re-detect the extracted artifact: the extracted file itself may contain further hidden data (nesting) — run the extracted artifact through the complete workflow; if it is a script/archive, continue according to the corresponding domain ([[re-script-deob]] / [[re-python]], etc.)
- Verify the artifact: only when the extracted artifact's
filetype matches expectations can it be determined as "confirmed embedding" (see the grading table in [[decision-tree]]) - Compression before steganography: extract first, then decompress (check the compressed header in the extracted artifact — zlib
78 9C/ gzip1F 8B/ bzip242 5A 68, see Pitfall 3) - Encrypted payload: when there is no key, mark it as not extractable (do not brute-force); if there are key clues, go to [[re-crypto-decrypt]]
Cross-domain combination
- [[re-ctf]] gateway: this skill belongs here
- [[re-fw-extract]]: binwalk reuse
- [[re-patching]]: connection with tail-appending experience
- [[re-triage]]: preliminary survey of extracted artifacts
- [[re-crypto-decrypt]]: connection with payload decryption
- [[re-disk-forensics]]: unallocated space/file-system-side steganography (forensics scenarios)
Common pitfalls and traps
- LSB order: symptom — garbled extraction; cause — row order (top-to-bottom/bottom-to-top)/bit order (LSB first/MSB first); countermeasure — tools automatically try or scripts enumerate combinations
- Multi-carrier misjudgment: symptom — multiple steganographic layers in one file; cause — nested steganography; countermeasure — layered extraction, verify each layer
- Compression before steganography: Symptom — extracted data is garbled; Cause — plaintext was compressed before being embedded; Countermeasure — first check for compression signatures (zlib/gzip/bzip2 headers) then decompress
- Tool output noise: Symptom — a large number of candidates; Cause — scan output contains false positives; Countermeasure — filter by magic/readability
- The carrier itself is abnormal: Symptom — the file is corrupted; Cause — steganographic writing damaged the structure; Countermeasure — repair first/tolerate corruption (bitwise extraction does not depend on structure)
- JPEG lossy confusion: Symptom — LSB extraction yields noise; Cause — JPEG lossy compression overwrites the bit planes (LSB-type steganography mainly targets PNG/BMP, JPEG uses the DCT domain); Countermeasure — determine the format first (pngcheck) then choose the method
- Entropy false positive: Symptom — a scan reports "steganography present" but there is no content; Cause — compressed/random data is naturally high-entropy; Countermeasure — entropy characteristics serve only as a suspicion clue, not as standalone proof (see [[decision-tree]] for determination grading)
- steghide password: Symptom — extraction without a password fails; Cause — a passphrase is required (CTFs often provide a hint); Countermeasure — first try without a password, then try based on hints/key clues, and if none, annotate it
- Single-tool blind spot: Symptom — zsteg returns no results but steganography is present; Cause — the channels/algorithms covered by the tool are limited; Countermeasure — cross-check with multiple paths: zsteg + steghide + scripts
- Carrier copy differences: Symptom — the same file from different sources gives different scan results; Cause — the copy was transcoded/compressed; Countermeasure — use the original carrier (verify by hash, see [[re-triage]])
- Challenge/scenario hints ignored: Symptom — you scan the image for ages, but the payload is actually in an accompanying file; Cause — multi-carrier hints were not read; Countermeasure — read the hints first, and split carriers according to the hints
- Confusing the compression layer with the steganography layer: Symptom — treating the randomness of compressed data as a steganography clue; Cause — compressed content is naturally high-entropy; Countermeasure — decompress first, then analyze the content (compression is not steganography)
- Three-branch determination of garbled data: Symptom — content is extracted but looks garbled; Cause — it may be compression/encryption/wrong order, or it may simply be random padding; Countermeasure — follow the extraction-failure branch of [[decision-tree]] based on compression headers/readability/statistical distribution
- See [[decision-tree]] for the detection/extraction branches and evidence grading; see [[gotchas]] for boundaries and counterexamples