diff --git a/windows/Get-SearchHistory.ps1 b/windows/Get-SearchHistory.ps1 new file mode 100644 index 0000000..cd1a781 --- /dev/null +++ b/windows/Get-SearchHistory.ps1 @@ -0,0 +1,195 @@ +# Get-SearchHistory.ps1 +# Extracts Windows Search history from WordWheelQuery registry + +param( + [int]$MaxResults = 50, + [switch]$ShowAll +) + +Write-Host "=== Windows Search History ===" -ForegroundColor Cyan +Write-Host "Search queries from Windows Search Bar and File Explorer`n" + +Write-Host "Note: Windows 11 without Microsoft account may not persist search history" -ForegroundColor Yellow +Write-Host "Modern search uses cloud sync and memory-only caching`n" -ForegroundColor Yellow + +if ($ShowAll) { + $MaxResults = [int]::MaxValue +} + +$foundAny = $false + +# WordWheelQuery - Windows Search history +Write-Host "--- WordWheelQuery (Search Bar / File Explorer) ---" -ForegroundColor Yellow +try { + $wordWheelPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\WordWheelQuery" + + if (Test-Path $wordWheelPath) { + $props = Get-ItemProperty -Path $wordWheelPath -ErrorAction SilentlyContinue + + # Get MRUListEx to determine order + if ($props.MRUListEx) { + $searches = @() + + # Parse MRUListEx (4-byte integers) + for ($i = 0; $i -lt $props.MRUListEx.Length - 4; $i += 4) { + $index = [BitConverter]::ToInt32($props.MRUListEx, $i) + if ($index -eq -1) { break } # End marker + + # Get the search term from the indexed property + $propName = "$index" + if ($props.$propName) { + # Convert binary data to Unicode string + $searchTerm = [System.Text.Encoding]::Unicode.GetString($props.$propName) + # Remove null terminators + $searchTerm = $searchTerm -replace '\x00', '' + + if ($searchTerm) { + $searches += $searchTerm + } + } + } + + if ($searches.Count -gt 0) { + $foundAny = $true + Write-Host "Registry: $wordWheelPath`n" -ForegroundColor Gray + + $count = 0 + foreach ($search in ($searches | Select-Object -First $MaxResults)) { + $count++ + Write-Host " $count. $search" -ForegroundColor Green + } + + if ($searches.Count -gt $MaxResults) { + Write-Host "`n ... and $($searches.Count - $MaxResults) more" -ForegroundColor Gray + } + + Write-Host "`nTotal searches: $($searches.Count)" -ForegroundColor Green + } else { + Write-Host " No search history found" -ForegroundColor Gray + } + } else { + Write-Host " No MRUListEx found" -ForegroundColor Gray + } + } else { + Write-Host " Registry key not found" -ForegroundColor Gray + } +} catch { + Write-Host " Error: $_" -ForegroundColor Red +} + +# TypedPaths - File Explorer address bar typed paths +Write-Host "`n--- TypedPaths (File Explorer Address Bar) ---" -ForegroundColor Yellow +try { + $typedPathsPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths" + + if (Test-Path $typedPathsPath) { + $paths = Get-ItemProperty -Path $typedPathsPath -ErrorAction SilentlyContinue + $pathList = @() + + # TypedPaths stores as url1, url2, etc. + for ($i = 1; $i -le 50; $i++) { + $urlKey = "url$i" + if ($paths.$urlKey) { + $pathList += $paths.$urlKey + } + } + + if ($pathList.Count -gt 0) { + $foundAny = $true + Write-Host "Registry: $typedPathsPath`n" -ForegroundColor Gray + + $count = 0 + foreach ($path in ($pathList | Select-Object -First $MaxResults)) { + $count++ + Write-Host " $count. $path" -ForegroundColor Green + } + + Write-Host "`nTotal typed paths: $($pathList.Count)" -ForegroundColor Green + } else { + Write-Host " No typed paths found" -ForegroundColor Gray + } + } else { + Write-Host " Registry key not found" -ForegroundColor Gray + } +} catch { + Write-Host " Error: $_" -ForegroundColor Red +} + +# RunMRU - Run dialog history +Write-Host "`n--- RunMRU (Run Dialog History) ---" -ForegroundColor Yellow +try { + $runMRUPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU" + + if (Test-Path $runMRUPath) { + $runProps = Get-ItemProperty -Path $runMRUPath -ErrorAction SilentlyContinue + $runList = @() + + # RunMRU uses letter keys (a, b, c, etc.) and MRUList for order + if ($runProps.MRUList) { + $mruOrder = $runProps.MRUList.ToCharArray() + + foreach ($char in $mruOrder) { + $key = [string]$char + if ($runProps.$key) { + # Remove \1 terminator if present + $command = $runProps.$key -replace '\\1$', '' + if ($command) { + $runList += $command + } + } + } + } + + if ($runList.Count -gt 0) { + $foundAny = $true + Write-Host "Registry: $runMRUPath`n" -ForegroundColor Gray + + $count = 0 + foreach ($cmd in ($runList | Select-Object -First $MaxResults)) { + $count++ + Write-Host " $count. $cmd" -ForegroundColor Green + } + + Write-Host "`nTotal run commands: $($runList.Count)" -ForegroundColor Green + } else { + Write-Host " No run history found" -ForegroundColor Gray + } + } else { + Write-Host " Registry key not found" -ForegroundColor Gray + } +} catch { + Write-Host " Error: $_" -ForegroundColor Red +} + +# Recent searches in specific apps (if available) +Write-Host "`n--- Cortana/Search App (if available) ---" -ForegroundColor Yellow +try { + # Check for modern search database + $searchPackage = Get-ChildItem "$env:LOCALAPPDATA\Packages" -Filter "Microsoft.Windows.Search_*" -Directory -ErrorAction SilentlyContinue | Select-Object -First 1 + + if ($searchPackage) { + $searchCache = Join-Path $searchPackage.FullName "LocalState\DeviceSearchCache" + + if (Test-Path $searchCache) { + Write-Host " Search cache found: $searchCache" -ForegroundColor Cyan + Write-Host " (Binary database - requires specialized tools to parse)" -ForegroundColor Yellow + } else { + Write-Host " Search cache not found" -ForegroundColor Gray + } + } else { + Write-Host " Modern search app not found" -ForegroundColor Gray + } +} catch { + Write-Host " Error: $_" -ForegroundColor Red +} + +if (-not $foundAny) { + Write-Host "`nNo search history found" -ForegroundColor Gray + Write-Host "This is common on Windows 11 without a Microsoft account" -ForegroundColor Yellow +} + +Write-Host "`nNote: Search history shows user queries and typed paths" -ForegroundColor Cyan +Write-Host "This can reveal file names, apps, and topics of interest" -ForegroundColor Cyan +Write-Host "`nWindows 11 Limitation: Modern search without Microsoft account" -ForegroundColor Yellow +Write-Host "does not persist history to registry (cloud-first design)" -ForegroundColor Yellow +Write-Host "This works best on Windows 10 or systems with Microsoft accounts" -ForegroundColor Yellow