Communitygithub.com

windows-lnk-파일-분석을-통한-아티팩트-추출

Windows LNK 바로가기 파일을 파싱하여 대상 경로, MAC 타임스탬프, 볼륨 정보, 머신 ID 등 포렌식 아티팩트를 추출합니다.

windows-lnk-파일-분석을-통한-아티팩트-추출란 무엇인가요?

이 스킬은 Windows LNK(Shell Link) 파일을 분석하여 사용자 파일 접근 기록, 네트워크 공유 및 이동식 미디어 사용 추적, 특정 문서 열람 증명 등 포렌식 조사에 필요한 핵심 아티팩트를 추출하는 방법을 제공합니다. LECmd, LnkParse3 등 다양한 도구를 활용하여 LNK 파일을 수집, 파싱, 분석하는 전 과정을 상세히 안내하며, 최종적으로 CSV 형식의 분석 결과를 생성합니다. 주요 분석 항목으로는 대상 파일 경로 및 타임스탬프(생성/수정/접근), 볼륨 일련번호, 드라이브 유형(고정/이동식/네트워크), 머신 ID(NetBIOS 이름), MAC 주소 등이 포함됩니다. 또한 USB 드라이브를 통한 데이터 유출, 시작 폴더 단축키를 이용한 악성코드 지속성, 네트워크 공유 접근 조사 등 실제 조사 시나리오를 제시하여 실무에서 즉시 활용할 수 있도록 구성되었습니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mukul975/Anthropic-Cybersecurity-Skills/tree/main/skills/analyzing-windows-lnk-files-for-artifacts

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Windows LNK 파일 분석을 통한 아티팩트 추출

사용 시기

  • Windows 바로가기 파일에서 사용자 파일 접근 기록을 재구성할 때
  • 접근된 파일, 네트워크 공유, 이동식 미디어를 추적할 때
  • 조사 중 사용자가 특정 문서를 열었음을 증명해야 할 때
  • 파일 접근을 다른 타임라인 아티팩트와 상호 연관시키려 할 때
  • 원격 시스템 또는 USB 장치에서 접근된 경로를 식별할 때

전제 조건

  • 포렌식 이미지에서 LNK 파일 접근 가능 (최근 항목, 바탕 화면, 빠른 실행)
  • 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}

# 최근 항목 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

# 시작 폴더 바로가기 복사 (지속성)
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 생성 및 수정 타임스탬프
# - 작업 디렉터리
# - 명령줄 인자
# - 볼륨 일련번호 및 레이블
# - 드라이브 유형 (고정, 이동식, 네트워크)
# - 머신 ID (NetBIOS 이름)
# - MAC 주소 (트래커 데이터베이스에서)
# - 대상 파일 크기

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', ''))

            # 트래커 데이터 추출 (머신 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"  대상: {parsed['target_path']}")
            print(f"  수정됨: {parsed['target_modified']}")
            print(f"  드라이브: {parsed['drive_type']} (일련번호: {parsed['volume_serial']})")
            if parsed['machine_id']:
                print(f"  머신: {parsed['machine_id']}")

    except Exception as e:
        print(f"  {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\n총 파싱된 LNK 파일: {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("=== 이동식 미디어에서 접근된 파일 ===\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']} | 볼륨: {row['volume_serial']}")

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

    print(f"\n=== 네트워크 공유에서 접근된 파일 ===\n")
    for row in network:
        print(f"  {row['target_modified']} | {row['target_path']}")

    print(f"\n이동식 미디어 파일: {len(removable)}")
    print(f"네트워크 공유 파일: {len(network)}")

    # 고유 머신 확인 (트래커 데이터)
    machines = set()
    for row in [*removable, *network]:
        if row.get('machine_id'):
            machines.add(row['machine_id'])
    if machines:
        print(f"\n발견된 머신 ID: {machines}")
PYEOF

# 시작 폴더 LNK 파일 확인 (지속성)
echo "=== 시작 폴더 바로가기 (지속성) ===" > /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', '알 수 없음')
    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
Jump Lists애플리케이션별 최근 및 고정 파일 목록 (내장 LNK 데이터 포함)
자동 대상최근 연 파일에 대한 시스템 관리 Jump List 항목
사용자 지정 대상사용자가 고정한 Jump List 항목 (수동 제거 시까지 유지)

도구 및 시스템

도구목적
LECmdEric Zimmerman의 LNK 파일 파서 (CSV/JSON 출력)
JLECmdEric Zimmerman의 Jump List 파서
LnkParse3프로그래밍 방식 LNK 파일 분석을 위한 Python 라이브러리
lnk_parser대체 Python LNK 파싱 도구
AutopsyLNK 파일 분석 모듈을 포함한 포렌식 플랫폼
KAPE자동화된 LNK 및 Jump List 아티팩트 수집
Plaso슈퍼 타임라인 생성을 위한 LNK 파일 파서 포함 타임라인 도구
LNK Explorer대화형 LNK 파일 검사를 위한 GUI 도구

일반 시나리오

시나리오 1: USB 드라이브를 통한 데이터 유출 최근 폴더 LNK 파일을 분석하여 이동식 드라이브의 대상을 찾고, 볼륨 일련번호를 USBSTOR 레지스트리 항목과 상호 연관시키고, USB 장치에서 접근된 파일 목록을 작성하고, 이동식 드라이브에서 열린 문서를 확인하고, 파일 복사 타임스탬프와 상호 연관시킵니다.

시나리오 2: 시작 폴더 바로가기를 통한 악성코드 지속성 시작 폴더 LNK 파일에서 악성 대상을 검사하고, 대상 경로와 인자에서 인코딩된 명령 또는 의심스러운 실행 파일을 확인하고, 대상 파일이 존재하는지 검증하고 검사하며, 생성 타임스탬프를 초기 침해 시간과 상호 연관시킵니다.

시나리오 3: 네트워크 공유 접근 조사 네트워크 경로(UNC 대상)가 있는 LNK 파일을 필터링하고, 접근된 네트워크 공유와 시간을 식별하고, 머신 ID를 알려진 기업 시스템과 상호 연관시키고, 정상 업무 외에 민감한 파일 서버에 접근했는지 확인하며, 규정 준수 조사를 위한 접근 타임라인을 구축합니다.

시나리오 4: 법적 절차를 위한 문서 접근 타임라인 모든 최근 폴더 LNK 파일을 추출하고, 사용자가 접근한 문서의 시간순 목록을 작성하고, 사건과 관련된 특정 파일을 식별하고, 파일이 열린 시간을 보여주는 대상 타임스탬프를 제시하며, 이메일 및 통신 타임라인과 상호 연관시킵니다.

출력 형식

LNK 파일 분석 요약:
  사용자 프로필: suspect_user
  총 LNK 파일: 234개 (최근 항목: 198, 바탕 화면: 23, 시작: 5, 기타: 8)

  파일 접근 통계:
    로컬 드라이브 (C:):    156개 파일
    이동식 미디어:         23개 파일 (3개의 고유 볼륨 일련번호)
    네트워크 공유:         15개 파일 (\\server01, \\fileserver)
    기타 드라이브:          4개 파일

  발견된 머신 ID: DESKTOP-ABC123, LAPTOP-XYZ789
  MAC 주소: AA:BB:CC:DD:EE:FF, 11:22:33:44:55:66

  이동식 미디어 접근:
    볼륨 일련번호 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

  시작 폴더 지속성:
    updater.lnk -> C:\ProgramData\svc\updater.exe (의심스러움)
    OneDrive.lnk -> C:\Users\...\OneDrive.exe (정상)

  타임라인: /cases/case-2024-001/analysis/lnk_analysis.csv

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,

관련 스킬