Add Windows forensic artifact collection toolkit
Add PowerShell scripts for collecting forensic artifacts: - USB/storage devices, mounted drives, portable devices - Network history and hotspot connections - Recent documents (OpenSavePidlMRU with PIDL parsing) - System info and user enumeration with multiple output modes Includes TODO.md for planned artifacts and updated README.
This commit is contained in:
141
windows/Get-RecentDocs.ps1
Normal file
141
windows/Get-RecentDocs.ps1
Normal file
@@ -0,0 +1,141 @@
|
||||
# Get-RecentDocs.ps1
|
||||
# Lists recently opened documents from OpenSavePidlMRU registry key
|
||||
|
||||
param(
|
||||
[int]$MaxPerType = 10,
|
||||
[switch]$ShowAll
|
||||
)
|
||||
|
||||
Write-Host "=== Recently Opened Documents ===" -ForegroundColor Cyan
|
||||
Write-Host "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU"
|
||||
|
||||
if ($ShowAll) {
|
||||
$MaxPerType = [int]::MaxValue
|
||||
Write-Host "Showing all entries`n" -ForegroundColor Yellow
|
||||
} else {
|
||||
Write-Host "Showing top $MaxPerType per type (use -ShowAll or -MaxPerType N to see more)`n" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
function Convert-PidlMRU {
|
||||
param([byte[]]$data)
|
||||
|
||||
if (-not $data -or $data.Length -lt 10) {
|
||||
return ""
|
||||
}
|
||||
|
||||
try {
|
||||
# Convert to Unicode string
|
||||
$unicodeText = [System.Text.Encoding]::Unicode.GetString($data)
|
||||
|
||||
# Remove null characters
|
||||
$cleaned = $unicodeText -replace '\x00', ''
|
||||
|
||||
# Try to extract valid file path (Windows path pattern)
|
||||
if ($cleaned -match '([A-Z]:\\(?:[^<>:"|?*\x00-\x1F]+\\)*[^<>:"|?*\x00-\x1F\\]+)') {
|
||||
return $matches[1]
|
||||
}
|
||||
|
||||
# Extract filename - match only valid filename characters
|
||||
# This regex looks for a sequence that starts with alphanumeric and includes a file extension
|
||||
if ($cleaned -match '([a-zA-Z0-9][a-zA-Z0-9._\- ]{0,200}\.[a-zA-Z0-9]{1,10})') {
|
||||
return $matches[1]
|
||||
}
|
||||
|
||||
# Fallback: filter to printable ASCII only and look for pattern
|
||||
$printable = -join ($cleaned.ToCharArray() | Where-Object {
|
||||
($_ -ge 32 -and $_ -le 126)
|
||||
})
|
||||
|
||||
# Try again with printable string
|
||||
if ($printable -match '([a-zA-Z0-9][a-zA-Z0-9._\- ]{0,200}\.[a-zA-Z0-9]{1,10})') {
|
||||
return $matches[1]
|
||||
}
|
||||
|
||||
return ""
|
||||
} catch {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$mruPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU"
|
||||
|
||||
if (Test-Path $mruPath) {
|
||||
# Get all extension subkeys
|
||||
$subKeys = Get-ChildItem -Path $mruPath -ErrorAction SilentlyContinue |
|
||||
Sort-Object PSChildName
|
||||
|
||||
if ($subKeys) {
|
||||
$totalFiles = 0
|
||||
$totalStored = 0
|
||||
|
||||
foreach ($subKey in $subKeys) {
|
||||
$extension = $subKey.PSChildName
|
||||
|
||||
$props = Get-ItemProperty -Path $subKey.PSPath -ErrorAction SilentlyContinue
|
||||
|
||||
# Get MRUListEx for ordering
|
||||
if ($props.MRUListEx) {
|
||||
$files = @()
|
||||
|
||||
for ($i = 0; $i -lt $props.MRUListEx.Length - 4; $i += 4) {
|
||||
$index = [BitConverter]::ToInt32($props.MRUListEx, $i)
|
||||
if ($index -eq -1) { break }
|
||||
|
||||
$propName = "$index"
|
||||
if ($props.$propName) {
|
||||
$fileName = Convert-PidlMRU -data $props.$propName
|
||||
if ($fileName) {
|
||||
$files += $fileName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$totalStored += $files.Count
|
||||
|
||||
# Only show if we found files
|
||||
if ($files.Count -gt 0) {
|
||||
if ($extension -eq "*") {
|
||||
Write-Host "`n--- All File Types ($($files.Count) total) ---" -ForegroundColor Yellow
|
||||
} else {
|
||||
Write-Host "`n--- .$extension Files ($($files.Count) total) ---" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
$count = 0
|
||||
$displayFiles = $files | Select-Object -First $MaxPerType
|
||||
|
||||
foreach ($file in $displayFiles) {
|
||||
$count++
|
||||
$totalFiles++
|
||||
Write-Host " $count. $file" -ForegroundColor Green
|
||||
}
|
||||
|
||||
if ($files.Count -gt $MaxPerType) {
|
||||
$remaining = $files.Count - $MaxPerType
|
||||
Write-Host " ... and $remaining more" -ForegroundColor Gray
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "`n=== Summary ===" -ForegroundColor Cyan
|
||||
Write-Host "Total stored: $totalStored files" -ForegroundColor Green
|
||||
Write-Host "Displayed: $totalFiles files" -ForegroundColor Green
|
||||
|
||||
if ($totalFiles -eq 0) {
|
||||
Write-Host "`nNo readable file paths found in MRU data" -ForegroundColor Gray
|
||||
Write-Host "The PIDL binary format may require more advanced parsing" -ForegroundColor Gray
|
||||
}
|
||||
} else {
|
||||
Write-Host "`nNo recent file history found" -ForegroundColor Gray
|
||||
}
|
||||
|
||||
} else {
|
||||
Write-Host "`nOpenSavePidlMRU registry key not found" -ForegroundColor Gray
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Host "Error: $_" -ForegroundColor Red
|
||||
}
|
||||
|
||||
Write-Host "`nNote: PIDL data parsing is limited. For complete analysis, use forensic tools like Registry Explorer" -ForegroundColor Cyan
|
||||
Reference in New Issue
Block a user