Communitygithub.com

分析NTFS空闲空间与文件系统痕迹

检查NTFS空闲空间、MFT条目、USN变更日志和备用数据流(ADS),以恢复隐藏或残留数据、重建已删除文件元数据,并从USN记录中重建可用的文件系统变更活动。在标准文件恢复不足以满足需求时(例如调查隐藏于ADS中的数据)用于深度取证分析。

分析NTFS空闲空间与文件系统痕迹 是什么?

该技能专门用于NTFS文件系统深度取证分析,涵盖文件空闲空间、主文件表(MFT)、USN变更日志和备用数据流(ADS)的检查与数据提取。它支持多种工具平台,如The Sleuth Kit(TSK)、MFTECmd(Eric Zimmerman工具集)以及Python库(analyzeMFT、pyusn等),可在终端和自动化脚本环境中使用。技能提供了一套完整的5步工作流程:识别并提取NTFS系统文件、分析MFT以发现已删除文件和时间戳篡改、从文件空闲空间中搜索隐藏数据、解析USN变更日志以重构文件操作历史,以及检测并提取ADS中的隐藏内容。它还涵盖4种常见取证场景:检测时间戳篡改、发现ADS中的隐藏数据、从MFT中恢复已删除文件,以及通过USN日志重构文件活动。该技能可输出结构化分析报告,帮助用户识别异常行为(如批量删除、数据隐藏),是电子取证和安全调查的重要工具。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mukul975/Anthropic-Cybersecurity-Skills/tree/main/skills/analyzing-slack-space-and-file-system-artifacts

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

分析NTFS空闲空间与文件系统痕迹 是做什么的?

何时使用

  • 在文件系统空闲空间中搜索隐藏或残留数据时
  • 分析NTFS主文件表(MFT)条目以获取已删除文件元数据时
  • 通过USN变更日志重构文件操作时
  • 检测用于隐藏数据或恶意软件的备用数据流(ADS)时
  • 在进行超出标准文件恢复范围的深度取证分析时

前提条件

  • 具有NTFS文件系统的取证磁盘镜像
  • Sleuth Kit工具包:istat, icat, fls, blkls, blkstat
  • MFTECmd(Eric Zimmerman)用于MFT解析
  • MFTExplorer用于交互式MFT分析
  • 理解NTFS结构(MFT, $UsnJrnl, $LogFile, ADS)
  • 安装了analyzeMFT或mft库的Python,用于自动解析

工作流程

步骤1:识别并提取NTFS文件系统痕迹

# 确定分区布局
mmls /cases/case-2024-001/images/evidence.dd

# 提取关键NTFS系统文件
# $MFT - 主文件表
icat -o 2048 /cases/case-2024-001/images/evidence.dd 0 > /cases/case-2024-001/ntfs/MFT

# $UsnJrnl:$J - USN变更日志
icat -o 2048 /cases/case-2024-001/images/evidence.dd 62-128 > /cases/case-2024-001/ntfs/UsnJrnl_J

# $LogFile - 事务日志
icat -o 2048 /cases/case-2024-001/images/evidence.dd 2 > /cases/case-2024-001/ntfs/LogFile

# 从卷中提取所有空闲空间
blkls -s -o 2048 /cases/case-2024-001/images/evidence.dd > /cases/case-2024-001/ntfs/slack_space.raw

# 获取文件系统信息
fsstat -o 2048 /cases/case-2024-001/images/evidence.dd | tee /cases/case-2024-001/ntfs/fs_info.txt

步骤2:分析主文件表(MFT)

# 使用MFTECmd解析MFT(Eric Zimmerman)
MFTECmd.exe -f "C:\cases\ntfs\MFT" --csv "C:\cases\analysis\" --csvf mft_analysis.csv

# 使用analyzeMFT进行解析(Python)
pip install analyzeMFT

analyzeMFT.py -f /cases/case-2024-001/ntfs/MFT \
   -o /cases/case-2024-001/analysis/mft_analysis.csv \
   -c

# 使用Python进行自定义MFT分析
python3 << 'PYEOF'
from mft import PyMft
import csv

mft = PyMft(open('/cases/case-2024-001/ntfs/MFT', 'rb').read())

deleted_files = []
suspicious_files = []

for entry in mft.entries():
    if entry is None:
        continue

    filename = entry.get_filename()
    if filename is None:
        continue

    is_deleted = not entry.is_active()
    is_directory = entry.is_directory()
    created = entry.get_created_timestamp()
    modified = entry.get_modified_timestamp()
    mft_modified = entry.get_mft_modified_timestamp()
    size = entry.get_file_size()

    # 标记已删除文件以待恢复
    if is_deleted and not is_directory and size > 0:
        deleted_files.append({
            'filename': filename,
            'size': size,
            'created': str(created),
            'modified': str(modified),
            'entry_number': entry.entry_number
        })

    # 检测时间戳篡改(MFT修改时间 != $SI修改时间)
    si_modified = entry.get_si_modified_timestamp()
    fn_modified = entry.get_fn_modified_timestamp()
    if si_modified and fn_modified:
        if abs((si_modified - fn_modified).total_seconds()) > 86400:  # >1天差异
            suspicious_files.append({
                'filename': filename,
                'si_modified': str(si_modified),
                'fn_modified': str(fn_modified),
                'delta': str(si_modified - fn_modified)
            })

print(f"=== 已删除文件(可恢复元数据) ===")
print(f"总数: {len(deleted_files)}")
for f in deleted_files[:20]:
    print(f"  [{f['modified']}] {f['filename']} ({f['size']} 字节)")

print(f"\n=== 潜在的时间戳篡改 ===")
print(f"可疑总数: {len(suspicious_files)}")
for f in suspicious_files[:10]:
    print(f"  {f['filename']}: $SI={f['si_modified']}, $FN={f['fn_modified']} (差异: {f['delta']})")
PYEOF

步骤3:分析空闲空间中的隐藏数据

# 在空闲空间中搜索字符串
strings -a /cases/case-2024-001/ntfs/slack_space.raw > /cases/case-2024-001/analysis/slack_strings.txt

# 在空闲空间中搜索特定模式
grep -iab "password\|secret\|confidential\|credit.card\|ssn" \
   /cases/case-2024-001/ntfs/slack_space.raw > /cases/case-2024-001/analysis/slack_keywords.txt

# 分析单个文件的空闲空间
python3 << 'PYEOF'
import struct

# 文件空闲空间包括:
# 1. RAM空闲空间:文件结束到下一个扇区边界之间的字节(可能填充RAM内容或零)
# 2. 驱动器空闲空间:最后一个文件扇区之后簇中剩余的扇区

# 分析特定MFT条目的空闲空间
# 使用Sleuth Kit获取特定文件的空闲空间
import subprocess

# 获取文件详情
result = subprocess.run(
    ['istat', '-o', '2048', '/cases/case-2024-001/images/evidence.dd', '14523'],
    capture_output=True, text=True
)
print(result.stdout)

# 输出显示数据运行 - 最后一个簇可能包含空闲数据
# 计算空闲空间大小:(分配大小 - 文件大小) 字节
PYEOF

# 在空闲空间中搜索文件签名(嵌入文件)
foremost -t jpg,pdf,zip -i /cases/case-2024-001/ntfs/slack_space.raw \
   -o /cases/case-2024-001/carved/slack_carved/

# 使用bulk_extractor在空闲空间中查找结构化数据
bulk_extractor -o /cases/case-2024-001/analysis/bulk_extract/ \
   /cases/case-2024-001/ntfs/slack_space.raw

步骤4:解析USN变更日志

# 使用MFTECmd解析USN日志
MFTECmd.exe -f "C:\cases\ntfs\UsnJrnl_J" --csv "C:\cases\analysis\" --csvf usn_journal.csv

# Python USN日志解析
pip install pyusn

python3 << 'PYEOF'
import struct
import csv
from datetime import datetime, timedelta

def parse_usn_record(data, offset):
    """解析单个USN_RECORD_V2记录。"""
    if offset + 8 > len(data):
        return None, offset

    record_len = struct.unpack_from('<I', data, offset)[0]
    if record_len < 56 or record_len > 65536 or offset + record_len > len(data):
        return None, offset + 8

    major_ver = struct.unpack_from('<H', data, offset + 4)[0]
    if major_ver != 2:
        return None, offset + record_len

    mft_ref = struct.unpack_from('<Q', data, offset + 8)[0] & 0xFFFFFFFFFFFF
    parent_ref = struct.unpack_from('<Q', data, offset + 16)[0] & 0xFFFFFFFFFFFF
    usn = struct.unpack_from('<Q', data, offset + 24)[0]
    timestamp = struct.unpack_from('<Q', data, offset + 32)[0]
    reason = struct.unpack_from('<I', data, offset + 40)[0]
    source_info = struct.unpack_from('<I', data, offset + 44)[0]
    security_id = struct.unpack_from('<I', data, offset + 48)[0]
    file_attrs = struct.unpack_from('<I', data, offset + 52)[0]
    filename_len = struct.unpack_from('<H', data, offset + 56)[0]
    filename_off = struct.unpack_from('<H', data, offset + 58)[0]

    name = data[offset + filename_off:offset + filename_off + filename_len].decode('utf-16-le', errors='ignore')

    # 将Windows FILETIME转换为datetime
    ts = datetime(1601, 1, 1) + timedelta(microseconds=timestamp // 10)

    # 解码原因标志
    reasons = []
    reason_flags = {
        0x01: 'DATA_OVERWRITE', 0x02: 'DATA_EXTEND', 0x04: 'DATA_TRUNCATION',
        0x10: 'NAMED_DATA_OVERWRITE', 0x20: 'NAMED_DATA_EXTEND',
        0x100: 'FILE_CREATE', 0x200: 'FILE_DELETE', 0x400: 'EA_CHANGE',
        0x800: 'SECURITY_CHANGE', 0x1000: 'RENAME_OLD_NAME', 0x2000: 'RENAME_NEW_NAME',
        0x4000: 'INDEXABLE_CHANGE', 0x8000: 'BASIC_INFO_CHANGE',
        0x10000: 'HARD_LINK_CHANGE', 0x20000: 'COMPRESSION_CHANGE',
        0x40000: 'ENCRYPTION_CHANGE', 0x80000: 'OBJECT_ID_CHANGE',
        0x100000: 'REPARSE_POINT_CHANGE', 0x200000: 'STREAM_CHANGE',
        0x80000000: 'CLOSE'
    }
    for flag, desc in reason_flags.items():
        if reason & flag:
            reasons.append(desc)

    record = {
        'timestamp': ts.strftime('%Y-%m-%d %H:%M:%S'),
        'filename': name,
        'mft_entry': mft_ref,
        'parent_entry': parent_ref,
        'reasons': '|'.join(reasons),
        'usn': usn
    }

    return record, offset + record_len

# 解析日志
with open('/cases/case-2024-001/ntfs/UsnJrnl_J', 'rb') as f:
    data = f.read()

records = []
offset = 0
while offset < len(data) - 8:
    record, offset = parse_usn_record(data, offset)
    if record:
        records.append(record)
    else:
        offset += 8  # 跳过零值

# 过滤删除事件
deletions = [r for r in records if 'FILE_DELETE' in r['reasons']]
creations = [r for r in records if 'FILE_CREATE' in r['reasons']]
renames = [r for r in records if 'RENAME_NEW_NAME' in r['reasons']]

print(f"USN记录总数: {len(records)}")
print(f"文件创建: {len(creations)}")
print(f"文件删除: {len(deletions)}")
print(f"文件重命名: {len(renames)}")

print("\n=== 最近的删除操作 ===")
for r in deletions[-20:]:
    print(f"  [{r['timestamp']}] 删除: {r['filename']} (MFT#{r['mft_entry']})")

# 将完整日志写入CSV
with open('/cases/case-2024-001/analysis/usn_journal.csv', 'w', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=['timestamp', 'filename', 'mft_entry', 'parent_entry', 'reasons', 'usn'])
    writer.writeheader()
    writer.writerows(records)
PYEOF

步骤5:检测并分析备用数据流(ADS)

# 列出镜像中的所有备用数据流
find /mnt/evidence -exec getfattr -d {} \; 2>/dev/null | grep -i "ads\|zone\|stream"

# 使用Sleuth Kit查找ADS
fls -r -o 2048 /cases/case-2024-001/images/evidence.dd | grep ":" | \
   tee /cases/case-2024-001/analysis/ads_list.txt

# 提取特定ADS内容
# 格式: icat 镜像 inode:ads_name
icat -o 2048 /cases/case-2024-001/images/evidence.dd 14523:hidden_stream \
   > /cases/case-2024-001/analysis/extracted_ads.bin

# 检查Zone.Identifier流(下载来源追踪)
fls -r -o 2048 /cases/case-2024-001/images/evidence.dd | grep "Zone.Identifier" | \
   while read line; do
       inode=$(echo "$line" | awk '{print $2}' | tr -d ':')
       echo "=== $line ==="
       icat -o 2048 /cases/case-2024-001/images/evidence.dd "${inode}:Zone.Identifier" 2>/dev/null
       echo ""
   done > /cases/case-2024-001/analysis/zone_identifiers.txt

# Zone.Identifier内容揭示:
# [ZoneTransfer]
# ZoneId=3          (3 = 互联网,表示文件是从互联网下载的)
# ReferrerUrl=https://malicious-site.com/payload.exe
# HostUrl=https://cdn.malicious-site.com/payload.exe

关键概念

概念描述
文件空闲空间文件结尾到簇边界之间的未使用空间,包含残留数据
RAM空闲空间从文件结尾到扇区边界之间的空闲空间部分(历史上填充了RAM内容)
MFT ($MFT)主文件表 - 包含每个文件条目的NTFS元数据数据库
USN日志 ($UsnJrnl)记录NTFS上所有文件/目录修改的变更日志
备用数据流NTFS功能,允许每个文件拥有多个数据流(隐藏存储)
$STANDARD_INFORMATIONMFT属性,其时间戳可由用户模式应用程序修改
$FILE_NAMEMFT属性,其时间戳仅可由内核修改
时间戳篡改修改文件时间戳以逃避检测的反取证技术

工具与系统

工具用途
MFTECmdEric Zimmerman的MFT和USN日志解析器,支持CSV输出
MFTExplorer用于MFT分析的交互式GUI工具
analyzeMFTPython MFT解析器,支持CSV/JSON输出
The Sleuth Kit文件系统取证工具包(fls, icat, blkls, istat)
bulk_extractor从原始数据(包括空闲空间)中提取特征
NTFS Log Tracker用于解析$LogFile事务记录的工具
streams.exeSysinternals工具,用于列出NTFS备用数据流
Plaso解析MFT和USN日志的超时间线工具

常见场景

场景1:通过时间戳篡改检测反取证行为 比较MFT条目中的$STANDARD_INFORMATION时间戳与$FILE_NAME时间戳,标记$SI时间戳早于$FN时间戳的文件(在正常操作中不可能),识别被篡改时间戳的文件作为故意操纵的证据,并与其它时间线证据关联。

场景2:备用数据流中的隐藏数据 扫描文件上除标准Zone.Identifier之外的ADS,提取ADS内容进行分析,检查存储在ADS中的隐藏可执行文件或文档,将ADS创建与用户活动时间线关联,记录发现作为证据。

场景3:从MFT重建已删除文件 解析MFT中未激活(已删除)的条目,提取已删除文件的文件名、大小和时间戳,如果数据簇未被覆盖,使用icat恢复文件内容,建立已删除证据文件列表,与USN日志删除事件关联。

场景4:从USN日志重构文件活动 解析调查期间的USN变更日志,识别文件创建、修改、重命名和删除事件,重构文件操作序列,检测数据暂存证据(创建、复制、压缩、删除模式),识别反取证文件擦除行为。

输出格式

文件系统痕迹分析:
  卷: NTFS (分区2, 465 GB)
  簇大小: 4096 字节

  MFT分析:
    条目总数: 456,789
    活动文件: 234,567
    已删除条目: 12,345 (其中8,901个具有可恢复元数据)
    时间戳被篡改文件: 23 (检测到$SI/$FN不匹配)

  USN日志:
    解析记录数: 2,345,678
    日期范围: 2024-01-01 至 2024-01-20
    文件创建: 45,678
    文件删除: 23,456
    文件重命名: 12,345

  备用数据流:
    发现ADS总数: 1,234
    Zone.Identifier: 890 (已下载文件)
    自定义/可疑ADS: 5 (检测到隐藏数据)

  空闲空间:
    空闲空间总量: 12.3 GB
    关键词命中数: 45 (密码, 信用卡)
    从空闲空间刻录文件: 23

  可疑发现:
    - 23个文件时间戳被篡改
    - 5个文件具有包含数据的隐藏ADS
    - USN显示2024-01-18发生批量删除(反取证行为)

…

[翻译截断]

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

abusing-dpapi-for-credential-access

Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys) online or offline using SharpDPAPI, SharpChrome, Mimikatz, or Impacket

abusing-shadow-credentials-for-privesc

Take over Active Directory accounts by writing attacker-controlled public keys to msDS-KeyCredentialLink (Shadow Credentials) with pyWhisker, Whisker, or Certipy, then authenticate via PKINIT to recover the target

achieving-cmmc-level-2-compliance

>-

acquiring-disk-image-with-dd-and-dcfldd

Create forensically sound bit-for-bit disk images with dd or dcfldd on a Linux forensic workstation, preserving evidence integrity through hash verification (MD5/SHA) during acquisition. Use when imaging a suspect drive, USB device, or memory card for investigation, preserving volatile disk evidence during incident response, or producing a verified copy for legal or law-enforcement proceedings before any destructive analysis.

analyzing-active-directory-acl-abuse

Detect dangerous ACL misconfigurations in Active Directory using ldap3

analyzing-android-malware-with-apktool

Perform static analysis of Android APK malware using apktool for resource decompilation, jadx for Java source recovery, and androguard for manifest inspection, dangerous permission-combination detection, and identification of obfuscated code, dynamic code loading, and reflection-based API calls. Use to statically triage a suspicious APK without executing it or to build mobile malware detection rules.

analyzing-api-gateway-access-logs

Parses API Gateway access logs (AWS API Gateway, Kong, Nginx) to detect

analyzing-apt-group-with-mitre-navigator

Query ATT&CK data with attackcti, mitreattack-python, and stix2, then build MITRE ATT&CK Navigator layers and multi-layer heatmap overlays mapping one or more APT groups

analyzing-azure-activity-logs-for-threats

Queries Azure Monitor activity logs and sign-in logs via azure-monitor-query

analyzing-bootkit-and-rootkit-samples

Analyzes bootkit and advanced rootkit malware infecting the Master

analyzing-browser-forensics-with-hindsight

Parse Chromium-based browser databases with Hindsight to extract and correlate browsing history, downloads, cookies, cached content, autofill data, saved passwords, and extensions from Chrome, Edge, Brave, Opera, and Vivaldi into a unified timeline (XLSX, JSON, or SQLite output). Use during incident response, insider-threat investigations, or criminal cases when you need to reconstruct a user

analyzing-campaign-attribution-evidence

Systematically evaluate cyber-campaign evidence to attribute an operation to a threat actor, using the Diamond Model and Analysis of Competing Hypotheses (ACH) to weigh infrastructure overlaps, TTP consistency, malware code similarity, and timing/language artifacts into confidence-weighted attribution assessments. Use when an incident investigation needs a defensible attribution confidence level.

analyzing-certificate-transparency-for-phishing

Monitor Certificate Transparency logs using crt.sh and Certstream to

analyzing-cloud-storage-access-patterns

Detect abnormal access in AWS S3, GCS, and Azure Blob Storage by analyzing CloudTrail Data Events, GCS audit logs, and Azure Storage Analytics for after-hours bulk downloads, new-IP access, and API-call spikes (e.g. GetObject) via statistical baselines and time-series anomaly detection. Use when investigating suspected cloud data exfiltration or building related detection rules.

analyzing-cobalt-strike-beacon-configuration

Extract and analyze Cobalt Strike beacon configuration from PE files

analyzing-cobaltstrike-malleable-c2-profiles

Parse and analyze Cobalt Strike Malleable C2 profiles with dissect.cobaltstrike (profiles and beacon-payload configs) and pyMalleableC2 (AST parsing) to extract HTTP/DNS transforms, URIs, headers, sleep/jitter, and injection behavior, then generate network detection signatures. Use when reverse-engineering a captured malleable profile or building detections against Cobalt Strike Beacon traffic.

analyzing-command-and-control-communication

Analyzes malware C2 communication over HTTP, HTTPS, DNS, and custom

analyzing-cyber-kill-chain

Analyzes intrusion activity against the Lockheed Martin Cyber Kill Chain

analyzing-disk-image-with-autopsy

Perform comprehensive forensic analysis of raw (dd), E01, or AFF disk images with Autopsy and The Sleuth Kit, recovering deleted files, examining metadata and embedded artifacts, keyword searching, and building investigation timelines with visual reports. Use for structured analysis of a forensic disk image or when stakeholders need visual reports from evidence.

analyzing-dns-logs-for-exfiltration

Analyzes DNS query logs to detect data exfiltration via DNS tunneling,

相关技能