Add typed URLs extraction with multi-profile support
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.
This commit is contained in:
222
windows/Get-TypedURLs.ps1
Normal file
222
windows/Get-TypedURLs.ps1
Normal file
@@ -0,0 +1,222 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user