mcpField
A
analyzing-usb-device-connection-history

analyzing-usb-device-connection-history

github.com/mukul975セキュリティ35.2k235 回インストール8 週間前に更新
リポジトリ

analyzing-usb-device-connection-history について

WindowsのUSBデバイス接続履歴を調べるデジタルフォレンジック向けスキルです。レジストリ、セットアップログ、イベントログの証跡を時系列にまとめ、インシデント対応や内部調査、監査に役立てます。

主な機能

  1. 01USBレジストリ証跡の抽出
  2. 02ドライブ文字とユーザーの対応確認
  3. 03初回接続時刻の特定
  4. 04デバイス活動タイムラインの作成
  5. 05デバイス識別情報の照合

活用シーン

  1. 01リムーバブルメディア経由の情報流出調査
  2. 02未承認USBデバイスの監査
  3. 03USB関連マルウェア事案の追跡
  4. 04フォレンジックイメージ間でのデバイス追跡

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill analyzing-usb-device-connection-history

インストール後、Claude Code で/analyzing-usb-device-connection-historyを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

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

詳細

USB デバイスの接続履歴の分析

使用する場面

  • リムーバブルストレージデバイスを介したデータ持ち出しの可能性を調査する場合
  • 内部脅威の調査で USB デバイスの使用状況を追跡する場合
  • リムーバブルメディアのポリシーが適用されていることを確認するコンプライアンス監査
  • USB 接続とファイルアクセスおよびコピーイベントを関連付ける場合
  • インシデント発生時のデバイス接続のタイムラインを作成する場合

前提条件

  • フォレンジックイメージ、または抽出済みのレジストリハイブとイベントログ
  • SYSTEM、SOFTWARE、NTUSER.DAT のレジストリハイブへのアクセス
  • SetupAPI ログ(setupapi.dev.log)
  • Windows イベントログ(System、Security、DriverFrameworks-UserMode)
  • USBDeview、USB Forensic Tracker、または RegRipper
  • USB デバイスの識別情報(VID、PID、シリアル番号)の理解

ワークフロー

ステップ 1:USB 関連アーティファクトを抽出する
# Mount forensic image and copy relevant artifacts
mount -o ro,loop,offset=$((2048*512)) /cases/case-2024-001/images/evidence.dd /mnt/evidence

mkdir -p /cases/case-2024-001/usb/

# Registry hives
cp /mnt/evidence/Windows/System32/config/SYSTEM /cases/case-2024-001/usb/
cp /mnt/evidence/Windows/System32/config/SOFTWARE /cases/case-2024-001/usb/
cp /mnt/evidence/Users/*/NTUSER.DAT /cases/case-2024-001/usb/

# SetupAPI logs (first connection timestamps)
cp /mnt/evidence/Windows/INF/setupapi.dev.log /cases/case-2024-001/usb/

# Event logs
cp /mnt/evidence/Windows/System32/winevt/Logs/System.evtx /cases/case-2024-001/usb/
cp "/mnt/evidence/Windows/System32/winevt/Logs/Microsoft-Windows-DriverFrameworks-UserMode%4Operational.evtx" \
   /cases/case-2024-001/usb/ 2>/dev/null
cp "/mnt/evidence/Windows/System32/winevt/Logs/Microsoft-Windows-Partition%4Diagnostic.evtx" \
   /cases/case-2024-001/usb/ 2>/dev/null
ステップ 2:USBSTOR レジストリキーを解析する
# Extract USBSTOR entries from SYSTEM hive
python3 << 'PYEOF'
from Registry import Registry
import json

reg = Registry.Registry("/cases/case-2024-001/usb/SYSTEM")

# Find current ControlSet
select = reg.open("Select")
current = select.value("Current").value()
controlset = f"ControlSet{current:03d}"

# Parse USBSTOR
usbstor_path = f"{controlset}\\Enum\\USBSTOR"
usbstor = reg.open(usbstor_path)

devices = []
print("=== USBSTOR DEVICES ===\n")

for device_class in usbstor.subkeys():
    # Format: Disk&Ven_VENDOR&Prod_PRODUCT&Rev_REVISION
    class_name = device_class.name()
    parts = class_name.split('&')
    vendor = parts[1].replace('Ven_', '') if len(parts) > 1 else 'Unknown'
    product = parts[2].replace('Prod_', '') if len(parts) > 2 else 'Unknown'
    revision = parts[3].replace('Rev_', '') if len(parts) > 3 else 'Unknown'

    for instance in device_class.subkeys():
        serial = instance.name()
        last_write = instance.timestamp()

        device_info = {
            'vendor': vendor,
            'product': product,
            'revision': revision,
            'serial': serial,
            'last_connected': str(last_write),
        }

        # Get friendly name if available
        try:
            friendly = instance.value("FriendlyName").value()
            device_info['friendly_name'] = friendly
        except:
            pass

        # Get device parameters
        try:
            params = instance.subkey("Device Parameters")
            try:
                device_info['class_guid'] = params.value("ClassGUID").value()
            except:
                pass
        except:
            pass

        devices.append(device_info)
        print(f"Device: {vendor} {product}")
        print(f"  Serial: {serial}")
        print(f"  Last Connected: {last_write}")
        print(f"  Friendly Name: {device_info.get('friendly_name', 'N/A')}")
        print()

# Save results
with open('/cases/case-2024-001/analysis/usb_devices.json', 'w') as f:
    json.dump(devices, f, indent=2)

print(f"\nTotal USB storage devices found: {len(devices)}")
PYEOF
ステップ 3:ドライブ文字の割り当てとユーザーとの関連を抽出する
# Parse MountedDevices from SYSTEM hive
python3 << 'PYEOF'
from Registry import Registry
import struct

reg = Registry.Registry("/cases/case-2024-001/usb/SYSTEM")

mounted = reg.open("MountedDevices")

print("=== MOUNTED DEVICES (Drive Letter Assignments) ===\n")
for value in mounted.values():
    name = value.name()
    data = value.value()

    if name.startswith("\\DosDevices\\"):
        drive_letter = name.replace("\\DosDevices\\", "")
        if len(data) > 24:
            # USB device - contains device path string
            try:
                device_path = data.decode('utf-16-le').strip('\x00')
                if 'USBSTOR' in device_path or 'USB#' in device_path:
                    print(f"  {drive_letter} -> {device_path}")
            except:
                pass
        else:
            # Fixed disk - contains disk signature + offset
            disk_sig = struct.unpack('<I', data[0:4])[0]
            offset = struct.unpack('<Q', data[4:12])[0]
            print(f"  {drive_letter} -> Disk Signature: 0x{disk_sig:08X}, Offset: {offset}")
PYEOF

# Parse user MountPoints2 (which user accessed which devices)
python3 << 'PYEOF'
from Registry import Registry
import os, glob

print("\n=== USER MOUNT POINTS (MountPoints2) ===\n")

for ntuser in glob.glob("/cases/case-2024-001/usb/NTUSER*.DAT"):
    try:
        reg = Registry.Registry(ntuser)
        mp2 = reg.open("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints2")

        print(f"User hive: {os.path.basename(ntuser)}")
        for key in mp2.subkeys():
            guid = key.name()
            last_write = key.timestamp()
            if '{' in guid:
                print(f"  Volume: {guid} | Last accessed: {last_write}")
        print()
    except Exception as e:
        print(f"  Error parsing {ntuser}: {e}")
PYEOF
ステップ 4:SetupAPI から初回接続タイムスタンプを抽出する
# Parse setupapi.dev.log for USB device first-install timestamps
python3 << 'PYEOF'
import re

print("=== SETUPAPI USB DEVICE INSTALLATIONS ===\n")

with open('/cases/case-2024-001/usb/setupapi.dev.log', 'r', errors='ignore') as f:
    content = f.read()

# Find USB device installation sections
pattern = r'>>>\s+\[Device Install.*?\n.*?Section start (\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}).*?\n(.*?)<<<'
matches = re.findall(pattern, content, re.DOTALL)

usb_installs = []
for timestamp, section in matches:
    if 'USBSTOR' in section or 'USB\\VID' in section:
        # Extract device ID
        dev_match = re.search(r'(USBSTOR\\[^\s]+|USB\\VID_\w+&PID_\w+[^\s]*)', section)
        if dev_match:
            device_id = dev_match.group(1)
            usb_installs.append({
                'first_install': timestamp,
                'device_id': device_id
            })
            print(f"  {timestamp} | {device_id}")

print(f"\nTotal USB installations found: {len(usb_installs)}")
PYEOF

# Parse Windows Event Logs for USB events
# Event IDs: 2003, 2010, 2100, 2102 (DriverFrameworks-UserMode)
# Event IDs: 6416 (Security - new external device recognized)
python3 << 'PYEOF'
import json
from evtx import PyEvtxParser

try:
    parser = PyEvtxParser("/cases/case-2024-001/usb/System.evtx")

    print("\n=== SYSTEM EVENT LOG USB EVENTS ===\n")
    for record in parser.records_json():
        data = json.loads(record['data'])
        event_id = str(data['Event']['System']['EventID'])

        # USB device connection events
        if event_id in ('20001', '20003', '10000', '10100'):
            timestamp = data['Event']['System']['TimeCreated']['#attributes']['SystemTime']
            event_data = data['Event'].get('UserData', data['Event'].get('EventData', {}))
            print(f"  [{timestamp}] EventID {event_id}: {json.dumps(event_data, default=str)[:200]}")
except Exception as e:
    print(f"Error: {e}")
PYEOF
ステップ 5:USB アクティビティのタイムラインを作成して報告する
# Compile all USB evidence into a unified timeline
python3 << 'PYEOF'
import json, csv

timeline = []

# Load USBSTOR data
with open('/cases/case-2024-001/analysis/usb_devices.json') as f:
    devices = json.load(f)

for device in devices:
    timeline.append({
        'timestamp': device['last_connected'],
        'source': 'USBSTOR Registry',
        'device': f"{device['vendor']} {device['product']}",
        'serial': device['serial'],
        'event': 'Last Connected',
        'detail': device.get('friendly_name', '')
    })

# Sort chronologically
timeline.sort(key=lambda x: x['timestamp'])

# Write timeline CSV
with open('/cases/case-2024-001/analysis/usb_timeline.csv', 'w', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=['timestamp', 'source', 'device', 'serial', 'event', 'detail'])
    writer.writeheader()
    writer.writerows(timeline)

print(f"USB Timeline: {len(timeline)} events written to usb_timeline.csv")

# Print summary
print("\n=== USB DEVICE SUMMARY ===")
for entry in timeline:
    print(f"  {entry['timestamp']} | {entry['device']} | {entry['serial'][:20]} | {entry['event']}")
PYEOF

主な概念

概念説明
USBSTORUSB マスストレージデバイスの識別情報と接続データを保存するレジストリキー
VID/PIDUSB デバイスのメーカーとモデルを一意に識別するベンダー ID と製品 ID
デバイスのシリアル番号個々の USB デバイスを識別する一意の番号(シリアル番号を共有するデバイスもあります)
MountedDevicesボリューム GUID とドライブ文字を物理デバイスに対応付けるレジストリキー
MountPoints2ユーザーがアクセスしたボリュームを示すユーザーごとのレジストリキー
SetupAPI ログデバイスの初回接続を記録する Windows ドライバーインストールログ
DeviceContainersデバイスのメタデータとタイムスタンプを含む、SOFTWARE ハイブ内のレジストリキー
EMDMgmtReadyBoost 対応デバイスをシリアル番号とタイムスタンプとともに追跡するレジストリキー

ツールとシステム

ツール目的
USB Forensic TrackerUSB デバイスの履歴抽出に特化したツール
USBDeviewシステムに接続されたすべての USB デバイスを一覧表示する NirSoft のツール
RegRipper(usbstor プラグイン)レジストリハイブから USB アーティファクトを自動抽出
Registry ExplorerUSB 関連キーを対話的にレジストリ分析
KAPEUSB 関連アーティファクトの自動収集
Plaso/log2timelineUSB 接続イベントを含むタイムラインの作成
FTK Imagerリムーバブルメディアを含むフォレンジックイメージの作成
VelociraptorUSB デバイス履歴のハンティング用アーティファクトを備えたエンドポイントエージェント

よくあるシナリオ

シナリオ 1:退職予定の従業員によるデータ持ち出し USBSTOR エントリを抽出して、これまでに接続されたすべての USB デバイスを特定し、デバイスのシリアル番号を MountPoints2 と照合してユーザーのアクセスを確認します。タイムスタンプをファイルアクセスログやジャンプリストの最近使ったファイルと相互参照し、USN ジャーナルで大容量ファイルのコピーのパターンを確認します。

シナリオ 2:セキュアなシステムでの未承認デバイス すべての USBSTOR エントリを承認済みデバイスリストと照合し、企業で承認されたハードウェアと VID/PID が一致しない未承認デバイスを特定します。未承認デバイスの初回および最終接続日時を特定し、データが転送されたかどうかを確認します。

シナリオ 3:USB 経由のマルウェア配信 マルウェアの実行直前に接続された USB デバイスを特定し(Prefetch のタイムスタンプ)、デバイスのシリアル番号とベンダー情報を抽出します。デバイスで自動実行が有効になっていたか確認し、Prefetch と ShimCache でリムーバブルドライブのドライブ文字から実行ファイルが起動された形跡を探します。

シナリオ 4:複数のシステムにわたる特定の USB ドライブの追跡 すべてのフォレンジックイメージの USBSTOR から同じデバイスのシリアル番号を検索し、そのドライブがどのシステムにいつ接続されたかを示すマップを作成します。組織内でのデバイスの移動経路を時系列で特定し、ネットワーク共有へのアクセスログと関連付けます。

出力形式

USB Device History Analysis:
  System: DESKTOP-ABC123 (Windows 10 Pro)
  Total USB Storage Devices: 12
  Analysis Sources: USBSTOR, MountedDevices, MountPoints2, SetupAPI, Event Logs

  Device Inventory:
    1. Kingston DataTraveler 3.0 (Serial: 0019E06B4521A2B0)
       First Connected:  2024-01-10 09:15:32 (SetupAPI)
       Last Connected:   2024-01-18 14:30:00 (USBSTOR)
       Drive Letter:     E:
       User Access:      suspect_user (MountPoints2)

    2. WD My Passport (Serial: 575834314131363035)
       First Connected:  2024-01-15 20:00:00
       Last Connected:   2024-01-15 23:45:00
       Drive Letter:     F:
       User Access:      suspect_user

  Suspicious Findings:
    - Kingston drive connected 15 times during investigation period
    - WD Passport connected only once, late evening (unusual hours)
    - Unknown device (VID_1234&PID_5678) connected 2024-01-17, no matching approved device

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

コメント