Skip to content

Commit 2edb41f

Browse files
Add USB history extraction script to log connected devices
Signed-off-by: Shahm Najeeb <[email protected]>
1 parent bdc668a commit 2edb41f

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

CODE/usb_history.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import ctypes
2+
import os
3+
import winreg
4+
from datetime import datetime, timedelta
5+
6+
from logicytics import log
7+
8+
9+
class USBHistory:
10+
def __init__(self):
11+
self.history_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "usb_history.txt")
12+
13+
def _save_history(self, message: str):
14+
"""Append a timestamped message to the history file and log it."""
15+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
16+
entry = f"{timestamp} - {message}\n"
17+
try:
18+
with open(self.history_path, "a", encoding="utf-8") as f:
19+
f.write(entry)
20+
log.debug(f"Saved entry: {message}")
21+
except Exception as e:
22+
log.error(f"Failed to write history: {e}")
23+
24+
# noinspection PyUnresolvedReferences
25+
@staticmethod
26+
def _get_last_write_time(root_key, sub_key_path):
27+
"""Return the precise last write time of a registry key, or None on failure."""
28+
try:
29+
handle = ctypes.wintypes.HANDLE()
30+
if ctypes.windll.advapi32.RegOpenKeyExW(root_key, sub_key_path, 0, winreg.KEY_READ,
31+
ctypes.byref(handle)) != 0:
32+
return None
33+
34+
ft = ctypes.wintypes.FILETIME()
35+
if ctypes.windll.advapi32.RegQueryInfoKeyW(handle, None, None, None, None, None, None, None, None, None,
36+
None, ctypes.byref(ft)) != 0:
37+
return None
38+
39+
t = ((ft.dwHighDateTime << 32) + ft.dwLowDateTime) // 10
40+
return datetime(1601, 1, 1) + timedelta(microseconds=t)
41+
except Exception:
42+
return None
43+
44+
@staticmethod
45+
def _enum_subkeys(root, path, warn_func):
46+
"""Yield all subkeys of a registry key, logging warnings on errors."""
47+
try:
48+
with winreg.OpenKey(root, path) as key:
49+
for i in range(1024): # reasonable upper bound to avoid infinite loops
50+
try:
51+
yield winreg.EnumKey(key, i)
52+
except OSError as e:
53+
if e.winerror == 259: # no more data
54+
break
55+
warn_func(f"Error enumerating {path} index {i}: {e}")
56+
except Exception as e:
57+
warn_func(f"Failed to open registry key {path}: {e}")
58+
59+
@staticmethod
60+
def _get_friendly_name(dev_info_path, device_id):
61+
"""Return the friendly name of a device if available, else the device ID."""
62+
try:
63+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, dev_info_path) as dev_key:
64+
return winreg.QueryValueEx(dev_key, "FriendlyName")[0]
65+
except FileNotFoundError:
66+
return device_id
67+
except Exception as e:
68+
log.warning(f"Failed to read friendly name for {dev_info_path}: {e}")
69+
return device_id
70+
71+
def read(self):
72+
"""Read all USB devices from USBSTOR and log their info."""
73+
log.info("Starting USB history extraction...")
74+
reg_path = r"SYSTEM\CurrentControlSet\Enum\USBSTOR"
75+
try:
76+
for device_class in self._enum_subkeys(winreg.HKEY_LOCAL_MACHINE, reg_path, log.warning):
77+
dev_class_path = f"{reg_path}\\{device_class}"
78+
for device_id in self._enum_subkeys(winreg.HKEY_LOCAL_MACHINE, dev_class_path, log.warning):
79+
dev_info_path = f"{dev_class_path}\\{device_id}"
80+
friendly_name = self._get_friendly_name(dev_info_path, device_id)
81+
last_write = self._get_last_write_time(winreg.HKEY_LOCAL_MACHINE, dev_info_path) or "Unknown"
82+
self._save_history(f"USB Device Found: {friendly_name} | LastWriteTime: {last_write}")
83+
log.info(f"USB history extraction complete, saved to {self.history_path}")
84+
except Exception as e:
85+
log.error(f"Error during USB history extraction: {e}")
86+
87+
88+
if __name__ == "__main__":
89+
USBHistory().read()

PLANS.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
| Task | Version | Might or Will be done? |
1010
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|------------------------|
1111
| Remake VulnScan .pkl and .pth to be more accurate | v3.6.0 ||
12-
| Advanced USB Device History Tracker | v3.6.0 ||
1312
| Merge `sensitive data miner` with `vulnscan` to be 1 tool | v4.0.0 ||
1413
| Remake Logicytics End-Execution cycle, where files created must go in `temp/` directory, and zipper takes it from there only, simplifying any code logic with this as well | v4.0.0 ||
1514
| Replace Logger.py with Util that contains (tprint), also implement the ExceptionHandler and UpdateManager from Util | v4.0.0 ||

0 commit comments

Comments
 (0)