mcpField
A
analyzing-windows-lnk-files-for-artifacts

analyzing-windows-lnk-files-for-artifacts

github.com/mukul975安全35.2k216 次安装8 周前更新
代码仓库

关于 analyzing-windows-lnk-files-for-artifacts

用于分析 Windows LNK 快捷方式文件和跳转列表的数字取证技能。它帮助调查人员从解析出的快捷方式元数据重建文件访问、可移动介质和网络共享活动及相关时间线。

主要功能

  1. 01从证据中收集 LNK 文件
  2. 02将快捷方式解析为 CSV 或 JSON
  3. 03检查目标路径和时间戳
  4. 04识别可移动介质和网络目标
  5. 05在时间线中关联快捷方式数据

适用场景

  1. 01重建用户的文档访问历史
  2. 02调查从 USB 驱动器访问的文件
  3. 03审查网络共享访问情况
  4. 04检查用于持久化的启动快捷方式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill analyzing-windows-lnk-files-for-artifacts

安装后在 Claude Code 中输入/analyzing-windows-lnk-files-for-artifacts确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
references/
api-reference.md
scripts/
agent.py

详细介绍

分析 Windows LNK 文件中的痕迹

使用场景

  • 从 Windows 快捷方式文件重建用户文件访问历史时
  • 用于跟踪已访问的文件、网络共享和可移动介质
  • 在调查中证明用户打开过特定文档时
  • 将文件访问与其他时间线痕迹关联时
  • 用于识别远程系统或 USB 设备上被访问的路径时

前置条件

  • 从取证镜像中获取 LNK 文件(Recent、Desktop、Quick Launch)
  • 用于分析的 LECmd(Eric Zimmerman)、python-lnk 或 LnkParser
  • 了解 LNK 文件结构(Shell Link Binary 格式)
  • 熟悉 LNK 文件在 Windows 系统中的位置
  • 已安装分析工具的取证工作站

工作流

步骤 1:从取证镜像中收集 LNK 文件
# Mount forensic image
mount -o ro,loop,offset=$((2048*512)) /cases/case-2024-001/images/evidence.dd /mnt/evidence

mkdir -p /cases/case-2024-001/lnk/{recent,desktop,startup,custom}

# Copy Recent items LNK files (primary source)
cp /mnt/evidence/Users/*/AppData/Roaming/Microsoft/Windows/Recent/*.lnk \
   /cases/case-2024-001/lnk/recent/ 2>/dev/null

# Copy automatic destinations (Jump Lists)
cp /mnt/evidence/Users/*/AppData/Roaming/Microsoft/Windows/Recent/AutomaticDestinations/*.automaticDestinations-ms \
   /cases/case-2024-001/lnk/recent/ 2>/dev/null

# Copy custom destinations (pinned Jump List items)
cp /mnt/evidence/Users/*/AppData/Roaming/Microsoft/Windows/Recent/CustomDestinations/*.customDestinations-ms \
   /cases/case-2024-001/lnk/custom/ 2>/dev/null

# Copy Desktop shortcuts
cp /mnt/evidence/Users/*/Desktop/*.lnk /cases/case-2024-001/lnk/desktop/ 2>/dev/null

# Copy Startup folder shortcuts (persistence)
cp /mnt/evidence/Users/*/AppData/Roaming/Microsoft/Windows/Start\ Menu/Programs/Startup/*.lnk \
   /cases/case-2024-001/lnk/startup/ 2>/dev/null
cp "/mnt/evidence/ProgramData/Microsoft/Windows/Start Menu/Programs/Startup"/*.lnk \
   /cases/case-2024-001/lnk/startup/ 2>/dev/null

# Find all LNK files on the system
find /mnt/evidence/ -name "*.lnk" -type f 2>/dev/null > /cases/case-2024-001/lnk/all_lnk_locations.txt

# Count and hash
ls /cases/case-2024-001/lnk/recent/ | wc -l
sha256sum /cases/case-2024-001/lnk/recent/*.lnk > /cases/case-2024-001/lnk/lnk_hashes.txt 2>/dev/null
步骤 2:使用 LECmd 解析 LNK 文件
# Using Eric Zimmerman's LECmd (Windows or via Mono)
# Process all LNK files in a directory
LECmd.exe -d "C:\cases\lnk\recent\" --csv "C:\cases\analysis\" --csvf lnk_analysis.csv

# Process a single LNK file with verbose output
LECmd.exe -f "C:\cases\lnk\recent\document.pdf.lnk"

# Process Jump List files
JLECmd.exe -d "C:\cases\lnk\recent\" --csv "C:\cases\analysis\" --csvf jumplist_analysis.csv

# Output includes:
# - Source file path
# - Target path (file that was accessed)
# - Target creation, modification, access timestamps
# - LNK creation and modification timestamps
# - Working directory
# - Command line arguments
# - Volume serial number and label
# - Drive type (Fixed, Removable, Network)
# - Machine ID (NetBIOS name)
# - MAC address (from tracker database)
# - File size of target
步骤 3:使用 Python 解析 LNK 文件
pip install LnkParse3

python3 << 'PYEOF'
import LnkParse3
import os, json, csv
from datetime import datetime

lnk_dir = '/cases/case-2024-001/lnk/recent/'
results = []

for filename in sorted(os.listdir(lnk_dir)):
    if not filename.lower().endswith('.lnk'):
        continue

    filepath = os.path.join(lnk_dir, filename)
    try:
        with open(filepath, 'rb') as f:
            lnk = LnkParse3.lnk_file(f)
            info = lnk.get_json()

            parsed = {
                'lnk_file': filename,
                'target_path': '',
                'working_dir': '',
                'arguments': '',
                'target_created': '',
                'target_modified': '',
                'target_accessed': '',
                'file_size': '',
                'drive_type': '',
                'volume_serial': '',
                'volume_label': '',
                'machine_id': '',
                'mac_address': '',
            }

            # Extract header timestamps
            header = info.get('header', {})
            parsed['target_created'] = str(header.get('creation_time', ''))
            parsed['target_modified'] = str(header.get('modified_time', ''))
            parsed['target_accessed'] = str(header.get('accessed_time', ''))
            parsed['file_size'] = str(header.get('file_size', ''))

            # Extract link info
            link_info = info.get('link_info', {})
            if link_info:
                local_path = link_info.get('local_base_path', '')
                network_path = link_info.get('common_network_relative_link', {}).get('net_name', '')
                parsed['target_path'] = local_path or network_path

                vol_info = link_info.get('volume_id', {})
                if vol_info:
                    parsed['drive_type'] = str(vol_info.get('drive_type', ''))
                    parsed['volume_serial'] = str(vol_info.get('drive_serial_number', ''))
                    parsed['volume_label'] = str(vol_info.get('volume_label', ''))

            # Extract string data
            string_data = info.get('string_data', {})
            parsed['working_dir'] = str(string_data.get('working_dir', ''))
            parsed['arguments'] = str(string_data.get('command_line_arguments', ''))

            # Extract tracker data (machine ID and MAC)
            extra = info.get('extra', {})
            tracker = extra.get('DISTRIBUTED_LINK_TRACKER_BLOCK', {})
            if tracker:
                parsed['machine_id'] = str(tracker.get('machine_id', ''))
                parsed['mac_address'] = str(tracker.get('mac_address', ''))

            results.append(parsed)

            # Print summary
            print(f"\n{filename}")
            print(f"  Target: {parsed['target_path']}")
            print(f"  Modified: {parsed['target_modified']}")
            print(f"  Drive: {parsed['drive_type']} (Serial: {parsed['volume_serial']})")
            if parsed['machine_id']:
                print(f"  Machine: {parsed['machine_id']}")

    except Exception as e:
        print(f"  Error parsing {filename}: {e}")

# Write results to CSV
with open('/cases/case-2024-001/analysis/lnk_analysis.csv', 'w', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=results[0].keys() if results else [])
    writer.writeheader()
    writer.writerows(results)

print(f"\n\nTotal LNK files parsed: {len(results)}")
PYEOF
步骤 4:分析调查价值
# Identify files accessed from removable media
python3 << 'PYEOF'
import csv

with open('/cases/case-2024-001/analysis/lnk_analysis.csv') as f:
    reader = csv.DictReader(f)

    print("=== FILES ACCESSED FROM REMOVABLE MEDIA ===\n")
    removable = []
    network = []

    for row in reader:
        if 'DRIVE_REMOVABLE' in row.get('drive_type', '').upper() or \
           'removable' in row.get('drive_type', '').lower():
            removable.append(row)
            print(f"  {row['target_modified']} | {row['target_path']} | Vol: {row['volume_serial']}")

        if 'network' in row.get('drive_type', '').lower() or \
           row.get('target_path', '').startswith('\\\\'):
            network.append(row)

    print(f"\n=== FILES ACCESSED FROM NETWORK SHARES ===\n")
    for row in network:
        print(f"  {row['target_modified']} | {row['target_path']}")

    print(f"\nRemovable media files: {len(removable)}")
    print(f"Network share files: {len(network)}")

    # Check for unique machines (tracker data)
    machines = set()
    for row in [*removable, *network]:
        if row.get('machine_id'):
            machines.add(row['machine_id'])
    if machines:
        print(f"\nMachine IDs found: {machines}")
PYEOF

# Check Startup folder LNK files for persistence
echo "=== STARTUP FOLDER SHORTCUTS (PERSISTENCE) ===" > /cases/case-2024-001/analysis/startup_persistence.txt
for lnk in /cases/case-2024-001/lnk/startup/*.lnk; do
    python3 -c "
import LnkParse3
with open('$lnk', 'rb') as f:
    lnk = LnkParse3.lnk_file(f)
    info = lnk.get_json()
    target = info.get('link_info', {}).get('local_base_path', 'Unknown')
    args = info.get('string_data', {}).get('command_line_arguments', '')
    print(f'  $(basename $lnk): {target} {args}')
" >> /cases/case-2024-001/analysis/startup_persistence.txt 2>/dev/null
done

关键概念

概念描述
Shell Link (.lnk)Windows 快捷方式文件格式,包含目标路径、时间戳和元数据
目标时间戳快捷方式所指向文件的创建、修改和访问时间
卷序列号目标文件所在驱动器卷的唯一标识符
机器 ID由分布式链接跟踪服务嵌入的 NetBIOS 名称
MAC 地址创建 LNK 文件的机器的网络适配器 MAC
跳转列表每个应用程序的最近和固定文件列表(包含嵌入的 LNK 数据)
自动目标系统管理的最近打开文件的跳转列表条目
自定义目标用户固定的跳转列表项,在手动移除之前持续存在

工具与系统

工具用途
LECmdEric Zimmerman 的命令行 LNK 文件解析器,支持 CSV/JSON 输出
JLECmdEric Zimmerman 的跳转列表解析器
LnkParse3用于程序化 LNK 文件分析的 Python 库
lnk_parser替代的 Python LNK 解析工具
Autopsy带 LNK 文件分析模块的取证平台
KAPE自动化 LNK 和跳转列表痕迹收集
Plaso带 LNK 文件解析器的时间线工具,用于创建超级时间线
LNK Explorer用于交互式检查 LNK 文件的 GUI 工具

常见场景

场景 1:通过 USB 驱动器进行数据泄露 分析 Recent 文件夹中指向可移动驱动器上目标的 LNK 文件,将卷序列号与 USBSTOR 注册表项关联,构建从 USB 设备访问的文件列表,确定从可移动驱动器打开了哪些文档,与文件复制时间戳关联。

场景 2:通过启动快捷方式实现恶意软件持久化 检查 Startup 文件夹中指向恶意目标的 LNK 文件,检查目标路径和参数中的编码命令或可疑可执行文件,验证目标文件是否存在并对其进行检查,将创建时间戳与初始入侵时间关联。

场景 3:网络共享访问调查 筛选包含网络路径(UNC 目标)的 LNK 文件,识别访问了哪些网络共享以及访问时间,将机器 ID 与已知企业系统关联,检查是否在正常职责之外访问了敏感文件服务器,为合规调查构建访问时间线。

场景 4:用于法律程序的文件访问时间线 提取所有 Recent 文件夹中的 LNK 文件,构建用户访问文档的时间顺序列表,识别与案件相关的特定文件,呈现显示文件打开时间的目标时间戳,与电子邮件和通信时间线关联。

输出格式

LNK File Analysis Summary:
  User Profile: suspect_user
  Total LNK Files: 234 (Recent: 198, Desktop: 23, Startup: 5, Other: 8)

  File Access Statistics:
    Local drive (C:):    156 files
    Removable media:     23 files (3 unique volume serials)
    Network shares:      15 files (\\server01, \\fileserver)
    Other drives:        4 files

  Machine IDs Found: DESKTOP-ABC123, LAPTOP-XYZ789
  MAC Addresses: AA:BB:CC:DD:EE:FF, 11:22:33:44:55:66

  Removable Media Access:
    Volume Serial 1234-ABCD:
      2024-01-15 14:32 - E:\Confidential\financial_report.xlsx
      2024-01-15 14:45 - E:\Confidential\customer_database.csv
      2024-01-15 15:00 - E:\Projects\source_code.zip

  Startup Persistence:
    updater.lnk -> C:\ProgramData\svc\updater.exe (SUSPICIOUS)
    OneDrive.lnk -> C:\Users\...\OneDrive.exe (Legitimate)

  Timeline: /cases/case-2024-001/analysis/lnk_analysis.csv

评论

支持 Markdown