performing-steganography-detection
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePerforming 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
undefinedbash
undefinedInstall 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
undefinedzip_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
undefinedStep 2: Run Automated Steganalysis Tools
步骤2:运行自动化隐写分析工具
bash
undefinedbash
undefinedUse 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
/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
/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/
-out /cases/case-2024-001/analysis/stegoveritas/
stegoveritas /cases/case-2024-001/media/suspect_image.jpg
-out /cases/case-2024-001/analysis/stegoveritas/
-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
-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
-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
-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
undefinedfor 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
-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
undefinedStep 3: Perform LSB (Least Significant Bit) Analysis
步骤3:执行LSB(最低有效位)分析
bash
undefinedbash
undefinedCustom 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
undefinedlsb_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
undefinedStep 4: Analyze Audio and Video Steganography
步骤4:分析音频与视频隐写术
bash
undefinedbash
undefinedSpectral 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)
undefinedundefinedStep 5: Generate Steganalysis Report
步骤5:生成隐写分析报告
bash
undefinedbash
undefinedCompile 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
undefinedpython3 << '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
undefinedKey Concepts
核心概念
| Concept | Description |
|---|---|
| LSB (Least Significant Bit) | Embedding data in the lowest-order bits of pixel or sample values |
| DCT steganography | Hiding data in JPEG discrete cosine transform coefficients |
| Spread spectrum | Distributing hidden data across the entire carrier signal |
| Steganalysis | The science of detecting the presence of hidden information |
| Chi-square attack | Statistical test detecting non-random LSB distributions |
| Cover medium | The original file used to carry hidden data (image, audio, video) |
| Stego medium | The resulting file after hidden data has been embedded |
| Capacity | Maximum 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
工具与系统
| Tool | Purpose |
|---|---|
| steghide | Embed/extract data in JPEG, BMP, WAV, AU files |
| zsteg | Detect LSB steganography in PNG and BMP files |
| binwalk | Detect embedded files and data within binary files |
| stegoveritas | Comprehensive steganalysis tool with multiple detection methods |
| StegSolve | Java GUI tool for image bit plane and filter analysis |
| OpenStego | Open-source steganography and watermarking tool |
| ExifTool | Metadata extraction and analysis for media files |
| stegseek | Fast 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