From 878d19f9173282d0075db3803e8f8be64a5ac84c Mon Sep 17 00:00:00 2001 From: mnerv <24420859+mnerv@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:31:39 +0100 Subject: [PATCH] Add Windows forensic artifact collection toolkit Add PowerShell scripts for collecting forensic artifacts: - USB/storage devices, mounted drives, portable devices - Network history and hotspot connections - Recent documents (OpenSavePidlMRU with PIDL parsing) - System info and user enumeration with multiple output modes Includes TODO.md for planned artifacts and updated README. --- TODO.md | 67 +++++++++++ windows/Get-HotspotConnections.ps1 | 113 +++++++++++++++++++ windows/Get-Info.ps1 | 127 +++++++++++++++++++++ windows/Get-MountedDevices.ps1 | 16 +++ windows/Get-NetworkHistory.ps1 | 37 ++++++ windows/Get-PortableDevices.ps1 | 23 ++++ windows/Get-RecentDocs.ps1 | 141 +++++++++++++++++++++++ windows/Get-USBDevices.ps1 | 36 ++++++ windows/Get-USBForensics.ps1 | 135 ++++++++++++++++++++++ windows/Get-USBStorage.ps1 | 26 +++++ windows/Get-Users.ps1 | 174 +++++++++++++++++++++++++++++ 11 files changed, 895 insertions(+) create mode 100644 TODO.md create mode 100644 windows/Get-HotspotConnections.ps1 create mode 100644 windows/Get-Info.ps1 create mode 100644 windows/Get-MountedDevices.ps1 create mode 100644 windows/Get-NetworkHistory.ps1 create mode 100644 windows/Get-PortableDevices.ps1 create mode 100644 windows/Get-RecentDocs.ps1 create mode 100644 windows/Get-USBDevices.ps1 create mode 100644 windows/Get-USBForensics.ps1 create mode 100644 windows/Get-USBStorage.ps1 create mode 100644 windows/Get-Users.ps1 diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..877855a --- /dev/null +++ b/TODO.md @@ -0,0 +1,67 @@ +# Forensic Artifacts TODO + +## Windows Forensic Scripts + +### Completed +- [x] USB Storage (USBSTOR) +- [x] Mounted Devices +- [x] USB Devices (VID/PID) +- [x] Portable Devices +- [x] Network Connection History +- [x] Hotspot Connections +- [x] Recent Documents (RecentDocs) + +### User Activity Artifacts +- [ ] UserAssist - Programs run by user through Windows Explorer +- [ ] ShimCache (AppCompatCache) - Executable files that have been run +- [ ] AmCache - Program execution with file hashes and timestamps +- [ ] Jump Lists - Recently accessed files per application +- [ ] Prefetch files - Program execution history with run counts +- [ ] BAM/DAM - Background Activity Moderator (program execution timestamps) + +### Browser & Search History +- [ ] Browser history - Edge, Chrome, Firefox artifacts +- [ ] Typed URLs - URLs manually typed in browsers +- [ ] Search terms - Windows Search history + +### File Access +- [ ] LNK files - Shortcut files showing file access +- [ ] Recycle Bin - Deleted files +- [ ] Shell Bags - Folder access history + +### System Information +- [ ] Computer name - System identification +- [ ] Timezone - System timezone settings +- [ ] Last shutdown time +- [ ] Installed programs - Software inventory +- [ ] System uptime history + +### Persistence Mechanisms +- [ ] Run/RunOnce keys - Programs that auto-start +- [ ] Scheduled tasks +- [ ] Services +- [ ] Startup folder contents + +### Network Artifacts +- [ ] DNS Cache +- [ ] Network shares accessed +- [ ] VPN connections +- [ ] Remote Desktop connections + +## Other Operating Systems + +### Linux +- [ ] User login history +- [ ] Command history (bash, zsh) +- [ ] Systemd journal logs +- [ ] Package installation history +- [ ] Cron jobs +- [ ] SSH keys and known hosts + +### macOS +- [ ] Unified logs (log show) +- [ ] LaunchAgents/LaunchDaemons +- [ ] Spotlight metadata +- [ ] FSEvents (file system events) +- [ ] Login/logout history +- [ ] Keychain artifacts diff --git a/windows/Get-HotspotConnections.ps1 b/windows/Get-HotspotConnections.ps1 new file mode 100644 index 0000000..f9b1676 --- /dev/null +++ b/windows/Get-HotspotConnections.ps1 @@ -0,0 +1,113 @@ +# Get-HotspotConnections.ps1 +# Collects Windows Mobile Hotspot connection artifacts + +# Check for admin privileges +$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + +if (-not $isAdmin) { + Write-Host "Error: This script requires Administrator privileges" -ForegroundColor Red + Write-Host "Please run PowerShell as Administrator and try again" -ForegroundColor Yellow + exit 1 +} + +Write-Host "=== Windows Mobile Hotspot Connection History ===" -ForegroundColor Cyan +Write-Host "Note: Windows does not maintain persistent logs of past hotspot clients" +Write-Host "Only event logs and currently connected devices can be retrieved`n" + +# Get current hotspot status +Write-Host "--- Current Hotspot Status ---" -ForegroundColor Yellow +try { + $hostedNetwork = netsh wlan show hostednetwork 2>$null + if ($hostedNetwork) { + $hostedNetwork | Write-Host + } +} catch { + Write-Host "Error getting hosted network status" -ForegroundColor Red +} + +# Get currently connected clients via ARP +Write-Host "`n--- Currently Connected Devices (ARP Cache) ---" -ForegroundColor Yellow +try { + $arp = Get-NetNeighbor -AddressFamily IPv4 -ErrorAction SilentlyContinue | + Where-Object { $_.State -ne "Unreachable" -and $_.IPAddress -notmatch "^(224\.|239\.)" } + + if ($arp) { + $arp | Select-Object IPAddress, LinkLayerAddress, State | Format-Table -AutoSize + } else { + Write-Host "No connected devices found in ARP cache" -ForegroundColor Gray + } +} catch { + Write-Host "Error accessing ARP cache: $_" -ForegroundColor Red +} + +# Extract hotspot connection events from WLAN-AutoConfig log +Write-Host "`n--- Recent Hotspot Connection Events ---" -ForegroundColor Yellow +try { + # Event ID 20019 = Client connection to hotspot + # Event ID 20020 = Connection establishment confirmation + # Event ID 8005/8006 = Hotspot start/stop + $events = Get-WinEvent -FilterHashtable @{ + LogName = "Microsoft-Windows-WLAN-AutoConfig/Operational" + ID = 8005, 8006, 20019, 20020 + } -MaxEvents 50 -ErrorAction SilentlyContinue + + if ($events) { + foreach ($event in $events) { + Write-Host "$($event.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Cyan -NoNewline + Write-Host " [ID:$($event.Id)]" -ForegroundColor Gray -NoNewline + + # Extract relevant info from message + $msg = $event.Message + if ($msg -match "MAC Address: ([0-9A-Fa-f:-]+)") { + Write-Host " MAC: $($matches[1])" -ForegroundColor Yellow + } elseif ($msg -match "SSID: (.+)") { + Write-Host " SSID: $($matches[1])" -ForegroundColor Green + } else { + Write-Host "" + } + } + } else { + Write-Host "No hotspot events found in logs" -ForegroundColor Gray + } +} catch { + Write-Host "Error accessing event logs: $_" -ForegroundColor Red +} + +# Get wireless authentication events (Event ID 5632) +Write-Host "`n--- Wireless Authentication Events (Last 20) ---" -ForegroundColor Yellow +try { + $authEvents = Get-WinEvent -FilterHashtable @{ + LogName = "Security" + ID = 5632 + } -MaxEvents 20 -ErrorAction SilentlyContinue + + if ($authEvents) { + foreach ($authEvent in $authEvents) { + Write-Host "$($authEvent.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Cyan + if ($authEvent.Message -match "Peer MAC Address:\s+([0-9A-Fa-f:-]+)") { + Write-Host " Peer MAC: $($matches[1])" -ForegroundColor Yellow + } + } + } else { + Write-Host "No wireless authentication events found" -ForegroundColor Gray + } +} catch { + Write-Host "Security event log not accessible or no events found" -ForegroundColor Gray +} + +# Get hosted network settings from registry +Write-Host "`n--- Hosted Network Registry Settings ---" -ForegroundColor Yellow +try { + $regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\WlanSvc\Parameters\HostedNetworkSettings" + if (Test-Path $regPath) { + $props = Get-ItemProperty -Path $regPath -ErrorAction SilentlyContinue + if ($props) { + Write-Host "Registry path exists with configuration data" -ForegroundColor Green + Write-Host "(Binary data - use registry editor for details)" + } + } else { + Write-Host "No hosted network settings found in registry" -ForegroundColor Gray + } +} catch { + Write-Host "Error accessing registry: $_" -ForegroundColor Red +} diff --git a/windows/Get-Info.ps1 b/windows/Get-Info.ps1 new file mode 100644 index 0000000..e7e5022 --- /dev/null +++ b/windows/Get-Info.ps1 @@ -0,0 +1,127 @@ +# Get-Info.ps1 +# Displays system and user information + +Write-Host "=== System Information ===" -ForegroundColor Cyan + +# Current User +Write-Host "`n--- Current User ---" -ForegroundColor Yellow +Write-Host "Username: $env:USERNAME" -ForegroundColor Green +Write-Host "Domain: $env:USERDOMAIN" -ForegroundColor Green +Write-Host "User Profile: $env:USERPROFILE" -ForegroundColor Green +Write-Host "Home Drive: $env:HOMEDRIVE" -ForegroundColor Green + +# Computer Info +Write-Host "`n--- Computer Information ---" -ForegroundColor Yellow +Write-Host "Computer Name: $env:COMPUTERNAME" -ForegroundColor Green + +try { + $cs = Get-CimInstance Win32_ComputerSystem + Write-Host "Full Computer Name: $($cs.DNSHostName).$($cs.Domain)" -ForegroundColor Green + Write-Host "Manufacturer: $($cs.Manufacturer)" -ForegroundColor Green + Write-Host "Model: $($cs.Model)" -ForegroundColor Green + Write-Host "Total RAM: $([math]::Round($cs.TotalPhysicalMemory / 1GB, 2)) GB" -ForegroundColor Green +} catch { + Write-Host "Error getting computer details: $_" -ForegroundColor Red +} + +# OS Info +Write-Host "`n--- Operating System ---" -ForegroundColor Yellow +try { + $os = Get-CimInstance Win32_OperatingSystem + Write-Host "OS: $($os.Caption)" -ForegroundColor Green + Write-Host "Version: $($os.Version)" -ForegroundColor Green + Write-Host "Build: $($os.BuildNumber)" -ForegroundColor Green + Write-Host "Architecture: $($os.OSArchitecture)" -ForegroundColor Green + Write-Host "Install Date: $($os.InstallDate)" -ForegroundColor Green + Write-Host "Last Boot: $($os.LastBootUpTime)" -ForegroundColor Green + + $uptime = (Get-Date) - $os.LastBootUpTime + Write-Host "Uptime: $($uptime.Days) days, $($uptime.Hours) hours, $($uptime.Minutes) minutes" -ForegroundColor Green +} catch { + Write-Host "Error getting OS details: $_" -ForegroundColor Red +} + +# Timezone +Write-Host "`n--- Time & Location ---" -ForegroundColor Yellow +try { + $timezone = Get-TimeZone + Write-Host "Timezone: $($timezone.DisplayName)" -ForegroundColor Green + Write-Host "Current Time: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Green +} catch { + Write-Host "Timezone: $env:TZ" -ForegroundColor Green +} + +# Network Info +Write-Host "`n--- Network Configuration ---" -ForegroundColor Yellow +try { + $adapters = Get-NetAdapter | Where-Object { $_.Status -eq "Up" } + foreach ($adapter in $adapters) { + Write-Host "Adapter: $($adapter.Name)" -ForegroundColor Green + Write-Host " MAC Address: $($adapter.MacAddress)" -ForegroundColor Cyan + Write-Host " Speed: $($adapter.LinkSpeed)" -ForegroundColor Cyan + + # Get IP addresses + $ipConfig = Get-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -ErrorAction SilentlyContinue + foreach ($ip in $ipConfig) { + if ($ip.AddressFamily -eq "IPv4") { + Write-Host " IPv4: $($ip.IPAddress)" -ForegroundColor Cyan + } elseif ($ip.AddressFamily -eq "IPv6" -and $ip.PrefixOrigin -ne "WellKnown") { + Write-Host " IPv6: $($ip.IPAddress)" -ForegroundColor Cyan + } + } + } +} catch { + Write-Host "Error getting network info: $_" -ForegroundColor Red +} + +# Disk Info +Write-Host "`n--- Disk Drives ---" -ForegroundColor Yellow +try { + $disks = Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Used -ne $null } + foreach ($disk in $disks) { + $usedGB = [math]::Round($disk.Used / 1GB, 2) + $freeGB = [math]::Round($disk.Free / 1GB, 2) + $totalGB = $usedGB + $freeGB + $percentUsed = [math]::Round(($usedGB / $totalGB) * 100, 1) + + Write-Host "$($disk.Name):\ - Total: $totalGB GB, Used: $usedGB GB ($percentUsed%), Free: $freeGB GB" -ForegroundColor Green + } +} catch { + Write-Host "Error getting disk info: $_" -ForegroundColor Red +} + +# User Accounts on System +Write-Host "`n--- Local User Accounts ---" -ForegroundColor Yellow +try { + $users = Get-LocalUser | Select-Object Name, Enabled, LastLogon + foreach ($user in $users) { + $status = if ($user.Enabled) { "Enabled" } else { "Disabled" } + $lastLogon = if ($user.LastLogon) { $user.LastLogon.ToString("yyyy-MM-dd HH:mm:ss") } else { "Never" } + Write-Host "$($user.Name) - $status - Last Logon: $lastLogon" -ForegroundColor Green + } +} catch { + Write-Host "Error getting user accounts: $_" -ForegroundColor Red +} + +# Environment Variables (useful ones) +Write-Host "`n--- Key Environment Variables ---" -ForegroundColor Yellow +Write-Host "Temp: $env:TEMP" -ForegroundColor Green +Write-Host "Path (first 3): $((($env:PATH -split ';') | Select-Object -First 3) -join '; ')..." -ForegroundColor Green +Write-Host "Processor: $env:PROCESSOR_IDENTIFIER" -ForegroundColor Green +Write-Host "Number of Processors: $env:NUMBER_OF_PROCESSORS" -ForegroundColor Green + +# Windows Product Info +Write-Host "`n--- Windows Product Information ---" -ForegroundColor Yellow +try { + $productName = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name ProductName -ErrorAction SilentlyContinue + $displayVersion = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name DisplayVersion -ErrorAction SilentlyContinue + $editionID = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name EditionID -ErrorAction SilentlyContinue + + if ($productName) { Write-Host "Product: $($productName.ProductName)" -ForegroundColor Green } + if ($displayVersion) { Write-Host "Display Version: $($displayVersion.DisplayVersion)" -ForegroundColor Green } + if ($editionID) { Write-Host "Edition: $($editionID.EditionID)" -ForegroundColor Green } +} catch { + Write-Host "Error getting product info: $_" -ForegroundColor Red +} + +Write-Host "`n=== End of System Information ===" -ForegroundColor Cyan diff --git a/windows/Get-MountedDevices.ps1 b/windows/Get-MountedDevices.ps1 new file mode 100644 index 0000000..13c3a79 --- /dev/null +++ b/windows/Get-MountedDevices.ps1 @@ -0,0 +1,16 @@ +# Get-MountedDevices.ps1 +# Lists mounted devices and drive letter mappings + +Write-Host "=== Mounted Devices ===" -ForegroundColor Cyan +Write-Host "HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices" + +try { + $mounted = Get-ItemProperty -Path "HKLM:\SYSTEM\MountedDevices" -ErrorAction SilentlyContinue + if ($mounted) { + $mounted.PSObject.Properties | Where-Object { $_.Name -notmatch "^PS" } | ForEach-Object { + Write-Host "$($_.Name)" -ForegroundColor Yellow + } + } +} catch { + Write-Host "Error: $_" -ForegroundColor Red +} diff --git a/windows/Get-NetworkHistory.ps1 b/windows/Get-NetworkHistory.ps1 new file mode 100644 index 0000000..199454c --- /dev/null +++ b/windows/Get-NetworkHistory.ps1 @@ -0,0 +1,37 @@ +# Get-NetworkHistory.ps1 +# Lists network connection history + +# Check for admin privileges +$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + +if (-not $isAdmin) { + Write-Host "Error: This script requires Administrator privileges" -ForegroundColor Red + Write-Host "Please run PowerShell as Administrator and try again" -ForegroundColor Yellow + exit 1 +} + +Write-Host "=== Network Connection History ===" -ForegroundColor Cyan +Write-Host "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles" + +try { + $networks = Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles" -ErrorAction SilentlyContinue + if ($networks) { + foreach ($network in $networks) { + $props = Get-ItemProperty -Path $network.PSPath -ErrorAction SilentlyContinue + Write-Host "$($props.ProfileName)" -ForegroundColor Yellow + Write-Host " Description: $($props.Description)" + Write-Host " Category: $($props.Category) (0=Public, 1=Private, 2=Domain)" + if ($props.DateCreated) { + Write-Host " First Connected: $($props.DateCreated)" + } + if ($props.DateLastConnected) { + Write-Host " Last Connected: $($props.DateLastConnected)" + } + Write-Host "" + } + } else { + Write-Host "No network history found." -ForegroundColor Gray + } +} catch { + Write-Host "Error: $_" -ForegroundColor Red +} diff --git a/windows/Get-PortableDevices.ps1 b/windows/Get-PortableDevices.ps1 new file mode 100644 index 0000000..eeb97ab --- /dev/null +++ b/windows/Get-PortableDevices.ps1 @@ -0,0 +1,23 @@ +# Get-PortableDevices.ps1 +# Lists portable devices (phones, cameras, etc.) + +Write-Host "=== Portable Devices ===" -ForegroundColor Cyan +Write-Host "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Portable Devices\Devices" + +try { + $portableDevices = Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows Portable Devices\Devices" -ErrorAction SilentlyContinue + if ($portableDevices) { + foreach ($device in $portableDevices) { + $props = Get-ItemProperty -Path $device.PSPath -ErrorAction SilentlyContinue + if ($props.FriendlyName) { + Write-Host "$($props.FriendlyName)" -ForegroundColor Yellow + Write-Host " $($device.PSChildName)" -ForegroundColor Gray + Write-Host "" + } + } + } else { + Write-Host "No portable devices found." -ForegroundColor Gray + } +} catch { + Write-Host "Error: $_" -ForegroundColor Red +} diff --git a/windows/Get-RecentDocs.ps1 b/windows/Get-RecentDocs.ps1 new file mode 100644 index 0000000..0122de5 --- /dev/null +++ b/windows/Get-RecentDocs.ps1 @@ -0,0 +1,141 @@ +# Get-RecentDocs.ps1 +# Lists recently opened documents from OpenSavePidlMRU registry key + +param( + [int]$MaxPerType = 10, + [switch]$ShowAll +) + +Write-Host "=== Recently Opened Documents ===" -ForegroundColor Cyan +Write-Host "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU" + +if ($ShowAll) { + $MaxPerType = [int]::MaxValue + Write-Host "Showing all entries`n" -ForegroundColor Yellow +} else { + Write-Host "Showing top $MaxPerType per type (use -ShowAll or -MaxPerType N to see more)`n" -ForegroundColor Yellow +} + +function Convert-PidlMRU { + param([byte[]]$data) + + if (-not $data -or $data.Length -lt 10) { + return "" + } + + try { + # Convert to Unicode string + $unicodeText = [System.Text.Encoding]::Unicode.GetString($data) + + # Remove null characters + $cleaned = $unicodeText -replace '\x00', '' + + # Try to extract valid file path (Windows path pattern) + if ($cleaned -match '([A-Z]:\\(?:[^<>:"|?*\x00-\x1F]+\\)*[^<>:"|?*\x00-\x1F\\]+)') { + return $matches[1] + } + + # Extract filename - match only valid filename characters + # This regex looks for a sequence that starts with alphanumeric and includes a file extension + if ($cleaned -match '([a-zA-Z0-9][a-zA-Z0-9._\- ]{0,200}\.[a-zA-Z0-9]{1,10})') { + return $matches[1] + } + + # Fallback: filter to printable ASCII only and look for pattern + $printable = -join ($cleaned.ToCharArray() | Where-Object { + ($_ -ge 32 -and $_ -le 126) + }) + + # Try again with printable string + if ($printable -match '([a-zA-Z0-9][a-zA-Z0-9._\- ]{0,200}\.[a-zA-Z0-9]{1,10})') { + return $matches[1] + } + + return "" + } catch { + return "" + } +} + +try { + $mruPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU" + + if (Test-Path $mruPath) { + # Get all extension subkeys + $subKeys = Get-ChildItem -Path $mruPath -ErrorAction SilentlyContinue | + Sort-Object PSChildName + + if ($subKeys) { + $totalFiles = 0 + $totalStored = 0 + + foreach ($subKey in $subKeys) { + $extension = $subKey.PSChildName + + $props = Get-ItemProperty -Path $subKey.PSPath -ErrorAction SilentlyContinue + + # Get MRUListEx for ordering + if ($props.MRUListEx) { + $files = @() + + for ($i = 0; $i -lt $props.MRUListEx.Length - 4; $i += 4) { + $index = [BitConverter]::ToInt32($props.MRUListEx, $i) + if ($index -eq -1) { break } + + $propName = "$index" + if ($props.$propName) { + $fileName = Convert-PidlMRU -data $props.$propName + if ($fileName) { + $files += $fileName + } + } + } + + $totalStored += $files.Count + + # Only show if we found files + if ($files.Count -gt 0) { + if ($extension -eq "*") { + Write-Host "`n--- All File Types ($($files.Count) total) ---" -ForegroundColor Yellow + } else { + Write-Host "`n--- .$extension Files ($($files.Count) total) ---" -ForegroundColor Yellow + } + + $count = 0 + $displayFiles = $files | Select-Object -First $MaxPerType + + foreach ($file in $displayFiles) { + $count++ + $totalFiles++ + Write-Host " $count. $file" -ForegroundColor Green + } + + if ($files.Count -gt $MaxPerType) { + $remaining = $files.Count - $MaxPerType + Write-Host " ... and $remaining more" -ForegroundColor Gray + } + } + } + } + + Write-Host "`n=== Summary ===" -ForegroundColor Cyan + Write-Host "Total stored: $totalStored files" -ForegroundColor Green + Write-Host "Displayed: $totalFiles files" -ForegroundColor Green + + if ($totalFiles -eq 0) { + Write-Host "`nNo readable file paths found in MRU data" -ForegroundColor Gray + Write-Host "The PIDL binary format may require more advanced parsing" -ForegroundColor Gray + } + } else { + Write-Host "`nNo recent file history found" -ForegroundColor Gray + } + + } else { + Write-Host "`nOpenSavePidlMRU registry key not found" -ForegroundColor Gray + } + +} catch { + Write-Host "Error: $_" -ForegroundColor Red +} + +Write-Host "`nNote: PIDL data parsing is limited. For complete analysis, use forensic tools like Registry Explorer" -ForegroundColor Cyan diff --git a/windows/Get-USBDevices.ps1 b/windows/Get-USBDevices.ps1 new file mode 100644 index 0000000..ef7209d --- /dev/null +++ b/windows/Get-USBDevices.ps1 @@ -0,0 +1,36 @@ +# Get-USBDevices.ps1 +# Lists all USB devices with vendor/product IDs + +Write-Host "`n=== USB Devices ===" -ForegroundColor Cyan +Write-Host "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB`n" + +try { + $usb = Get-ChildItem -Path "HKLM:\SYSTEM\CurrentControlSet\Enum\USB" -ErrorAction SilentlyContinue + if ($usb) { + foreach ($device in $usb) { + if ($device.PSChildName -match "VID_|vid_") { + $instances = Get-ChildItem -Path $device.PSPath -ErrorAction SilentlyContinue + $hasDevice = $false + + foreach ($instance in $instances) { + $props = Get-ItemProperty -Path $instance.PSPath -ErrorAction SilentlyContinue + if ($props.DeviceDesc) { + if (-not $hasDevice) { + Write-Host "$($device.PSChildName)" -ForegroundColor Yellow + $hasDevice = $true + } + # Clean up device description - extract text after semicolon if present + $desc = $props.DeviceDesc + if ($desc -match ';(.+)$') { + $desc = $matches[1] + } + Write-Host " $desc" + } + } + if ($hasDevice) { Write-Host "" } + } + } + } +} catch { + Write-Host "Error: $_" -ForegroundColor Red +} diff --git a/windows/Get-USBForensics.ps1 b/windows/Get-USBForensics.ps1 new file mode 100644 index 0000000..fcaf806 --- /dev/null +++ b/windows/Get-USBForensics.ps1 @@ -0,0 +1,135 @@ +# Get-USBForensics.ps1 +# PowerShell script to gather USB and storage forensic artifacts + +Write-Host "`n=== USB Storage Devices (USBSTOR) ===" -ForegroundColor Cyan +Write-Host "Location: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR`n" + +try { + $usbstor = Get-ChildItem -Path "HKLM:\SYSTEM\CurrentControlSet\Enum\USBSTOR" -ErrorAction SilentlyContinue + if ($usbstor) { + foreach ($device in $usbstor) { + Write-Host "Device: $($device.PSChildName)" -ForegroundColor Yellow + + $instances = Get-ChildItem -Path $device.PSPath -ErrorAction SilentlyContinue + foreach ($instance in $instances) { + $props = Get-ItemProperty -Path $instance.PSPath -ErrorAction SilentlyContinue + Write-Host " Serial: $($instance.PSChildName)" + Write-Host " Friendly Name: $($props.FriendlyName)" + Write-Host " Service: $($props.Service)" + Write-Host "" + } + } + } else { + Write-Host "No USB storage devices found." -ForegroundColor Gray + } +} catch { + Write-Host "Error accessing USBSTOR: $_" -ForegroundColor Red +} + +Write-Host "`n=== USB Devices (USB) ===" -ForegroundColor Cyan +Write-Host "Location: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB`n" + +try { + $usb = Get-ChildItem -Path "HKLM:\SYSTEM\CurrentControlSet\Enum\USB" -ErrorAction SilentlyContinue + if ($usb) { + foreach ($device in $usb) { + if ($device.PSChildName -match "VID_|vid_") { + Write-Host "Device: $($device.PSChildName)" -ForegroundColor Yellow + + $instances = Get-ChildItem -Path $device.PSPath -ErrorAction SilentlyContinue + foreach ($instance in $instances) { + $props = Get-ItemProperty -Path $instance.PSPath -ErrorAction SilentlyContinue + if ($props.DeviceDesc) { + Write-Host " Instance: $($instance.PSChildName)" + Write-Host " Description: $($props.DeviceDesc)" + Write-Host "" + } + } + } + } + } +} catch { + Write-Host "Error accessing USB: $_" -ForegroundColor Red +} + +Write-Host "`n=== Mounted Devices ===" -ForegroundColor Cyan +Write-Host "Location: HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices`n" + +try { + $mounted = Get-ItemProperty -Path "HKLM:\SYSTEM\MountedDevices" -ErrorAction SilentlyContinue + if ($mounted) { + $mounted.PSObject.Properties | Where-Object { $_.Name -notmatch "^PS" } | ForEach-Object { + Write-Host "Drive: $($_.Name)" -ForegroundColor Yellow + # Convert byte array to hex string for readability + if ($_.Value -is [byte[]]) { + $hexValue = ($_.Value | ForEach-Object { $_.ToString("X2") }) -join " " + Write-Host " Value: $hexValue" + } else { + Write-Host " Value: $($_.Value)" + } + Write-Host "" + } + } +} catch { + Write-Host "Error accessing MountedDevices: $_" -ForegroundColor Red +} + +Write-Host "`n=== Portable Devices ===" -ForegroundColor Cyan +Write-Host "Location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Portable Devices\Devices`n" + +try { + $portableDevices = Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows Portable Devices\Devices" -ErrorAction SilentlyContinue + if ($portableDevices) { + foreach ($device in $portableDevices) { + Write-Host "Device: $($device.PSChildName)" -ForegroundColor Yellow + $props = Get-ItemProperty -Path $device.PSPath -ErrorAction SilentlyContinue + Write-Host " Friendly Name: $($props.FriendlyName)" + Write-Host "" + } + } else { + Write-Host "No portable devices found." -ForegroundColor Gray + } +} catch { + Write-Host "Error accessing Portable Devices: $_" -ForegroundColor Red +} + +Write-Host "`n=== Setup API Device Install Log (Last 20 USB entries) ===" -ForegroundColor Cyan +Write-Host "Location: C:\Windows\inf\setupapi.dev.log`n" + +try { + $setupLog = "C:\Windows\inf\setupapi.dev.log" + if (Test-Path $setupLog) { + $usbEntries = Select-String -Path $setupLog -Pattern "USB" -Context 0,2 -ErrorAction SilentlyContinue | Select-Object -Last 20 + foreach ($entry in $usbEntries) { + Write-Host $entry.Line -ForegroundColor Gray + } + } else { + Write-Host "Setup log not found." -ForegroundColor Gray + } +} catch { + Write-Host "Error accessing setup log: $_" -ForegroundColor Red +} + +Write-Host "`n=== Current USB Devices (via WMI) ===" -ForegroundColor Cyan + +try { + $wmiUSB = Get-WmiObject Win32_USBControllerDevice -ErrorAction SilentlyContinue | ForEach-Object { + [wmi]($_.Dependent) + } | Select-Object Description, DeviceID, Manufacturer | Where-Object { $_.Description -ne $null } + + if ($wmiUSB) { + $wmiUSB | ForEach-Object { + Write-Host "Description: $($_.Description)" -ForegroundColor Yellow + Write-Host " Device ID: $($_.DeviceID)" + Write-Host " Manufacturer: $($_.Manufacturer)" + Write-Host "" + } + } else { + Write-Host "No USB devices currently connected." -ForegroundColor Gray + } +} catch { + Write-Host "Error accessing WMI: $_" -ForegroundColor Red +} + +Write-Host "`n=== Script Complete ===" -ForegroundColor Green +Write-Host "Note: Run as Administrator for complete results.`n" diff --git a/windows/Get-USBStorage.ps1 b/windows/Get-USBStorage.ps1 new file mode 100644 index 0000000..6597ea6 --- /dev/null +++ b/windows/Get-USBStorage.ps1 @@ -0,0 +1,26 @@ +# Get-USBStorage.ps1 +# Lists USB storage devices from USBSTOR registry key + +Write-Host "=== USB Storage Devices (USBSTOR) ===" -ForegroundColor Cyan +Write-Host "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR" + +try { + $usbstor = Get-ChildItem -Path "HKLM:\SYSTEM\CurrentControlSet\Enum\USBSTOR" -ErrorAction SilentlyContinue + if ($usbstor) { + foreach ($device in $usbstor) { + Write-Host "Device: $($device.PSChildName)" -ForegroundColor Yellow + + $instances = Get-ChildItem -Path $device.PSPath -ErrorAction SilentlyContinue + foreach ($instance in $instances) { + $props = Get-ItemProperty -Path $instance.PSPath -ErrorAction SilentlyContinue + Write-Host " Serial: $($instance.PSChildName)" + if ($props.FriendlyName) { Write-Host " Name: $($props.FriendlyName)" } + Write-Host "" + } + } + } else { + Write-Host "No USB storage devices found." -ForegroundColor Gray + } +} catch { + Write-Host "Error: $_" -ForegroundColor Red +} diff --git a/windows/Get-Users.ps1 b/windows/Get-Users.ps1 new file mode 100644 index 0000000..e286d20 --- /dev/null +++ b/windows/Get-Users.ps1 @@ -0,0 +1,174 @@ +# Get-Users.ps1 +# Lists all users on the system with detailed information + +param( + [Parameter(Position=0)] + [ValidateSet("simple", "detailed", "full")] + [string]$Mode = "simple" +) + +Write-Host "=== System Users ===" -ForegroundColor Cyan + +if ($Mode -eq "simple") { + Write-Host "Mode: Simple (use -Mode detailed or -Mode full for more info)`n" -ForegroundColor Yellow +} elseif ($Mode -eq "detailed") { + Write-Host "Mode: Detailed`n" -ForegroundColor Yellow +} else { + Write-Host "Mode: Full`n" -ForegroundColor Yellow +} + +# Local Users +Write-Host "--- Local User Accounts ---" -ForegroundColor Yellow +try { + $localUsers = Get-LocalUser + + if ($Mode -eq "simple") { + # Simple mode: just list usernames + foreach ($user in $localUsers) { + $status = if ($user.Enabled) { "" } else { " (Disabled)" } + Write-Host "$($user.Name)$status" -ForegroundColor Green + } + + } elseif ($Mode -eq "detailed") { + # Detailed mode: username, enabled status, last logon + foreach ($user in $localUsers) { + Write-Host "`n$($user.Name)" -ForegroundColor Green + Write-Host " Enabled: $($user.Enabled)" -ForegroundColor Cyan + Write-Host " Last Logon: $(if ($user.LastLogon) { $user.LastLogon.ToString('yyyy-MM-dd HH:mm:ss') } else { 'Never' })" -ForegroundColor Cyan + Write-Host " Password Last Set: $(if ($user.PasswordLastSet) { $user.PasswordLastSet.ToString('yyyy-MM-dd HH:mm:ss') } else { 'Never' })" -ForegroundColor Cyan + } + + } else { + # Full mode: all details + foreach ($user in $localUsers) { + Write-Host "`nUsername: $($user.Name)" -ForegroundColor Green + Write-Host " Full Name: $($user.FullName)" -ForegroundColor Cyan + Write-Host " Description: $($user.Description)" -ForegroundColor Cyan + Write-Host " Enabled: $($user.Enabled)" -ForegroundColor Cyan + Write-Host " Account Expires: $(if ($user.AccountExpires) { $user.AccountExpires } else { 'Never' })" -ForegroundColor Cyan + Write-Host " Password Last Set: $(if ($user.PasswordLastSet) { $user.PasswordLastSet.ToString('yyyy-MM-dd HH:mm:ss') } else { 'Never' })" -ForegroundColor Cyan + Write-Host " Password Expires: $(if ($user.PasswordExpires) { $user.PasswordExpires } else { 'Never' })" -ForegroundColor Cyan + Write-Host " Last Logon: $(if ($user.LastLogon) { $user.LastLogon.ToString('yyyy-MM-dd HH:mm:ss') } else { 'Never' })" -ForegroundColor Cyan + Write-Host " Password Required: $($user.PasswordRequired)" -ForegroundColor Cyan + Write-Host " User May Change Password: $($user.UserMayChangePassword)" -ForegroundColor Cyan + Write-Host " SID: $($user.SID)" -ForegroundColor Gray + } + } + + Write-Host "`nTotal Local Users: $($localUsers.Count)" -ForegroundColor Green + +} catch { + Write-Host "Error getting local users: $_" -ForegroundColor Red +} + +# Only show profile paths in detailed and full modes +if ($Mode -ne "simple") { + Write-Host "`n--- User Profiles (from Registry) ---" -ForegroundColor Yellow + try { + $profileListPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" + + if (Test-Path $profileListPath) { + $profiles = Get-ChildItem -Path $profileListPath -ErrorAction SilentlyContinue + + foreach ($profile in $profiles) { + $props = Get-ItemProperty -Path $profile.PSPath -ErrorAction SilentlyContinue + + if ($props.ProfileImagePath) { + $sid = $profile.PSChildName + + # Try to resolve SID to username + try { + $objSID = New-Object System.Security.Principal.SecurityIdentifier($sid) + $objUser = $objSID.Translate([System.Security.Principal.NTAccount]) + $username = $objUser.Value + } catch { + $username = "Unknown" + } + + Write-Host "`n$username" -ForegroundColor Green + Write-Host " Profile Path: $($props.ProfileImagePath)" -ForegroundColor Cyan + + if ($Mode -eq "full") { + Write-Host " SID: $sid" -ForegroundColor Gray + + if ($props.LocalProfileLoadTimeHigh -and $props.LocalProfileLoadTimeLow) { + $loadTime = [DateTime]::FromFileTime(([Int64]$props.LocalProfileLoadTimeHigh -shl 32) -bor $props.LocalProfileLoadTimeLow) + Write-Host " Profile Load Time: $($loadTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Cyan + } + } + } + } + } + } catch { + Write-Host "Error reading profile list: $_" -ForegroundColor Red + } +} + +# Currently Logged In Users +Write-Host "`n--- Currently Logged In Users ---" -ForegroundColor Yellow +try { + $loggedInUsers = quser 2>$null + + if ($loggedInUsers) { + $loggedInUsers | ForEach-Object { + Write-Host $_ -ForegroundColor Green + } + } else { + # Alternative method using WMI + $sessions = Get-CimInstance -ClassName Win32_ComputerSystem + if ($sessions.UserName) { + Write-Host "$($sessions.UserName)" -ForegroundColor Green + } else { + Write-Host "No users currently logged in" -ForegroundColor Gray + } + } +} catch { + Write-Host "Error getting logged in users: $_" -ForegroundColor Red +} + +# Only show groups in full mode +if ($Mode -eq "full") { + Write-Host "`n--- Local Groups ---" -ForegroundColor Yellow + try { + $groups = Get-LocalGroup + + foreach ($group in $groups) { + Write-Host "`n$($group.Name)" -ForegroundColor Green + Write-Host " Description: $($group.Description)" -ForegroundColor Cyan + Write-Host " SID: $($group.SID)" -ForegroundColor Gray + + # Get group members + try { + $members = Get-LocalGroupMember -Group $group.Name -ErrorAction SilentlyContinue + if ($members) { + Write-Host " Members:" -ForegroundColor Cyan + foreach ($member in $members) { + Write-Host " - $($member.Name) ($($member.ObjectClass))" -ForegroundColor Yellow + } + } else { + Write-Host " Members: None" -ForegroundColor Gray + } + } catch { + Write-Host " Members: Unable to retrieve" -ForegroundColor Gray + } + } + } catch { + Write-Host "Error getting local groups: $_" -ForegroundColor Red + } +} + +# Summary +if ($Mode -ne "simple") { + Write-Host "`n=== Summary ===" -ForegroundColor Cyan + try { + $enabledUsers = (Get-LocalUser | Where-Object { $_.Enabled -eq $true }).Count + $disabledUsers = (Get-LocalUser | Where-Object { $_.Enabled -eq $false }).Count + $totalGroups = (Get-LocalGroup).Count + + Write-Host "Enabled Users: $enabledUsers" -ForegroundColor Green + Write-Host "Disabled Users: $disabledUsers" -ForegroundColor Green + Write-Host "Total Groups: $totalGroups" -ForegroundColor Green + } catch { + Write-Host "Error generating summary" -ForegroundColor Red + } +}