分析USB裝置連線歷史記錄 是做什麼的?
使用時機
- 調查透過可移除儲存裝置進行的潛在資料外洩
- 內部威脅調查中追蹤USB裝置使用情況
- 進行合規性稽核,驗證可移除媒體政策是否落實
- 關聯USB連線與檔案存取及複製事件
- 在事件調查期間建立裝置連線時間線
先決條件
- 鑑識映像或提取的登錄Hive及事件日誌
- 存取SYSTEM、SOFTWARE及NTUSER.DAT登錄Hive的權限
- SetupAPI日誌 (setupapi.dev.log)
- Windows事件日誌 (系統、安全性、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/
# 登錄Hive
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 Hive中提取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_廠商&Prod_產品&Rev_版本
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),
}
# 取得易記名稱(如果有的話)
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 Hive解析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"使用者Hive: {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 (安全性 - 新外部裝置被識別)
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 | 供應商ID與產品ID,唯一識別USB裝置製造商與型號 |
| 裝置序號 | 個別USB裝置的唯一識別碼(部分裝置共享序號) |
| MountedDevices | 將磁碟區GUID和磁碟機代號對應至實體裝置的登錄機碼 |
| MountPoints2 | 每個使用者的登錄機碼,顯示該使用者存取過哪些磁碟區 |
| SetupAPI日誌 | Windows驅動程式安裝日誌,記錄裝置的首次連線時間 |
| DeviceContainers | SOFTWARE Hive中的登錄機碼,包含裝置中繼資料與時間戳 |
| EMDMgmt | 記錄ReadyBoost相容裝置(含序號與時間戳)的登錄機碼 |
工具與系統
| 工具 | 用途 |
|---|---|
| USB Forensic Tracker | 專門用於提取USB裝置歷史記錄的工具 |
| USBDeview | NirSoft工具,列出系統中所有已連線的USB裝置 |
| RegRipper (usbstor 插件) | 從登錄Hive自動提取USB鑑識物 |
| Registry Explorer | 互動式登錄分析,用於USB相關機碼 |
| KAPE | 自動化收集USB相關鑑識物 |
| Plaso/log2timeline | 建立時間線,包含USB連線事件 |
| FTK Imager | 鑑識映像,包括可移除媒體 |
| Velociraptor | 端點代理,具USB裝置歷史記錄狩獵鑑識物 |
常見情境
情境1:離職員工資料外洩 提取USBSTOR項目以識別所有曾連線的USB裝置,將裝置序號與MountPoints2關聯以確認使用者存取,將時間戳與檔案存取日誌及Jump List近期檔案交叉比對,檢查USN日誌中的大量檔案複製模式。
情境2:安全系統上的未授權裝置 審查所有USBSTOR項目,與已核准裝置清單比對,透過VID/PID識別不符合公司核准硬體的未授權裝置,判斷未授權裝置首次與最後連線時間,檢查是否有任何資料被傳輸。
情境3:透過USB傳遞惡意軟體 識別在惡意軟體執行(Prefetch時間戳)之前連線的USB裝置,提取裝置序號與供應商資訊,檢查該裝置是否啟用了自動執行,在Prefetch與ShimCache中尋找從可移除磁碟機代號啟動的可執行檔。
情境4:跨多個系統追蹤特定USB隨身碟 在所有鑑識映像中搜尋相同的裝置序號,建立該隨身碟連線過哪些系統以及連線時間的對應圖,識別裝置在組織中的時間順序路徑,與網路共用存取日誌交叉比對。
輸出格式
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僅連線一次,且在深夜(非正常時段)
- 未知裝置 (VID_1234&PID_5678) 於2024-01-17連線,無對應的核准裝置
時間線:/cases/case-2024-001/analysis/usb_timeline.csv