analyzing-usb-device-connection-history について
WindowsのUSBデバイス接続履歴を調べるデジタルフォレンジック向けスキルです。レジストリ、セットアップログ、イベントログの証跡を時系列にまとめ、インシデント対応や内部調査、監査に役立てます。
主な機能
- 01USBレジストリ証跡の抽出
- 02ドライブ文字とユーザーの対応確認
- 03初回接続時刻の特定
- 04デバイス活動タイムラインの作成
- 05デバイス識別情報の照合
活用シーン
- 01リムーバブルメディア経由の情報流出調査
- 02未承認USBデバイスの監査
- 03USB関連マルウェア事案の追跡
- 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 と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/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
主な概念
| 概念 | 説明 |
|---|---|
| USBSTOR | USB マスストレージデバイスの識別情報と接続データを保存するレジストリキー |
| VID/PID | USB デバイスのメーカーとモデルを一意に識別するベンダー ID と製品 ID |
| デバイスのシリアル番号 | 個々の USB デバイスを識別する一意の番号(シリアル番号を共有するデバイスもあります) |
| MountedDevices | ボリューム GUID とドライブ文字を物理デバイスに対応付けるレジストリキー |
| MountPoints2 | ユーザーがアクセスしたボリュームを示すユーザーごとのレジストリキー |
| SetupAPI ログ | デバイスの初回接続を記録する Windows ドライバーインストールログ |
| DeviceContainers | デバイスのメタデータとタイムスタンプを含む、SOFTWARE ハイブ内のレジストリキー |
| EMDMgmt | ReadyBoost 対応デバイスをシリアル番号とタイムスタンプとともに追跡するレジストリキー |
ツールとシステム
| ツール | 目的 |
|---|---|
| USB Forensic Tracker | USB デバイスの履歴抽出に特化したツール |
| USBDeview | システムに接続されたすべての USB デバイスを一覧表示する NirSoft のツール |
| RegRipper(usbstor プラグイン) | レジストリハイブから USB アーティファクトを自動抽出 |
| Registry Explorer | USB 関連キーを対話的にレジストリ分析 |
| KAPE | USB 関連アーティファクトの自動収集 |
| Plaso/log2timeline | USB 接続イベントを含むタイムラインの作成 |
| FTK Imager | リムーバブルメディアを含むフォレンジックイメージの作成 |
| Velociraptor | USB デバイス履歴のハンティング用アーティファクトを備えたエンドポイントエージェント |
よくあるシナリオ
シナリオ 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