mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-13 06:34:57 +03:00
c47eed6a64
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
183 lines
6.4 KiB
Python
183 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Agent for analyzing USB device connection history from Windows registry hives."""
|
|
|
|
import os
|
|
import json
|
|
import argparse
|
|
import csv
|
|
|
|
from regipy.registry import RegistryHive
|
|
|
|
|
|
def parse_usbstor(system_hive_path):
|
|
"""Parse USBSTOR registry key to enumerate USB storage devices."""
|
|
reg = RegistryHive(system_hive_path)
|
|
select_key = reg.get_key("Select")
|
|
current = select_key.get_value("Current")
|
|
controlset = f"ControlSet{current:03d}"
|
|
usbstor_path = f"{controlset}\\Enum\\USBSTOR"
|
|
devices = []
|
|
try:
|
|
usbstor_key = reg.get_key(usbstor_path)
|
|
except Exception:
|
|
return devices
|
|
for device_class in usbstor_key.iter_subkeys():
|
|
parts = device_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.iter_subkeys():
|
|
serial = instance.name
|
|
device_info = {
|
|
"vendor": vendor,
|
|
"product": product,
|
|
"revision": revision,
|
|
"serial": serial,
|
|
"last_connected": str(instance.header.last_modified),
|
|
}
|
|
for val in instance.iter_values():
|
|
if val.name == "FriendlyName":
|
|
device_info["friendly_name"] = val.value
|
|
devices.append(device_info)
|
|
return devices
|
|
|
|
|
|
def parse_mounted_devices(system_hive_path):
|
|
"""Parse MountedDevices to map drive letters to USB devices."""
|
|
reg = RegistryHive(system_hive_path)
|
|
mounted_key = reg.get_key("MountedDevices")
|
|
mappings = []
|
|
for val in mounted_key.iter_values():
|
|
if val.name.startswith("\\DosDevices\\"):
|
|
drive_letter = val.name.replace("\\DosDevices\\", "")
|
|
data = val.value
|
|
if isinstance(data, bytes) and len(data) > 24:
|
|
try:
|
|
device_path = data.decode("utf-16-le").strip("\x00")
|
|
if "USBSTOR" in device_path or "USB#" in device_path:
|
|
mappings.append({
|
|
"drive_letter": drive_letter,
|
|
"device_path": device_path,
|
|
})
|
|
except (UnicodeDecodeError, ValueError):
|
|
pass
|
|
return mappings
|
|
|
|
|
|
def parse_mountpoints2(ntuser_path):
|
|
"""Parse MountPoints2 from NTUSER.DAT to find user-accessed volumes."""
|
|
reg = RegistryHive(ntuser_path)
|
|
mp2_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MountPoints2"
|
|
mount_points = []
|
|
try:
|
|
mp2_key = reg.get_key(mp2_path)
|
|
except Exception:
|
|
return mount_points
|
|
for subkey in mp2_key.iter_subkeys():
|
|
if "{" in subkey.name:
|
|
mount_points.append({
|
|
"volume_guid": subkey.name,
|
|
"last_accessed": str(subkey.header.last_modified),
|
|
})
|
|
return mount_points
|
|
|
|
|
|
def parse_setupapi_log(log_path):
|
|
"""Parse setupapi.dev.log for USB first-install timestamps."""
|
|
import re
|
|
installs = []
|
|
with open(log_path, "r", errors="ignore") as f:
|
|
content = f.read()
|
|
pattern = r">>>\s+\[Device Install.*?\n.*?Section start (\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}).*?\n(.*?)<<<"
|
|
for match in re.finditer(pattern, content, re.DOTALL):
|
|
timestamp, section = match.group(1), match.group(2)
|
|
dev_match = re.search(r"(USBSTOR\\[^\s]+|USB\\VID_\w+&PID_\w+[^\s]*)", section)
|
|
if dev_match:
|
|
installs.append({
|
|
"first_install": timestamp,
|
|
"device_id": dev_match.group(1),
|
|
})
|
|
return installs
|
|
|
|
|
|
def build_timeline(devices, mappings, mount_points):
|
|
"""Build a unified USB activity timeline."""
|
|
timeline = []
|
|
for dev in devices:
|
|
timeline.append({
|
|
"timestamp": dev["last_connected"],
|
|
"source": "USBSTOR",
|
|
"device": f"{dev['vendor']} {dev['product']}",
|
|
"serial": dev["serial"],
|
|
"event": "Last Connected",
|
|
"detail": dev.get("friendly_name", ""),
|
|
})
|
|
for mp in mount_points:
|
|
timeline.append({
|
|
"timestamp": mp["last_accessed"],
|
|
"source": "MountPoints2",
|
|
"device": mp["volume_guid"],
|
|
"serial": "",
|
|
"event": "Volume Accessed",
|
|
"detail": "",
|
|
})
|
|
timeline.sort(key=lambda x: x["timestamp"])
|
|
return timeline
|
|
|
|
|
|
def export_timeline_csv(timeline, output_path):
|
|
"""Export timeline to CSV."""
|
|
if not timeline:
|
|
return
|
|
with open(output_path, "w", newline="") as f:
|
|
writer = csv.DictWriter(f, fieldnames=timeline[0].keys())
|
|
writer.writeheader()
|
|
writer.writerows(timeline)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="USB Device Connection History Agent")
|
|
parser.add_argument("--system-hive", required=True, help="Path to SYSTEM registry hive")
|
|
parser.add_argument("--ntuser", help="Path to NTUSER.DAT hive")
|
|
parser.add_argument("--setupapi-log", help="Path to setupapi.dev.log")
|
|
parser.add_argument("--output-dir", default="./usb_analysis")
|
|
parser.add_argument("--case-id", default="CASE-001")
|
|
args = parser.parse_args()
|
|
|
|
os.makedirs(args.output_dir, exist_ok=True)
|
|
|
|
devices = parse_usbstor(args.system_hive)
|
|
print(f"[+] USBSTOR devices: {len(devices)}")
|
|
for d in devices:
|
|
print(f" {d['vendor']} {d['product']} | Serial: {d['serial']}")
|
|
|
|
mappings = parse_mounted_devices(args.system_hive)
|
|
print(f"[+] USB drive mappings: {len(mappings)}")
|
|
|
|
mount_points = []
|
|
if args.ntuser:
|
|
mount_points = parse_mountpoints2(args.ntuser)
|
|
print(f"[+] MountPoints2 entries: {len(mount_points)}")
|
|
|
|
if args.setupapi_log:
|
|
installs = parse_setupapi_log(args.setupapi_log)
|
|
print(f"[+] SetupAPI installations: {len(installs)}")
|
|
|
|
timeline = build_timeline(devices, mappings, mount_points)
|
|
csv_path = os.path.join(args.output_dir, "usb_timeline.csv")
|
|
export_timeline_csv(timeline, csv_path)
|
|
print(f"[+] Timeline exported to {csv_path} ({len(timeline)} events)")
|
|
|
|
report = {
|
|
"case_id": args.case_id,
|
|
"total_devices": len(devices),
|
|
"devices": devices,
|
|
"drive_mappings": mappings,
|
|
"timeline_events": len(timeline),
|
|
}
|
|
print(json.dumps(report, indent=2, default=str))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|