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 -o ro,loop,offset=$((2048*512)) /cases/case-2024-001/images/evidence.dd /mnt/evidence
mkdir -p /cases/case-2024-001/usb/
# レジストリハイブ
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ログ(初回接続タイムスタンプ)
cp /mnt/evidence/Windows/INF/setupapi.dev.log /cases/case-2024-001/usb/
# イベントログ
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レジストリキーの解析
# SYSTEMハイブからUSBSTORエントリを抽出
python3 << 'PYEOF'
from Registry import Registry
import json
reg = Registry.Registry("/cases/case-2024-001/usb/SYSTEM")
# 現在のControlSetを特定
select = reg.open("Select")
current = select.value("Current").value()
controlset = f"ControlSet{current:03d}"
# USBSTORを解析
usbstor_path = f"{controlset}\\Enum\\USBSTOR"
usbstor = reg.open(usbstor_path)
devices = []
print("=== USBSTORデバイス ===\n")
for device_class in usbstor.subkeys():
# 形式: 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 '不明'
product = parts[2].replace('Prod_', '') if len(parts) > 2 else '不明'
revision = parts[3].replace('Rev_', '') if len(parts) > 3 else '不明'
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),
}
# フレンドリ名が利用可能な場合は取得
try:
friendly = instance.value("FriendlyName").value()
device_info['friendly_name'] = friendly
except:
pass
# デバイスパラメータを取得
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"デバイス: {vendor} {product}")
print(f" シリアル: {serial}")
print(f" 最終接続: {last_write}")
print(f" フレンドリ名: {device_info.get('friendly_name', 'N/A')}")
print()
# 結果を保存
with open('/cases/case-2024-001/analysis/usb_devices.json', 'w') as f:
json.dump(devices, f, indent=2)
print(f"\n検出されたUSBストレージデバイスの総数: {len(devices)}")
PYEOF
手順3: ドライブレター割り当てとユーザー関連付けの抽出
# SYSTEMハイブからMountedDevicesを解析
python3 << 'PYEOF'
from Registry import Registry
import struct
reg = Registry.Registry("/cases/case-2024-001/usb/SYSTEM")
mounted = reg.open("MountedDevices")
print("=== マウント済みデバイス(ドライブレター割り当て)===\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デバイス - デバイスパス文字列を含む
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:
# 固定ディスク - ディスク署名+オフセットを含む
disk_sig = struct.unpack('<I', data[0:4])[0]
offset = struct.unpack('<Q', data[4:12])[0]
print(f" {drive_letter} -> ディスク署名: 0x{disk_sig:08X}, オフセット: {offset}")
PYEOF
# ユーザーのMountPoints2を解析(どのユーザーがどのデバイスにアクセスしたか)
python3 << 'PYEOF'
from Registry import Registry
import os, glob
print("\n=== ユーザーマウントポイント(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"ユーザーハイブ: {os.path.basename(ntuser)}")
for key in mp2.subkeys():
guid = key.name()
last_write = key.timestamp()
if '{' in guid:
print(f" ボリューム: {guid} | 最終アクセス: {last_write}")
print()
except Exception as e:
print(f" {ntuser}の解析エラー: {e}")
PYEOF
手順4: SetupAPIから初回接続タイムスタンプの抽出
# setupapi.dev.logからUSBデバイスの初回インストールタイムスタンプを解析
python3 << 'PYEOF'
import re
print("=== SETUPAPI USBデバイスインストール ===\n")
with open('/cases/case-2024-001/usb/setupapi.dev.log', 'r', errors='ignore') as f:
content = f.read()
# USBデバイスインストールセクションを検索
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:
# デバイス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"\n検出されたUSBインストールの総数: {len(usb_installs)}")
PYEOF
# WindowsイベントログからUSBイベントを解析
# イベントID: 2003、2010、2100、2102 (DriverFrameworks-UserMode)
# イベントID: 6416 (Security - 新しい外部デバイス認識)
python3 << 'PYEOF'
import json
from evtx import PyEvtxParser
try:
parser = PyEvtxParser("/cases/case-2024-001/usb/System.evtx")
print("\n=== システムイベントログ USBイベント ===\n")
for record in parser.records_json():
data = json.loads(record['data'])
event_id = str(data['Event']['System']['EventID'])
# USBデバイス接続イベント
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}] イベントID {event_id}: {json.dumps(event_data, default=str)[:200]}")
except Exception as e:
print(f"エラー: {e}")
PYEOF
手順5: USBアクティビティタイムラインとレポートの作成
# すべてのUSB証拠を統合タイムラインにまとめる
python3 << 'PYEOF'
import json, csv
timeline = []
# USBSTORデータを読み込み
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 レジストリ',
'device': f"{device['vendor']} {device['product']}",
'serial': device['serial'],
'event': '最終接続',
'detail': device.get('friendly_name', '')
})
# 時系列順にソート
timeline.sort(key=lambda x: x['timestamp'])
# タイムライン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タイムライン: {len(timeline)} イベントをusb_timeline.csvに書き込みました")
# サマリーを表示
print("\n=== USBデバイスサマリー ===")
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 | NirSoft製ツール。システムに接続されたすべてのUSBデバイスを一覧表示 |
| 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デバイス履歴分析:
システム: DESKTOP-ABC123 (Windows 10 Pro)
USBストレージデバイス総数: 12
分析ソース: USBSTOR、MountedDevices、MountPoints2、SetupAPI、イベントログ
デバイス一覧:
1. Kingston DataTraveler 3.0 (シリアル: 0019E06B4521A2B0)
初回接続: 2024-01-10 09:15:32 (SetupAPI)
最終接続: 2024-01-18 14:30:00 (USBSTOR)
ドライブレター: E:
ユーザーアクセス: suspect_user (MountPoints2)
2. WD My Passport (シリアル: 575834314131363035)
初回接続: 2024-01-15 20:00:00
最終接続: 2024-01-15 23:45:00
ドライブレター: F:
ユーザーアクセス: suspect_user
不審な発見:
- Kingstonドライブが調査期間中に15回接続
- WD Passportは1回のみ接続、深夜帯(異常な時間帯)
- 不明なデバイス (VID_1234&PID_5678) が2024-01-17に接続、承認済みデバイスに該当なし
タイムライン: /cases/case-2024-001/analysis/usb_timeline.csv