Die Oberfläche ist lokalisiert; Skill-Beschreibungen und -Dokumente werden per KI automatisch in Ihre Sprache übersetzt. Code, Befehle, Pfade und Fachbegriffe bleiben im Original, maßgeblich ist das Dokument des Autors.
Skills entdecken
Produktivität · SKILL.md

analyzing-windows-lnk-files-for-artifacts

analyzing-windows-lnk-files-for-artifacts

解析 Windows LNK 快捷方式文件,提取目标路径、时间戳、卷信息和机器标识符,用于取证时间线重建。

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill-Dokumentation

GitHub

name: analyzing-windows-lnk-files-for-artifacts description: 解析 Windows LNK 快捷方式文件,提取目标路径、时间戳、卷信息和机器标识符,用于取证时间线重建。 domain: cybersecurity subdomain: digital-forensics tags: [forensics, lnk-files, windows-artifacts, shortcut-analysis, timeline-reconstruction, evidence-collection] version: "1.0" author: mahipal license: Apache-2.0

分析 Windows LNK 文件取证痕迹

适用场景

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

前置条件

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

工作流程

步骤 1:从取证镜像收集 LNK 文件

# 以只读方式挂载取证镜像
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}

# 复制 Recent 目录下的 LNK 文件(主要来源)
cp /mnt/evidence/Users/*/AppData/Roaming/Microsoft/Windows/Recent/*.lnk \
   /cases/case-2024-001/lnk/recent/ 2>/dev/null

# 复制自动目标文件(Jump Lists)
cp /mnt/evidence/Users/*/AppData/Roaming/Microsoft/Windows/Recent/AutomaticDestinations/*.automaticDestinations-ms \
   /cases/case-2024-001/lnk/recent/ 2>/dev/null

# 复制自定义目标文件(固定的 Jump List 项目)
cp /mnt/evidence/Users/*/AppData/Roaming/Microsoft/Windows/Recent/CustomDestinations/*.customDestinations-ms \
   /cases/case-2024-001/lnk/custom/ 2>/dev/null

# 复制桌面快捷方式
cp /mnt/evidence/Users/*/Desktop/*.lnk /cases/case-2024-001/lnk/desktop/ 2>/dev/null

# 复制 Startup 文件夹快捷方式(持久化)
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

# 查找系统中所有 LNK 文件
find /mnt/evidence/ -name "*.lnk" -type f 2>/dev/null > /cases/case-2024-001/lnk/all_lnk_locations.txt

# 统计并哈希
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 文件

# 使用 Eric Zimmerman 的 LECmd(Windows 或通过 Mono)
# 处理目录中所有 LNK 文件
LECmd.exe -d "C:\cases\lnk\recent\" --csv "C:\cases\analysis\" --csvf lnk_analysis.csv

# 以详细输出模式处理单个 LNK 文件
LECmd.exe -f "C:\cases\lnk\recent\document.pdf.lnk"

# 处理 Jump List 文件
JLECmd.exe -d "C:\cases\lnk\recent\" --csv "C:\cases\analysis\" --csvf jumplist_analysis.csv

# 输出包含:
# - 源文件路径
# - 目标路径(被访问的文件)
# - 目标创建、修改、访问时间戳
# - LNK 创建和修改时间戳
# - 工作目录
# - 命令行参数
# - 卷序列号和标签
# - 驱动器类型(Fixed、Removable、Network)
# - 机器 ID(NetBIOS 名称)
# - MAC 地址(来自 tracker 数据库)
# - 目标文件大小

步骤 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': '',
            }

            # 提取头部时间戳
            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', ''))

            # 提取链接信息
            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', ''))

            # 提取字符串数据
            string_data = info.get('string_data', {})
            parsed['working_dir'] = str(string_data.get('working_dir', ''))
            parsed['arguments'] = str(string_data.get('command_line_arguments', ''))

            # 提取 tracker 数据(机器 ID 和 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(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}")

# 将结果写入 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:分析取证价值

# 识别从可移动介质访问的文件
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)}")

    # 检查唯一机器(tracker 数据)
    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

# 检查 Startup 文件夹 LNK 文件以发现持久化
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由分布式链接跟踪(Distributed Link Tracking)服务嵌入的 NetBIOS 名称
MAC 地址创建 LNK 文件的机器上的网络适配器 MAC
Jump Lists每个应用程序的最近和固定文件列表(包含嵌入的 LNK 数据)
自动目标(Automatic Destinations)系统管理的最近打开文件 Jump List 条目
自定义目标(Custom Destinations)用户固定的 Jump List 项目,手动删除前一直保留

工具与系统

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

常见场景

场景 1:通过 USB 驱动器数据外泄(Data Exfiltration) 分析 Recent 文件夹 LNK 文件中指向可移动驱动器的目标,将卷序列号与 USBSTOR 注册表条目关联,建立从 USB 设备访问的文件列表,确认哪些文档是从可移动驱动器打开的,与文件复制时间戳关联。

场景 2:通过 Startup 快捷方式恶意软件持久化 检查 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
Gespeicherte Skills