Add Jump Lists collection (Get-JumpLists.ps1)

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.
This commit is contained in:
2026-02-03 21:57:10 +01:00
parent dcebc0f4fa
commit 0f15779472
2 changed files with 209 additions and 1 deletions

View File

@@ -18,7 +18,7 @@
- [ ] UserAssist - Programs run by user through Windows Explorer - [ ] UserAssist - Programs run by user through Windows Explorer
- [ ] ShimCache (AppCompatCache) - Executable files that have been run - [ ] ShimCache (AppCompatCache) - Executable files that have been run
- [ ] AmCache - Program execution with file hashes and timestamps - [ ] AmCache - Program execution with file hashes and timestamps
- [ ] Jump Lists - Recently accessed files per application - [x] Jump Lists - Recently accessed files per application
- [ ] Prefetch files - Program execution history with run counts - [ ] Prefetch files - Program execution history with run counts
- [ ] BAM/DAM - Background Activity Moderator (program execution timestamps) - [ ] BAM/DAM - Background Activity Moderator (program execution timestamps)

208
windows/Get-JumpLists.ps1 Normal file
View File

@@ -0,0 +1,208 @@
# 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