| name | performing-file-carving-with-foremost |
| description | 使用 Foremost 的文件头/文件尾签名雕刻技术,从磁盘镜像和未分配空间中恢复文件,无论文件系统状态如何均可提取证据。 |
| domain | cybersecurity |
| subdomain | digital-forensics |
| tags | ["forensics","file-carving","foremost","data-recovery","evidence-recovery","unallocated-space"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
使用 Foremost 执行文件雕刻
适用场景
- 从未分配磁盘空间或损坏的文件系统中恢复文件时
- 从格式化或擦除的存储介质中提取证据时
- 文件系统元数据不可用但原始数据扇区包含证据时
- 调查需要从原始镜像中恢复特定文件类型时
- 作为基于文件系统恢复的补充,以最大化证据提取时
前置条件
- 取证工作站上已安装 Foremost
- 原始(dd)格式的取证磁盘镜像
- 充足的输出存储空间(可能大于源文件)
- 针对特定文件类型的自定义 foremost.conf(可选)
- 了解目标文件类型的文件签名(魔术字节)
- Scalpel 作为性能关键型雕刻的替代工具
工作流程
步骤 1:安装和配置 Foremost
sudo apt-get install foremost
foremost -V
cat /etc/foremost.conf
cp /etc/foremost.conf /cases/case-2024-001/custom_foremost.conf
cat << 'EOF' >> /cases/case-2024-001/custom_foremost.conf
docx y 10000000 \x50\x4b\x03\x04 \x50\x4b\x05\x06
xlsx y 10000000 \x50\x4b\x03\x04 \x50\x4b\x05\x06
pptx y 10000000 \x50\x4b\x03\x04 \x50\x4b\x05\x06
sqlite y 50000000 \x53\x51\x4c\x69\x74\x65\x20\x66\x6f\x72\x6d\x61\x74
pst y 500000000 \x21\x42\x44\x4e
eml y 1000000 \x46\x72\x6f\x6d\x3a \x0d\x0a\x0d\x0a
evtx y 50000000 \x45\x6c\x66\x46\x69\x6c\x65
EOF
步骤 2:对磁盘镜像运行 Foremost
foremost -t all \
-i /cases/case-2024-001/images/evidence.dd \
-o /cases/case-2024-001/carved/foremost_all/
foremost -t jpg,png,pdf,doc,xls,zip \
-i /cases/case-2024-001/images/evidence.dd \
-o /cases/case-2024-001/carved/foremost_targeted/
foremost -c /cases/case-2024-001/custom_foremost.conf \
-i /cases/case-2024-001/images/evidence.dd \
-o /cases/case-2024-001/carved/foremost_custom/
mmls /cases/case-2024-001/images/evidence.dd
blkls -o 2048 /cases/case-2024-001/images/evidence.dd \
> /cases/case-2024-001/unallocated.dd
foremost -t all \
-i /cases/case-2024-001/unallocated.dd \
-o /cases/case-2024-001/carved/foremost_unalloc/
foremost -v -t all \
-i /cases/case-2024-001/images/evidence.dd \
-o /cases/case-2024-001/carved/foremost_verbose/ 2>&1 | \
tee /cases/case-2024-001/carved/foremost_log.txt
dd if=/cases/case-2024-001/images/evidence.dd bs=512 skip=2048 | \
foremost -t jpg,pdf -o /cases/case-2024-001/carved/foremost_pipe/
步骤 3:使用 Scalpel 进行高性能雕刻
sudo apt-get install scalpel
cp /etc/scalpel/scalpel.conf /cases/case-2024-001/scalpel.conf
scalpel -c /cases/case-2024-001/scalpel.conf \
-o /cases/case-2024-001/carved/scalpel/ \
/cases/case-2024-001/images/evidence.dd
步骤 4:处理并验证雕刻的文件
cat /cases/case-2024-001/carved/foremost_all/audit.txt
python3 << 'PYEOF'
import os
import subprocess
from collections import defaultdict
carved_dir = '/cases/case-2024-001/carved/foremost_all/'
stats = defaultdict(lambda: {'total': 0, 'valid': 0, 'invalid': 0, 'size': 0})
for subdir in os.listdir(carved_dir):
subdir_path = os.path.join(carved_dir, subdir)
if not os.path.isdir(subdir_path) or subdir == 'audit.txt':
continue
for filename in os.listdir(subdir_path):
filepath = os.path.join(subdir_path, filename)
if not os.path.isfile(filepath):
continue
ext = subdir
filesize = os.path.getsize(filepath)
stats[ext]['total'] += 1
stats[ext]['size'] += filesize
result = subprocess.run(['file', '--brief', filepath], capture_output=True, text=True)
file_type = result.stdout.strip()
if 'data' in file_type.lower() or 'empty' in file_type.lower():
stats[ext]['invalid'] += 1
else:
stats[ext]['valid'] += 1
print("=== 雕刻文件验证 ===\n")
print(f"{'类型':<10} {'总数':<8} {'有效':<8} {'无效':<10} {'总大小':<15}")
print( * 55)
ext sorted(stats.keys()):
s = stats[ext]
size_mb = s[] / (1024*1024)
(f)
subdir os.listdir(carved_dir):
subdir_path = os.path.join(carved_dir, subdir)
os.path.isdir(subdir_path):
filename os.listdir(subdir_path):
filepath = os.path.join(subdir_path, filename)
os.path.isfile(filepath) and os.path.getsize(filepath) == 0:
os.remove(filepath)
PYEOF
find /cases/case-2024-001/carved/foremost_all/ - f ! -name \
- {} \; > /cases/case-2024-001/carved/carved_file_hashes.txt
步骤 5:检查并归档证据文件
exiftool -r -csv /cases/case-2024-001/carved/foremost_all/jpg/ \
> /cases/case-2024-001/analysis/carved_image_metadata.csv
find /cases/case-2024-001/carved/foremost_all/pdf/ -name "*.pdf" -exec pdftotext {} - \; 2>/dev/null | \
grep -iE '(confidential|secret|password|account|ssn|credit.card)' \
> /cases/case-2024-001/analysis/keyword_hits_pdf.txt
mkdir -p /cases/case-2024-001/carved/thumbnails/
find /cases/case-2024-001/carved/foremost_all/jpg/ -name "*.jpg" -exec \
convert {} -thumbnail 200x200 /cases/case-2024-001/carved/thumbnails/{} \; 2>/dev/null
python3 << 'PYEOF'
import os, hashlib, csv, subprocess
catalog = []
carved_dir = '/cases/case-2024-001/carved/foremost_all/'
for subdir in sorted(os.listdir(carved_dir)):
subdir_path = os.path.join(carved_dir, subdir)
if not os.path.isdir(subdir_path):
continue
for filename in sorted(os.listdir(subdir_path)):
filepath = os.path.join(subdir_path, filename)
if not os.path.isfile(filepath):
continue
size = os.path.getsize(filepath)
sha256 = hashlib.sha256(open(filepath, 'rb').read()).hexdigest()
file_type = subprocess.run(['file', '--brief', filepath], capture_output=True, text=True).stdout.strip()
catalog.append({
'filename': filename,
'type': subdir,
'size': size,
'sha256': sha256,
'file_description': file_type[:100]
})
with open('/cases/case-2024-001/analysis/carved_file_catalog.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=[, , , , ])
writer.writeheader()
writer.writerows(catalog)
(f)
PYEOF
关键概念
| 概念 | 描述 |
|---|
| 文件雕刻(File carving) | 通过在原始数据中搜索已知的文件头/文件尾字节序列来恢复文件 |
| 文件签名(File signature) | 标识文件类型的开头(文件头)或结尾(文件尾)的唯一字节模式 |
| 未分配空间(Unallocated space) | 未分配给任何文件的磁盘扇区;雕刻的主要目标 |
| 文件碎片化(Fragmentation) | 文件数据存储于非连续扇区时,使雕刻更加复杂 |
| 文件头文件尾雕刻 | 提取已知文件起始和结束签名之间的数据 |
| 误报(False positives) | 雕刻数据匹配文件签名但内容损坏或无关 |
| 松弛空间(Slack space) | 文件最后分配簇末尾的未使用字节 |
| 扇区对齐 | 文件通常从扇区边界开始,提高雕刻精度 |
工具与系统
| 工具 | 用途 |
|---|
| Foremost | 最初为美国空军 OSI 开发的文件头文件尾雕刻工具 |
| Scalpel | 支持可配置签名的高性能文件雕刻工具 |
| PhotoRec | 支持 300+ 格式的基于签名的文件恢复工具 |
| bulk_extractor | 从原始数据中提取特征(邮箱、URL、信用卡号) |
| blkls | Sleuth Kit 工具,从磁盘镜像中提取未分配空间 |
| mmls | 用于识别雕刻目标的分区表显示工具 |
| ExifTool | 从雕刻的图像和文档文件中提取元数据 |
| hashdeep | 对雕刻文件目录进行递归哈希计算 |
常见场景
场景 1:恢复已删除的证据文档
针对用 blkls 提取的未分配空间运行 Foremost,目标文件类型为 doc、pdf、xlsx,验证雕刻文档,搜索与案件相关的关键字,归档并哈希所有可恢复文档,作为证据提交。
场景 2:从格式化介质中恢复图像
从格式化 U 盘镜像中雕刻 JPEG、PNG、GIF、BMP,提取包含 GPS 坐标和相机信息的 EXIF 元数据,生成缩略图以便快速视觉审查,识别与证据相关的图像,记录恢复链。
场景 3:从损坏的 PST 文件中恢复电子邮件
使用带有 PST 和 EML 签名的自定义 foremost.conf,从损坏的 Outlook 数据文件中雕刻邮件制品,尝试在查看器中打开雕刻的 PST 片段,提取单独的 EML 邮件,搜索相关通信内容。
场景 4:金融调查的数据库恢复
配置 Foremost 从未分配空间中雕刻 SQLite 数据库,恢复已删除的应用程序数据库,查询恢复的数据库中的财务记录,与已知交易数据交叉比对,记录调查发现以用于起诉。
输出格式
文件雕刻摘要:
工具:Foremost 1.5.7
来源:evidence.dd(500 GB)
目标:未分配空间(234 GB)
耗时:1 小时 45 分钟
雕刻文件:
jpg: 2,345 个文件(1.8 GB)- 有效:2,100 / 无效:245
png: 234 个文件(456 MB)- 有效:210 / 无效:24
pdf: 156 个文件(890 MB)- 有效:134 / 无效:22
doc: 89 个文件(234 MB)- 有效:67 / 无效:22
xls: 45 个文件(123 MB)- 有效:38 / 无效:7
zip: 67 个文件(567 MB)- 有效:52 / 无效:15
exe: 34 个文件(234 MB)- 有效:30 / 无效:4
sqlite: 12 个文件(89 MB) - 有效:10 / 无效:2
总文件数:2,982(恢复 3.4 GB)
与证据相关:标记 45 个文件待审查
审计日志:/cases/case-2024-001/carved/foremost_all/audit.txt
文件目录:/cases/case-2024-001/analysis/carved_file_catalog.csv