performing-steganography-detection

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Performing Steganography Detection

隐写术检测实操

When to Use

适用场景

  • When suspecting covert data hiding in images, audio, or video files
  • During investigations involving suspected data exfiltration via media files
  • For analyzing files in espionage or insider threat investigations
  • When standard file analysis reveals anomalies in media file properties
  • For detecting communication channels using steganographic techniques
  • 怀疑图像、音频或视频文件中隐藏有秘密数据时
  • 涉及通过媒体文件窃取数据的调查过程中
  • 间谍活动或内部威胁调查中的文件分析
  • 标准文件分析发现媒体文件属性存在异常时
  • 检测使用隐写技术的通信渠道时

Prerequisites

前置条件

  • StegDetect, zsteg, stegsolve, binwalk for analysis
  • steghide, OpenStego for extraction attempts
  • ExifTool for metadata analysis
  • Python with Pillow, numpy for custom analysis
  • Understanding of common steganographic techniques (LSB, DCT, spread spectrum)
  • Sample files for comparison and statistical analysis
  • 用于分析的StegDetect、zsteg、stegsolve、binwalk工具
  • 用于提取尝试的steghide、OpenStego工具
  • 用于元数据分析的ExifTool
  • 支持自定义分析的Python及Pillow、numpy库
  • 了解常见隐写技术(LSB、DCT、扩频)
  • 用于对比和统计分析的样本文件

Workflow

操作流程

Step 1: Initial File Assessment and Metadata Analysis

步骤1:初始文件评估与元数据分析

bash
undefined
bash
undefined

Install steganography detection tools

Install steganography detection tools

sudo apt-get install steghide stegsnow pip install zsteg pip install stegoveritas gem install zsteg # Ruby-based tool for PNG/BMP
sudo apt-get install steghide stegsnow pip install zsteg pip install stegoveritas gem install zsteg # Ruby-based tool for PNG/BMP

Examine file metadata for anomalies

Examine file metadata for anomalies

exiftool /cases/case-2024-001/media/suspect_image.jpg | tee /cases/case-2024-001/analysis/metadata.txt
exiftool /cases/case-2024-001/media/suspect_image.jpg | tee /cases/case-2024-001/analysis/metadata.txt

Check for unusual file size (larger than expected for resolution/format)

Check for unusual file size (larger than expected for resolution/format)

identify -verbose /cases/case-2024-001/media/suspect_image.jpg | head -30
identify -verbose /cases/case-2024-001/media/suspect_image.jpg | head -30

Verify file type matches extension

Verify file type matches extension

file /cases/case-2024-001/media/suspect_image.jpg
file /cases/case-2024-001/media/suspect_image.jpg

Confirm JPEG signature vs actual content

Confirm JPEG signature vs actual content

Check for appended data after file footer

Check for appended data after file footer

python3 << 'PYEOF' import os
filepath = '/cases/case-2024-001/media/suspect_image.jpg' filesize = os.path.getsize(filepath)
with open(filepath, 'rb') as f: data = f.read()
python3 << 'PYEOF' import os
filepath = '/cases/case-2024-001/media/suspect_image.jpg' filesize = os.path.getsize(filepath)
with open(filepath, 'rb') as f: data = f.read()

JPEG files end with FF D9

JPEG files end with FF D9

jpeg_end = data.rfind(b'\xff\xd9') if jpeg_end > 0: trailing_bytes = filesize - jpeg_end - 2 if trailing_bytes > 0: print(f"WARNING: {trailing_bytes} bytes of data after JPEG end marker!") print(f" File size: {filesize} bytes") print(f" JPEG data: {jpeg_end + 2} bytes") print(f" Hidden data: {trailing_bytes} bytes") # Extract trailing data with open('/cases/case-2024-001/analysis/trailing_data.bin', 'wb') as out: out.write(data[jpeg_end + 2:]) else: print("No trailing data detected after JPEG end marker")
jpeg_end = data.rfind(b'\xff\xd9') if jpeg_end > 0: trailing_bytes = filesize - jpeg_end - 2 if trailing_bytes > 0: print(f"WARNING: {trailing_bytes} bytes of data after JPEG end marker!") print(f" File size: {filesize} bytes") print(f" JPEG data: {jpeg_end + 2} bytes") print(f" Hidden data: {trailing_bytes} bytes") # Extract trailing data with open('/cases/case-2024-001/analysis/trailing_data.bin', 'wb') as out: out.write(data[jpeg_end + 2:]) else: print("No trailing data detected after JPEG end marker")

Check for embedded ZIP/RAR archives

Check for embedded ZIP/RAR archives

zip_offset = data.find(b'PK\x03\x04') rar_offset = data.find(b'Rar!\x1a\x07') if zip_offset > 0: print(f"ZIP archive found at offset {zip_offset}") if rar_offset > 0: print(f"RAR archive found at offset {rar_offset}") PYEOF
undefined
zip_offset = data.find(b'PK\x03\x04') rar_offset = data.find(b'Rar!\x1a\x07') if zip_offset > 0: print(f"ZIP archive found at offset {zip_offset}") if rar_offset > 0: print(f"RAR archive found at offset {rar_offset}") PYEOF
undefined

Step 2: Run Automated Steganalysis Tools

步骤2:运行自动化隐写分析工具

bash
undefined
bash
undefined

Use binwalk to detect embedded files and data

Use binwalk to detect embedded files and data

binwalk /cases/case-2024-001/media/suspect_image.jpg | tee /cases/case-2024-001/analysis/binwalk_scan.txt
binwalk /cases/case-2024-001/media/suspect_image.jpg | tee /cases/case-2024-001/analysis/binwalk_scan.txt

Extract embedded files

Extract embedded files

binwalk --extract --directory /cases/case-2024-001/analysis/binwalk_extracted/
/cases/case-2024-001/media/suspect_image.jpg
binwalk --extract --directory /cases/case-2024-001/analysis/binwalk_extracted/
/cases/case-2024-001/media/suspect_image.jpg

Use zsteg for PNG and BMP analysis (LSB detection)

Use zsteg for PNG and BMP analysis (LSB detection)

zsteg /cases/case-2024-001/media/suspect_image.png | tee /cases/case-2024-001/analysis/zsteg_results.txt
zsteg /cases/case-2024-001/media/suspect_image.png | tee /cases/case-2024-001/analysis/zsteg_results.txt

zsteg with all checks

zsteg with all checks

zsteg -a /cases/case-2024-001/media/suspect_image.png
zsteg -a /cases/case-2024-001/media/suspect_image.png

Use stegoveritas for comprehensive analysis

Use stegoveritas for comprehensive analysis

stegoveritas /cases/case-2024-001/media/suspect_image.jpg
-out /cases/case-2024-001/analysis/stegoveritas/
stegoveritas /cases/case-2024-001/media/suspect_image.jpg
-out /cases/case-2024-001/analysis/stegoveritas/

Stegoveritas performs:

Stegoveritas performs:

- Metadata extraction

- Metadata extraction

- LSB analysis (multiple bit planes)

- LSB analysis (multiple bit planes)

- Color map analysis

- Color map analysis

- Trailing data detection

- Trailing data detection

- Embedded file extraction

- Embedded file extraction

- Image transformation analysis

- Image transformation analysis

Use steghide for JPEG/BMP/WAV/AU extraction attempts

Use steghide for JPEG/BMP/WAV/AU extraction attempts

Try with empty password

Try with empty password

steghide extract -sf /cases/case-2024-001/media/suspect_image.jpg -p ""
-xf /cases/case-2024-001/analysis/steghide_extract.bin 2>&1
steghide extract -sf /cases/case-2024-001/media/suspect_image.jpg -p ""
-xf /cases/case-2024-001/analysis/steghide_extract.bin 2>&1

Try with common passwords

Try with common passwords

for pwd in password secret hidden stego test 123456 admin; do result=$(steghide extract -sf /cases/case-2024-001/media/suspect_image.jpg
-p "$pwd" -xf "/cases/case-2024-001/analysis/steghide_$pwd.bin" 2>&1) if echo "$result" | grep -q "extracted"; then echo "SUCCESS with password: $pwd" fi done
undefined
for pwd in password secret hidden stego test 123456 admin; do result=$(steghide extract -sf /cases/case-2024-001/media/suspect_image.jpg
-p "$pwd" -xf "/cases/case-2024-001/analysis/steghide_$pwd.bin" 2>&1) if echo "$result" | grep -q "extracted"; then echo "SUCCESS with password: $pwd" fi done
undefined

Step 3: Perform LSB (Least Significant Bit) Analysis

步骤3:执行LSB(最低有效位)分析

bash
undefined
bash
undefined

Custom LSB analysis with Python

Custom LSB analysis with Python

python3 << 'PYEOF' from PIL import Image import numpy as np
img = Image.open('/cases/case-2024-001/media/suspect_image.png') pixels = np.array(img)
python3 << 'PYEOF' from PIL import Image import numpy as np
img = Image.open('/cases/case-2024-001/media/suspect_image.png') pixels = np.array(img)

Extract LSB from each color channel

Extract LSB from each color channel

for channel, name in enumerate(['Red', 'Green', 'Blue']): if channel >= pixels.shape[2]: break
lsb_data = pixels[:, :, channel] & 1

# Count distribution (should be ~50/50 for natural images)
zeros = np.sum(lsb_data == 0)
ones = np.sum(lsb_data == 1)
total = zeros + ones
ratio = ones / total

print(f"{name} channel LSB: 0s={zeros} ({zeros/total*100:.1f}%), 1s={ones} ({ones/total*100:.1f}%)")
if abs(ratio - 0.5) < 0.01:
    print(f"  NEUTRAL - Close to random (could be stego or natural)")
elif ratio > 0.55 or ratio < 0.45:
    print(f"  ANOMALY - Significant deviation from expected distribution")
for channel, name in enumerate(['Red', 'Green', 'Blue']): if channel >= pixels.shape[2]: break
lsb_data = pixels[:, :, channel] & 1

# Count distribution (should be ~50/50 for natural images)
zeros = np.sum(lsb_data == 0)
ones = np.sum(lsb_data == 1)
total = zeros + ones
ratio = ones / total

print(f"{name} channel LSB: 0s={zeros} ({zeros/total*100:.1f}%), 1s={ones} ({ones/total*100:.1f}%)")
if abs(ratio - 0.5) < 0.01:
    print(f"  NEUTRAL - Close to random (could be stego or natural)")
elif ratio > 0.55 or ratio < 0.45:
    print(f"  ANOMALY - Significant deviation from expected distribution")

Extract LSB data as bytes

Extract LSB data as bytes

lsb_bits = (pixels[:, :, 0] & 1).flatten() lsb_bytes = np.packbits(lsb_bits)
lsb_bits = (pixels[:, :, 0] & 1).flatten() lsb_bytes = np.packbits(lsb_bits)

Check if extracted data has structure

Check if extracted data has structure

with open('/cases/case-2024-001/analysis/lsb_extracted.bin', 'wb') as f: f.write(lsb_bytes.tobytes())
with open('/cases/case-2024-001/analysis/lsb_extracted.bin', 'wb') as f: f.write(lsb_bytes.tobytes())

Check for known file signatures in extracted data

Check for known file signatures in extracted data

import struct header = bytes(lsb_bytes[:16]) print(f"\nLSB extracted header (hex): {header.hex()}") if header[:4] == b'PK\x03\x04': print(" DETECTED: ZIP archive in LSB data!") elif header[:3] == b'GIF': print(" DETECTED: GIF image in LSB data!") elif header[:4] == b'\x89PNG': print(" DETECTED: PNG image in LSB data!") elif header[:2] == b'\xff\xd8': print(" DETECTED: JPEG image in LSB data!")
import struct header = bytes(lsb_bytes[:16]) print(f"\nLSB extracted header (hex): {header.hex()}") if header[:4] == b'PK\x03\x04': print(" DETECTED: ZIP archive in LSB data!") elif header[:3] == b'GIF': print(" DETECTED: GIF image in LSB data!") elif header[:4] == b'\x89PNG': print(" DETECTED: PNG image in LSB data!") elif header[:2] == b'\xff\xd8': print(" DETECTED: JPEG image in LSB data!")

Generate LSB visualization

Generate LSB visualization

lsb_img = Image.fromarray((lsb_data * 255).astype(np.uint8)) lsb_img.save('/cases/case-2024-001/analysis/lsb_visualization.png') print("\nLSB visualization saved to lsb_visualization.png") PYEOF
undefined
lsb_img = Image.fromarray((lsb_data * 255).astype(np.uint8)) lsb_img.save('/cases/case-2024-001/analysis/lsb_visualization.png') print("\nLSB visualization saved to lsb_visualization.png") PYEOF
undefined

Step 4: Analyze Audio and Video Steganography

步骤4:分析音频与视频隐写术

bash
undefined
bash
undefined

Spectral analysis of audio files

Spectral analysis of audio files

python3 << 'PYEOF' import wave import numpy as np
python3 << 'PYEOF' import wave import numpy as np

Analyze WAV file for audio steganography

Analyze WAV file for audio steganography

with wave.open('/cases/case-2024-001/media/suspect_audio.wav', 'r') as wav: frames = wav.readframes(wav.getnframes()) samples = np.frombuffer(frames, dtype=np.int16)
# LSB analysis of audio samples
lsb = samples & 1
zeros = np.sum(lsb == 0)
ones = np.sum(lsb == 1)
total = len(lsb)

print(f"Audio LSB Analysis:")
print(f"  Samples: {total}")
print(f"  LSB 0s: {zeros} ({zeros/total*100:.1f}%)")
print(f"  LSB 1s: {ones} ({ones/total*100:.1f}%)")

# Extract LSB data
lsb_bytes = np.packbits(lsb)
with open('/cases/case-2024-001/analysis/audio_lsb.bin', 'wb') as f:
    f.write(lsb_bytes.tobytes())

# Chi-square test for randomness
from scipy import stats
chi2, p_value = stats.chisquare([zeros, ones])
print(f"  Chi-square: {chi2:.4f}, p-value: {p_value:.4f}")
if p_value < 0.05:
    print(f"  ANOMALY: LSB distribution is not random (potential stego)")
PYEOF
with wave.open('/cases/case-2024-001/media/suspect_audio.wav', 'r') as wav: frames = wav.readframes(wav.getnframes()) samples = np.frombuffer(frames, dtype=np.int16)
# LSB analysis of audio samples
lsb = samples & 1
zeros = np.sum(lsb == 0)
ones = np.sum(lsb == 1)
total = len(lsb)

print(f"Audio LSB Analysis:")
print(f"  Samples: {total}")
print(f"  LSB 0s: {zeros} ({zeros/total*100:.1f}%)")
print(f"  LSB 1s: {ones} ({ones/total*100:.1f}%)")

# Extract LSB data
lsb_bytes = np.packbits(lsb)
with open('/cases/case-2024-001/analysis/audio_lsb.bin', 'wb') as f:
    f.write(lsb_bytes.tobytes())

# Chi-square test for randomness
from scipy import stats
chi2, p_value = stats.chisquare([zeros, ones])
print(f"  Chi-square: {chi2:.4f}, p-value: {p_value:.4f}")
if p_value < 0.05:
    print(f"  ANOMALY: LSB distribution is not random (potential stego)")
PYEOF

Use steghide on audio files

Use steghide on audio files

steghide info /cases/case-2024-001/media/suspect_audio.wav
steghide info /cases/case-2024-001/media/suspect_audio.wav

Analyze with sonic-visualiser or audacity for spectral anomalies

Analyze with sonic-visualiser or audacity for spectral anomalies

(Check spectrogram for hidden images encoded in frequency domain)

(Check spectrogram for hidden images encoded in frequency domain)

undefined
undefined

Step 5: Generate Steganalysis Report

步骤5:生成隐写分析报告

bash
undefined
bash
undefined

Compile findings

Compile findings

python3 << 'PYEOF' import os, json
report = { "case": "2024-001", "files_analyzed": [], "findings": [] }
analysis_dir = '/cases/case-2024-001/analysis/' for f in os.listdir(analysis_dir): if f.endswith('.txt'): with open(os.path.join(analysis_dir, f)) as fh: content = fh.read() if 'DETECTED' in content or 'SUCCESS' in content or 'WARNING' in content: report["findings"].append({ "source": f, "content": content[:500] })
with open('/cases/case-2024-001/analysis/steg_report.json', 'w') as f: json.dump(report, f, indent=2)
print("Steganalysis report generated") print(f"Total findings: {len(report['findings'])}") PYEOF
undefined
python3 << 'PYEOF' import os, json
report = { "case": "2024-001", "files_analyzed": [], "findings": [] }
analysis_dir = '/cases/case-2024-001/analysis/' for f in os.listdir(analysis_dir): if f.endswith('.txt'): with open(os.path.join(analysis_dir, f)) as fh: content = fh.read() if 'DETECTED' in content or 'SUCCESS' in content or 'WARNING' in content: report["findings"].append({ "source": f, "content": content[:500] })
with open('/cases/case-2024-001/analysis/steg_report.json', 'w') as f: json.dump(report, f, indent=2)
print("Steganalysis report generated") print(f"Total findings: {len(report['findings'])}") PYEOF
undefined

Key Concepts

核心概念

ConceptDescription
LSB (Least Significant Bit)Embedding data in the lowest-order bits of pixel or sample values
DCT steganographyHiding data in JPEG discrete cosine transform coefficients
Spread spectrumDistributing hidden data across the entire carrier signal
SteganalysisThe science of detecting the presence of hidden information
Chi-square attackStatistical test detecting non-random LSB distributions
Cover mediumThe original file used to carry hidden data (image, audio, video)
Stego mediumThe resulting file after hidden data has been embedded
CapacityMaximum amount of data that can be hidden without visible distortion
概念描述
LSB (Least Significant Bit)将数据嵌入像素或采样值的最低有效位中
DCT steganography在JPEG离散余弦变换系数中隐藏数据
Spread spectrum将隐藏数据分布在整个载体信号中
Steganalysis检测隐藏信息存在的科学
Chi-square attack检测非随机LSB分布的统计测试
Cover medium用于承载隐藏数据的原始文件(图像、音频、视频)
Stego medium嵌入隐藏数据后的最终文件
Capacity不产生可见失真的前提下可隐藏的最大数据量

Tools & Systems

工具与系统

ToolPurpose
steghideEmbed/extract data in JPEG, BMP, WAV, AU files
zstegDetect LSB steganography in PNG and BMP files
binwalkDetect embedded files and data within binary files
stegoveritasComprehensive steganalysis tool with multiple detection methods
StegSolveJava GUI tool for image bit plane and filter analysis
OpenStegoOpen-source steganography and watermarking tool
ExifToolMetadata extraction and analysis for media files
stegseekFast steghide password cracker for JPEG stego extraction
工具用途
steghide在JPEG、BMP、WAV、AU文件中嵌入/提取数据
zsteg检测PNG和BMP文件中的LSB隐写术
binwalk检测二进制文件中嵌入的文件和数据
stegoveritas具备多种检测方法的综合性隐写分析工具
StegSolve用于图像位平面和滤镜分析的Java GUI工具
OpenStego开源隐写术与水印工具
ExifTool媒体文件的元数据提取与分析
stegseek用于steghide隐写提取的快速密码破解工具

Common Scenarios

常见场景

Scenario 1: Covert Communication Investigation Examine images exchanged between suspects via messaging platforms, run stegoveritas and zsteg on all PNG/BMP files, attempt steghide extraction with known passwords on JPEG files, analyze LSB distributions for statistical anomalies, extract and decode any hidden messages.
Scenario 2: Data Exfiltration via Image Upload Monitor images uploaded to cloud services for unusual file sizes, compare image metadata with expected camera/device profiles, run binwalk to detect embedded archives, analyze JPEG quantization tables for steghide signatures, extract and examine any hidden payloads.
Scenario 3: Malware Command and Control Analyze images downloaded by malware for embedded commands, check for data appended after file end markers, examine DNS query responses for base64-encoded data in TXT records, analyze PNG IDAT chunks for anomalous compressed data sizes.
Scenario 4: Intellectual Property Theft via Audio Files Analyze audio files for embedded documents in LSB, check spectrograms for visual patterns hidden in frequency domain, compare audio file sizes with expected sizes for bitrate and duration, extract and analyze any hidden data payloads.
场景1:秘密通信调查 检查嫌疑人通过消息平台交换的图像,对所有PNG/BMP文件运行stegoveritas和zsteg,使用已知密码对JPEG文件尝试steghide提取,分析LSB分布的统计异常,提取并解码任何隐藏消息。
场景2:通过图像上传窃取数据 监控上传至云服务的图像是否存在异常文件大小,将图像元数据与预期的相机/设备配置文件对比,运行binwalk检测嵌入的归档文件,分析JPEG量化表中的steghide特征,提取并检查任何隐藏载荷。
场景3:恶意软件命令与控制 分析恶意软件下载的图像中是否嵌入命令,检查文件结束标记后是否附加数据,查看DNS查询响应的TXT记录中是否存在Base64编码数据,分析PNG IDAT块的压缩数据大小是否异常。
场景4:通过音频文件窃取知识产权 分析音频文件中是否在LSB中嵌入文档,检查频谱图中是否存在隐藏在频域的视觉模式,对比音频文件大小与基于比特率和时长的预期大小,提取并分析任何隐藏数据载荷。

Output Format

输出格式

Steganalysis Summary:
  Files Analyzed: 45 (32 images, 8 audio, 5 video)

  Detection Results:
    suspect_image_03.png:
      zsteg: Text detected in R channel LSB
      Content: "Meet at location B, Tuesday 1400"
      Method: LSB embedding in Red channel

    suspect_photo_17.jpg:
      steghide: Data extracted with password "secret123"
      Hidden file: confidential_report.pdf (234 KB)
      Method: DCT coefficient modification

    profile_pic.png:
      binwalk: ZIP archive embedded at offset 45678
      Contents: 3 spreadsheet files with financial data
      Method: Data appended after PNG IEND marker

    recording_05.wav:
      LSB analysis: Non-random distribution (p < 0.001)
      Extracted: 12 KB binary payload (further analysis needed)
      Method: Audio LSB embedding

  Clean Files: 41 (no steganographic indicators)
  Suspicious Files: 4 (data extracted)

  Report: /cases/case-2024-001/analysis/steg_report.json
隐写分析摘要:
  分析文件数: 45个(32张图像、8个音频、5个视频)

  检测结果:
    suspect_image_03.png:
      zsteg: 在R通道LSB中检测到文本
      内容: "周二14:00在B地点会面"
      方法: 在红色通道中嵌入LSB

    suspect_photo_17.jpg:
      steghide: 使用密码"secret123"提取到数据
      隐藏文件: confidential_report.pdf(234 KB)
      方法: 修改DCT系数

    profile_pic.png:
      binwalk: 在偏移量45678处检测到ZIP归档
      内容: 3个包含财务数据的电子表格文件
      方法: 在PNG IEND标记后附加数据

    recording_05.wav:
      LSB分析: 分布非随机(p < 0.001)
      提取结果: 12 KB二进制载荷(需进一步分析)
      方法: 音频LSB嵌入

  无异常文件: 41个(无隐写术迹象)
  可疑文件: 4个(已提取数据)

  报告: /cases/case-2024-001/analysis/steg_report.json