Add Get-TypedURLs.ps1 for browser typed URL forensics: - IE (registry), Edge, Chrome, Chromium (all profiles), Firefox - Auto-detects all browser profiles (Default, Profile 1, 2, etc.) - Shows typed counts and visit frequencies - Proper DB locking/cleanup with finally blocks - Requires sqlite3.exe for Chromium-based browsers Update README.md and TODO.md with recent scripts.
223 lines
8.7 KiB
PowerShell
223 lines
8.7 KiB
PowerShell
# Get-TypedURLs.ps1
|
|
# Extracts manually typed URLs from browsers (IE, Edge, Chrome, Firefox)
|
|
|
|
param(
|
|
[int]$MaxPerBrowser = 20,
|
|
[switch]$ShowAll
|
|
)
|
|
|
|
Write-Host "=== Typed URLs ===" -ForegroundColor Cyan
|
|
Write-Host "URLs manually typed into browser address bars`n"
|
|
|
|
if ($ShowAll) {
|
|
$MaxPerBrowser = [int]::MaxValue
|
|
}
|
|
|
|
$foundAny = $false
|
|
|
|
# Internet Explorer - TypedURLs from Registry
|
|
Write-Host "--- Internet Explorer (Registry) ---" -ForegroundColor Yellow
|
|
try {
|
|
$ieTypedURLs = "HKCU:\Software\Microsoft\Internet Explorer\TypedURLs"
|
|
|
|
if (Test-Path $ieTypedURLs) {
|
|
$urls = Get-ItemProperty -Path $ieTypedURLs -ErrorAction SilentlyContinue
|
|
$urlList = @()
|
|
|
|
# IE stores as url1, url2, url3, etc.
|
|
for ($i = 1; $i -le 50; $i++) {
|
|
$urlKey = "url$i"
|
|
if ($urls.$urlKey) {
|
|
$urlList += $urls.$urlKey
|
|
}
|
|
}
|
|
|
|
if ($urlList.Count -gt 0) {
|
|
$foundAny = $true
|
|
$count = 0
|
|
foreach ($url in $urlList) {
|
|
$count++
|
|
Write-Host " $count. $url" -ForegroundColor Green
|
|
if ($count -ge $MaxPerBrowser) { break }
|
|
}
|
|
Write-Host " Total: $($urlList.Count)" -ForegroundColor Gray
|
|
} else {
|
|
Write-Host " No typed URLs found" -ForegroundColor Gray
|
|
}
|
|
} else {
|
|
Write-Host " Registry key not found" -ForegroundColor Gray
|
|
}
|
|
} catch {
|
|
Write-Host " Error: $_" -ForegroundColor Red
|
|
}
|
|
|
|
# Function to parse Chrome/Edge History SQLite database
|
|
function Get-ChromiumTypedURLs {
|
|
param(
|
|
[string]$historyPath,
|
|
[string]$browserName,
|
|
[int]$maxResults
|
|
)
|
|
|
|
Write-Host " Checking: $historyPath" -ForegroundColor Gray
|
|
|
|
if (-not (Test-Path $historyPath)) {
|
|
Write-Host " History database not found" -ForegroundColor Gray
|
|
return
|
|
}
|
|
|
|
try {
|
|
# Copy database to temp (Chrome locks it when running)
|
|
$tempDB = "$env:TEMP\history_temp_$(Get-Random).db"
|
|
|
|
# Try to copy, might fail if browser is running
|
|
try {
|
|
Copy-Item -Path $historyPath -Destination $tempDB -Force -ErrorAction Stop
|
|
} catch {
|
|
Write-Host " Database locked - close $browserName and try again" -ForegroundColor Yellow
|
|
return
|
|
}
|
|
|
|
# Load SQLite assembly (if available)
|
|
try {
|
|
Add-Type -Path "System.Data.SQLite.dll" -ErrorAction Stop
|
|
} catch {
|
|
# Try to use sqlite3.exe if available
|
|
$sqlite3 = Get-Command sqlite3.exe -ErrorAction SilentlyContinue
|
|
|
|
if ($sqlite3) {
|
|
$query = "SELECT url, typed_count FROM urls WHERE typed_count > 0 ORDER BY typed_count DESC LIMIT $maxResults;"
|
|
$result = & sqlite3.exe $tempDB $query
|
|
|
|
if ($result) {
|
|
$foundAny = $true
|
|
$count = 0
|
|
foreach ($line in $result) {
|
|
$parts = $line -split '\|'
|
|
if ($parts.Length -ge 2) {
|
|
$count++
|
|
Write-Host " $count. $($parts[0])" -ForegroundColor Green
|
|
Write-Host " Typed: $($parts[1]) times" -ForegroundColor Gray
|
|
}
|
|
}
|
|
} else {
|
|
Write-Host " No typed URLs found" -ForegroundColor Gray
|
|
}
|
|
} else {
|
|
Write-Host " SQLite not available - install sqlite3.exe or System.Data.SQLite" -ForegroundColor Yellow
|
|
Write-Host " Database location: $historyPath" -ForegroundColor Cyan
|
|
}
|
|
}
|
|
} catch {
|
|
Write-Host " Error reading database: $_" -ForegroundColor Red
|
|
} finally {
|
|
# Always clean up temp database
|
|
if (Test-Path $tempDB -ErrorAction SilentlyContinue) {
|
|
Remove-Item -Path $tempDB -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
}
|
|
|
|
# Microsoft Edge
|
|
Write-Host "`n--- Microsoft Edge ---" -ForegroundColor Yellow
|
|
$edgeHistory = "$env:LOCALAPPDATA\Microsoft\Edge\User Data\Default\History"
|
|
Get-ChromiumTypedURLs -historyPath $edgeHistory -browserName "Edge" -maxResults $MaxPerBrowser
|
|
|
|
# Google Chrome
|
|
Write-Host "`n--- Google Chrome ---" -ForegroundColor Yellow
|
|
$chromeHistory = "$env:LOCALAPPDATA\Google\Chrome\User Data\Default\History"
|
|
Get-ChromiumTypedURLs -historyPath $chromeHistory -browserName "Chrome" -maxResults $MaxPerBrowser
|
|
|
|
# Ungoogled Chromium / Chromium - Check all profiles
|
|
Write-Host "`n--- Chromium (Ungoogled) ---" -ForegroundColor Yellow
|
|
$chromiumUserData = "$env:LOCALAPPDATA\Chromium\User Data"
|
|
|
|
if (Test-Path $chromiumUserData) {
|
|
# Check Default profile
|
|
$chromiumHistory = "$chromiumUserData\Default\History"
|
|
if (Test-Path $chromiumHistory) {
|
|
Write-Host " Profile: Default" -ForegroundColor Cyan
|
|
Get-ChromiumTypedURLs -historyPath $chromiumHistory -browserName "Chromium" -maxResults $MaxPerBrowser
|
|
}
|
|
|
|
# Check numbered profiles (Profile 1, Profile 2, etc.)
|
|
$profiles = Get-ChildItem -Path $chromiumUserData -Directory -Filter "Profile*" -ErrorAction SilentlyContinue
|
|
foreach ($profile in $profiles) {
|
|
$profileHistory = Join-Path $profile.FullName "History"
|
|
if (Test-Path $profileHistory) {
|
|
Write-Host " Profile: $($profile.Name)" -ForegroundColor Cyan
|
|
Get-ChromiumTypedURLs -historyPath $profileHistory -browserName "Chromium" -maxResults $MaxPerBrowser
|
|
}
|
|
}
|
|
} else {
|
|
Write-Host " Chromium not installed" -ForegroundColor Gray
|
|
}
|
|
|
|
# Firefox
|
|
Write-Host "`n--- Mozilla Firefox ---" -ForegroundColor Yellow
|
|
try {
|
|
$firefoxProfiles = "$env:APPDATA\Mozilla\Firefox\Profiles"
|
|
|
|
if (Test-Path $firefoxProfiles) {
|
|
$profiles = Get-ChildItem -Path $firefoxProfiles -Directory -ErrorAction SilentlyContinue
|
|
|
|
if ($profiles) {
|
|
foreach ($profile in $profiles) {
|
|
$placesDB = Join-Path $profile.FullName "places.sqlite"
|
|
|
|
if (Test-Path $placesDB) {
|
|
Write-Host " Profile: $($profile.Name)" -ForegroundColor Cyan
|
|
|
|
# Copy to temp
|
|
$tempDB = "$env:TEMP\places_temp_$(Get-Random).db"
|
|
Copy-Item -Path $placesDB -Destination $tempDB -Force -ErrorAction Stop
|
|
|
|
# Try sqlite3.exe
|
|
$sqlite3 = Get-Command sqlite3.exe -ErrorAction SilentlyContinue
|
|
|
|
if ($sqlite3) {
|
|
# Firefox uses visit_count in moz_places, but doesn't track typed specifically
|
|
# We look for high visit counts as proxy
|
|
$query = "SELECT url, visit_count FROM moz_places WHERE visit_count > 5 ORDER BY visit_count DESC LIMIT $MaxPerBrowser;"
|
|
$result = & sqlite3.exe $tempDB $query
|
|
|
|
if ($result) {
|
|
$foundAny = $true
|
|
$count = 0
|
|
foreach ($line in $result) {
|
|
$parts = $line -split '\|'
|
|
if ($parts.Length -ge 2) {
|
|
$count++
|
|
Write-Host " $count. $($parts[0])" -ForegroundColor Green
|
|
Write-Host " Visits: $($parts[1])" -ForegroundColor Gray
|
|
}
|
|
}
|
|
} else {
|
|
Write-Host " No frequently visited URLs found" -ForegroundColor Gray
|
|
}
|
|
} else {
|
|
Write-Host " SQLite not available" -ForegroundColor Yellow
|
|
Write-Host " Database location: $placesDB" -ForegroundColor Cyan
|
|
}
|
|
|
|
Remove-Item -Path $tempDB -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
} else {
|
|
Write-Host " No Firefox profiles found" -ForegroundColor Gray
|
|
}
|
|
} else {
|
|
Write-Host " Firefox not installed or no profiles" -ForegroundColor Gray
|
|
}
|
|
} catch {
|
|
Write-Host " Error: $_" -ForegroundColor Red
|
|
}
|
|
|
|
if (-not $foundAny) {
|
|
Write-Host "`nNo typed URLs found in any browser" -ForegroundColor Gray
|
|
}
|
|
|
|
Write-Host "`nNote: Requires sqlite3.exe in PATH for Chrome/Edge/Firefox parsing" -ForegroundColor Yellow
|
|
Write-Host "Download from: https://www.sqlite.org/download.html" -ForegroundColor Cyan
|
|
Write-Host "Or install via: winget install SQLite.SQLite" -ForegroundColor Cyan
|