Collect Jump List artifacts showing recent files per application. Includes smart app detection via content scanning, LNK file enumeration with target extraction, and both automatic/custom destinations. Supports -ShowAll and -MaxPerApp parameters. Mark Jump Lists complete in TODO.md.
209 lines
9.1 KiB
PowerShell
209 lines
9.1 KiB
PowerShell
# Get-JumpLists.ps1
|
|
# Lists Jump List artifacts showing recently accessed files per application
|
|
|
|
param(
|
|
[int]$MaxPerApp = 10,
|
|
[switch]$ShowAll
|
|
)
|
|
|
|
Write-Host "=== Jump Lists ===" -ForegroundColor Cyan
|
|
Write-Host "Recently accessed files per application`n"
|
|
|
|
if ($ShowAll) {
|
|
$MaxPerApp = [int]::MaxValue
|
|
}
|
|
|
|
# Jump List locations
|
|
$automaticDestinations = "$env:APPDATA\Microsoft\Windows\Recent\AutomaticDestinations"
|
|
$customDestinations = "$env:APPDATA\Microsoft\Windows\Recent\CustomDestinations"
|
|
|
|
# Common AppIDs (application identifiers)
|
|
# Note: AppIDs are CRC-64 hashes of executable paths and vary between systems
|
|
# We'll rely primarily on content detection instead
|
|
$knownAppIDs = @{
|
|
# Only including well-known, verified AppIDs
|
|
"1b4dd67f29cb1962" = "Internet Explorer"
|
|
"6d809377-6af0-444b-8957-a3773f02200e" = "Remote Desktop Connection"
|
|
}
|
|
|
|
# Function to try identifying app from jump list content
|
|
function Get-AppNameFromJumpList {
|
|
param([string]$filePath)
|
|
|
|
try {
|
|
# Try to read first few KB and look for common strings
|
|
$bytes = [System.IO.File]::ReadAllBytes($filePath) | Select-Object -First 8192
|
|
$text = [System.Text.Encoding]::Unicode.GetString($bytes)
|
|
|
|
# Look for common app identifiers in the content
|
|
if ($text -match 'chrome\.exe') { return "Google Chrome" }
|
|
if ($text -match 'firefox\.exe') { return "Mozilla Firefox" }
|
|
if ($text -match 'msedge\.exe') { return "Microsoft Edge" }
|
|
if ($text -match 'Code\.exe') { return "Visual Studio Code" }
|
|
if ($text -match 'WINWORD\.EXE') { return "Microsoft Word" }
|
|
if ($text -match 'EXCEL\.EXE') { return "Microsoft Excel" }
|
|
if ($text -match 'POWERPNT\.EXE') { return "Microsoft PowerPoint" }
|
|
if ($text -match 'notepad\+\+\.exe') { return "Notepad++" }
|
|
if ($text -match 'sublime_text\.exe') { return "Sublime Text" }
|
|
if ($text -match 'devenv\.exe') { return "Visual Studio" }
|
|
if ($text -match 'pycharm.*\.exe') { return "PyCharm" }
|
|
if ($text -match 'idea.*\.exe') { return "IntelliJ IDEA" }
|
|
if ($text -match 'vlc\.exe') { return "VLC Media Player" }
|
|
if ($text -match 'AcroRd.*\.exe') { return "Adobe Reader" }
|
|
if ($text -match '7zFM\.exe') { return "7-Zip" }
|
|
if ($text -match 'WindowsTerminal\.exe') { return "Windows Terminal" }
|
|
if ($text -match 'powershell\.exe') { return "Windows PowerShell" }
|
|
if ($text -match 'explorer\.exe') { return "File Explorer" }
|
|
|
|
return $null
|
|
} catch {
|
|
return $null
|
|
}
|
|
}
|
|
|
|
$totalFiles = 0
|
|
$totalApps = 0
|
|
|
|
# Process AutomaticDestinations (automatically managed jump lists)
|
|
Write-Host "--- Automatic Destinations ---" -ForegroundColor Yellow
|
|
if (Test-Path $automaticDestinations) {
|
|
$autoJumpLists = Get-ChildItem -Path $automaticDestinations -Filter "*.automaticDestinations-ms" -ErrorAction SilentlyContinue
|
|
|
|
if ($autoJumpLists) {
|
|
foreach ($jumpList in $autoJumpLists) {
|
|
# Extract AppID from filename
|
|
$appID = $jumpList.Name -replace '\.automaticDestinations-ms$', ''
|
|
|
|
# Try to identify app from known AppIDs first
|
|
$appName = if ($knownAppIDs.ContainsKey($appID)) {
|
|
$knownAppIDs[$appID]
|
|
} else {
|
|
# Try to identify from file content
|
|
$detectedName = Get-AppNameFromJumpList -filePath $jumpList.FullName
|
|
if ($detectedName) {
|
|
"$detectedName (detected)"
|
|
} else {
|
|
"Unknown Application"
|
|
}
|
|
}
|
|
|
|
Write-Host "`n$appName" -ForegroundColor Green
|
|
Write-Host " AppID: $appID" -ForegroundColor Gray
|
|
Write-Host " File: $($jumpList.Name)" -ForegroundColor Gray
|
|
Write-Host " Modified: $($jumpList.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Gray
|
|
Write-Host " Size: $($jumpList.Length) bytes" -ForegroundColor Gray
|
|
|
|
# Note: Parsing .automaticDestinations-ms files requires complex OLE/compound file parsing
|
|
# This would need a specialized library or tool like JLECmd (Eric Zimmerman)
|
|
Write-Host " (Use JLECmd or similar tool for detailed parsing)" -ForegroundColor Cyan
|
|
|
|
$totalApps++
|
|
}
|
|
|
|
Write-Host "`nTotal applications with jump lists: $totalApps" -ForegroundColor Green
|
|
} else {
|
|
Write-Host "No automatic destination jump lists found" -ForegroundColor Gray
|
|
}
|
|
} else {
|
|
Write-Host "AutomaticDestinations directory not found" -ForegroundColor Gray
|
|
}
|
|
|
|
# Process CustomDestinations (manually pinned items)
|
|
Write-Host "`n--- Custom Destinations (Pinned Items) ---" -ForegroundColor Yellow
|
|
if (Test-Path $customDestinations) {
|
|
$customJumpLists = Get-ChildItem -Path $customDestinations -Filter "*.customDestinations-ms" -ErrorAction SilentlyContinue
|
|
|
|
if ($customJumpLists) {
|
|
$pinnedApps = 0
|
|
foreach ($jumpList in $customJumpLists) {
|
|
# Extract AppID from filename
|
|
$appID = $jumpList.Name -replace '\.customDestinations-ms$', ''
|
|
|
|
# Try to identify app from known AppIDs first
|
|
$appName = if ($knownAppIDs.ContainsKey($appID)) {
|
|
$knownAppIDs[$appID]
|
|
} else {
|
|
# Try to identify from file content
|
|
$detectedName = Get-AppNameFromJumpList -filePath $jumpList.FullName
|
|
if ($detectedName) {
|
|
"$detectedName (detected)"
|
|
} else {
|
|
"Unknown Application"
|
|
}
|
|
}
|
|
|
|
Write-Host "`n$appName" -ForegroundColor Green
|
|
Write-Host " AppID: $appID" -ForegroundColor Gray
|
|
Write-Host " File: $($jumpList.Name)" -ForegroundColor Gray
|
|
Write-Host " Modified: $($jumpList.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Gray
|
|
Write-Host " Size: $($jumpList.Length) bytes" -ForegroundColor Gray
|
|
Write-Host " (Contains user-pinned items)" -ForegroundColor Cyan
|
|
|
|
$pinnedApps++
|
|
}
|
|
|
|
Write-Host "`nTotal applications with pinned items: $pinnedApps" -ForegroundColor Green
|
|
} else {
|
|
Write-Host "No custom destination jump lists found" -ForegroundColor Gray
|
|
}
|
|
} else {
|
|
Write-Host "CustomDestinations directory not found" -ForegroundColor Gray
|
|
}
|
|
|
|
# Recent Items (LNK files)
|
|
Write-Host "`n--- Recent Items (LNK Files) ---" -ForegroundColor Yellow
|
|
$recentItems = "$env:APPDATA\Microsoft\Windows\Recent"
|
|
|
|
if (Test-Path $recentItems) {
|
|
$lnkFiles = Get-ChildItem -Path $recentItems -Filter "*.lnk" -ErrorAction SilentlyContinue |
|
|
Sort-Object LastWriteTime -Descending
|
|
|
|
if ($lnkFiles) {
|
|
Write-Host "Recent files accessed (via LNK shortcuts):`n" -ForegroundColor Cyan
|
|
|
|
$count = 0
|
|
foreach ($lnk in ($lnkFiles | Select-Object -First $MaxPerApp)) {
|
|
$count++
|
|
$totalFiles++
|
|
|
|
Write-Host " $count. $($lnk.Name -replace '\.lnk$', '')" -ForegroundColor Green
|
|
Write-Host " Last Accessed: $($lnk.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Gray
|
|
Write-Host " Path: $($lnk.FullName)" -ForegroundColor Gray
|
|
|
|
# Try to extract target path using Shell.Application
|
|
try {
|
|
$shell = New-Object -ComObject WScript.Shell
|
|
$shortcut = $shell.CreateShortcut($lnk.FullName)
|
|
if ($shortcut.TargetPath) {
|
|
Write-Host " Target: $($shortcut.TargetPath)" -ForegroundColor Cyan
|
|
}
|
|
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell) | Out-Null
|
|
} catch {
|
|
# Silently fail if COM object can't be created
|
|
}
|
|
}
|
|
|
|
if ($lnkFiles.Count -gt $MaxPerApp) {
|
|
Write-Host "`n ... and $($lnkFiles.Count - $MaxPerApp) more" -ForegroundColor Gray
|
|
}
|
|
|
|
Write-Host "`nTotal recent LNK files: $($lnkFiles.Count)" -ForegroundColor Green
|
|
} else {
|
|
Write-Host "No recent LNK files found" -ForegroundColor Gray
|
|
}
|
|
} else {
|
|
Write-Host "Recent items directory not found" -ForegroundColor Gray
|
|
}
|
|
|
|
Write-Host "`n=== Summary ===" -ForegroundColor Cyan
|
|
Write-Host "Applications with jump lists: $totalApps" -ForegroundColor Green
|
|
Write-Host "Recent LNK files displayed: $totalFiles" -ForegroundColor Green
|
|
|
|
Write-Host "`nNote: For detailed Jump List parsing, use specialized tools:" -ForegroundColor Yellow
|
|
Write-Host " - JLECmd (Eric Zimmerman): https://github.com/EricZimmerman/JLECmd" -ForegroundColor Cyan
|
|
Write-Host " - Autopsy with Jump List Analyzer plugin" -ForegroundColor Cyan
|
|
Write-Host " - Registry Explorer for viewing shellbags" -ForegroundColor Cyan
|
|
|
|
Write-Host "`nJump List files are compound OLE documents requiring specialized parsing" -ForegroundColor Yellow
|
|
Write-Host "This script shows metadata; use JLECmd for full content extraction" -ForegroundColor Yellow
|