-
-
Notifications
You must be signed in to change notification settings - Fork 3
v3.6.0 Update features #235
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
3ef1c03
Quick document changes to get ready for v3.6.0
DefinetlyNotAI bdc668a
Add encrypted drive audit script for volume analysis and BitLocker st…
DefinetlyNotAI 2edb41f
Add USB history extraction script to log connected devices
DefinetlyNotAI 1e88262
Refactor vulnscan.py to enhance file processing and backup functional…
DefinetlyNotAI 69e9391
Refactor vulnscan.py for improved file processing and logging; update…
DefinetlyNotAI b431a08
Update vulnscan.py to define sensitive paths for scanning; refactor m…
DefinetlyNotAI c6890a9
Remove unnecessary browser data paths from sensitive paths in vulnsca…
DefinetlyNotAI d9d1572
Update config.ini to version 3.6.0 and include new usb_history.py script
DefinetlyNotAI c621162
Update CODE/vulnscan.py
DefinetlyNotAI bdc9196
PR suggestion commit incorporation
DefinetlyNotAI bf9cf3f
Update TODO
DefinetlyNotAI File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| import datetime | ||
| import getpass | ||
| import os | ||
| import platform | ||
| import shutil | ||
| import subprocess | ||
| from pathlib import Path | ||
|
|
||
| from logicytics import check, log | ||
|
|
||
|
|
||
| def now_iso(): | ||
| return datetime.datetime.now().astimezone().isoformat() | ||
|
|
||
|
|
||
| def run_cmd(cmd): | ||
| log.debug(f"Running command: {cmd}") | ||
| try: | ||
| proc = subprocess.run(cmd, capture_output=True, text=True, timeout=30) | ||
DefinetlyNotAI marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if proc.returncode == 0: | ||
| log.debug(f"Command succeeded: {cmd}") | ||
| else: | ||
| log.warning(f"Command returned {proc.returncode}: {cmd}") | ||
| return proc.stdout.strip(), proc.stderr.strip(), proc.returncode | ||
| except FileNotFoundError: | ||
| log.error(f"Command not found: {cmd[0]}") | ||
| return "", "not found", 127 | ||
| except subprocess.TimeoutExpired: | ||
| log.error(f"Command timed out: {cmd}") | ||
| return "", "timeout", 124 | ||
|
|
||
|
|
||
| def have(cmd_name): | ||
| exists = shutil.which(cmd_name) is not None | ||
| log.debug(f"Check if '{cmd_name}' exists: {exists}") | ||
| return exists | ||
|
|
||
|
|
||
| def get_mountvol_output(): | ||
| log.info("Gathering mounted volumes via mountvol") | ||
| out, err, _ = run_cmd(["mountvol"]) | ||
| if not out: | ||
| return err | ||
| lines = out.splitlines() | ||
| filtered = [] | ||
| keep = False | ||
| for line in lines: | ||
| if line.strip().startswith("\\\\?\\Volume"): | ||
| keep = True | ||
| if keep: | ||
| filtered.append(line) | ||
| return "\n".join(filtered) | ||
|
|
||
|
|
||
| def main(): | ||
| script_dir = Path(__file__).resolve().parent | ||
| report_path = script_dir / "win_encrypted_volume_report.txt" | ||
| log.info(f"Starting encrypted volume analysis, report will be saved to {report_path}") | ||
|
|
||
| with report_path.open("w", encoding="utf-8") as f: | ||
| f.write("=" * 80 + "\n") | ||
| f.write("Windows Encrypted Volume Report\n") | ||
| f.write("=" * 80 + "\n") | ||
| f.write(f"Generated at: {now_iso()}\n") | ||
| f.write(f"User: {getpass.getuser()}\n") | ||
| f.write(f"IsAdmin: {check.admin()}\n") | ||
| f.write(f"Hostname: {platform.node()}\n") | ||
| f.write(f"Version: {platform.platform()}\n\n") | ||
|
|
||
| # Logical drives | ||
| log.info("Gathering logical volumes via wmic") | ||
| f.write("Logical Volumes (wmic):\n") | ||
| out, err, _ = run_cmd(["wmic", "logicaldisk", "get", | ||
| "DeviceID,DriveType,FileSystem,FreeSpace,Size,VolumeName"]) | ||
| f.write(out + "\n" + err + "\n\n") | ||
|
|
||
| # Mounted volumes | ||
| f.write("Mounted Volumes (mountvol):\n") | ||
| f.write(get_mountvol_output() + "\n\n") | ||
|
|
||
| # BitLocker status | ||
| f.write("=" * 80 + "\nBitLocker Status\n" + "=" * 80 + "\n") | ||
| if have("manage-bde"): | ||
| log.info("Checking BitLocker status with manage-bde") | ||
| for letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": | ||
| path = f"{letter}:" | ||
| if os.path.exists(f"{path}\\"): | ||
| out, err, _ = run_cmd(["manage-bde", "-status", path]) | ||
| f.write(f"Drive {path}:\n{out}\n{err}\n\n") | ||
| else: | ||
| log.warning("manage-bde not found") | ||
|
|
||
| if have("powershell"): | ||
| log.info("Checking BitLocker status with PowerShell") | ||
| f.write("PowerShell Get-BitLockerVolume:\n") | ||
| ps_cmd = r"Get-BitLockerVolume | Format-List *" | ||
| out, err, _ = run_cmd(["powershell", "-NoProfile", "-Command", ps_cmd]) | ||
| f.write(out + "\n" + err + "\n\n") | ||
| else: | ||
| log.warning("PowerShell not available") | ||
|
|
||
| log.info(f"Report successfully saved to {report_path}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -122,4 +122,5 @@ def wrapper(*args, **kwargs) -> callable: | |
| "ObjectLoadError", | ||
| "log", | ||
| "Log", | ||
| "config", | ||
| ] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| import ctypes | ||
| import os | ||
| import winreg | ||
| from datetime import datetime, timedelta | ||
DefinetlyNotAI marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| from logicytics import log | ||
|
|
||
|
|
||
| class USBHistory: | ||
| def __init__(self): | ||
| self.history_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "usb_history.txt") | ||
|
|
||
| def _save_history(self, message: str): | ||
| """Append a timestamped message to the history file and log it.""" | ||
| timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | ||
| entry = f"{timestamp} - {message}\n" | ||
| try: | ||
| with open(self.history_path, "a", encoding="utf-8") as f: | ||
| f.write(entry) | ||
| log.debug(f"Saved entry: {message}") | ||
| except Exception as e: | ||
| log.error(f"Failed to write history: {e}") | ||
|
|
||
| # noinspection PyUnresolvedReferences | ||
| @staticmethod | ||
| def _get_last_write_time(root_key, sub_key_path): | ||
| """Return the precise last write time of a registry key, or None on failure.""" | ||
| handle = ctypes.wintypes.HANDLE() | ||
| try: | ||
| advapi32 = ctypes.windll.advapi32 | ||
| if advapi32.RegOpenKeyExW(root_key, sub_key_path, 0, winreg.KEY_READ, ctypes.byref(handle)) != 0: | ||
| return None | ||
| ft = ctypes.wintypes.FILETIME() | ||
| if advapi32.RegQueryInfoKeyW(handle, None, None, None, None, None, None, None, None, None, None, | ||
| ctypes.byref(ft)) != 0: | ||
| return None | ||
| t = ((ft.dwHighDateTime << 32) + ft.dwLowDateTime) // 10 | ||
| return datetime(1601, 1, 1) + timedelta(microseconds=t) | ||
| finally: | ||
| if handle: | ||
| ctypes.windll.advapi32.RegCloseKey(handle) | ||
|
|
||
| @staticmethod | ||
| def _enum_subkeys(root, path, warn_func): | ||
| """Yield all subkeys of a registry key, logging warnings on errors.""" | ||
| try: | ||
| with winreg.OpenKey(root, path) as key: | ||
| subkey_count, _, _ = winreg.QueryInfoKey(key) | ||
| for i in range(subkey_count): | ||
| try: | ||
| yield winreg.EnumKey(key, i) | ||
| except OSError as e: | ||
| if getattr(e, "winerror", None) == 259: # ERROR_NO_MORE_ITEMS | ||
| break | ||
| warn_func(f"Error enumerating {path} index {i}: {e}") | ||
| except OSError as e: | ||
| warn_func(f"Failed to open registry key {path}: {e}") | ||
|
|
||
| @staticmethod | ||
| def _get_friendly_name(dev_info_path, device_id): | ||
| """Return the friendly name of a device if available, else the device ID.""" | ||
| try: | ||
| with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, dev_info_path) as dev_key: | ||
| return winreg.QueryValueEx(dev_key, "FriendlyName")[0] | ||
| except FileNotFoundError: | ||
| return device_id | ||
| except Exception as e: | ||
| log.warning(f"Failed to read friendly name for {dev_info_path}: {e}") | ||
| return device_id | ||
|
|
||
| def read(self): | ||
| """Read all USB devices from USBSTOR and log their info.""" | ||
| log.info("Starting USB history extraction...") | ||
| reg_path = r"SYSTEM\CurrentControlSet\Enum\USBSTOR" | ||
| try: | ||
| for device_class in self._enum_subkeys(winreg.HKEY_LOCAL_MACHINE, reg_path, log.warning): | ||
| dev_class_path = f"{reg_path}\\{device_class}" | ||
| for device_id in self._enum_subkeys(winreg.HKEY_LOCAL_MACHINE, dev_class_path, log.warning): | ||
| dev_info_path = f"{dev_class_path}\\{device_id}" | ||
| friendly_name = self._get_friendly_name(dev_info_path, device_id) | ||
| last_write = self._get_last_write_time(winreg.HKEY_LOCAL_MACHINE, dev_info_path) or "Unknown" | ||
| self._save_history(f"USB Device Found: {friendly_name} | LastWriteTime: {last_write}") | ||
| log.info(f"USB history extraction complete, saved to {self.history_path}") | ||
| except Exception as e: | ||
| log.error(f"Error during USB history extraction: {e}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| USBHistory().read() | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.