tools/Invoke-FotonEasy.ps1
|
# Invoke-FotonEasy.ps1 # Menu/wrapper so collection and analysis do not require memorizing cmdlets. # Collect still uses dist\Foton-Collect.ps1 (one file on the endpoint). [CmdletBinding()] param( [Parameter(Position = 0)][string]$Command = 'help', [Parameter(Position = 1)][string]$Target, [Parameter(ValueFromRemainingArguments = $true)][string[]]$Rest ) $ErrorActionPreference = 'Stop' $repoRoot = Split-Path $PSScriptRoot -Parent $collect = Join-Path $repoRoot 'dist\Foton-Collect.ps1' $psd1 = Join-Path $repoRoot 'Foton.psd1' $banner = Join-Path $repoRoot 'src\Private\Core\Write-FotonBanner.ps1' function Show-FotonEasyHelp { Write-Host ' Simple commands' -ForegroundColor Cyan Write-Host '' Write-Host ' Collect on a Windows PC (copy ONE file, no module install):' Write-Host ' 1. On a lab box: .\build\Build-Standalone.ps1' Write-Host ' 2. Copy dist\Foton-Collect_v*_schema*.ps1 (or Foton-Collect.ps1) to the target' Write-Host ' 3. Double-click it or: powershell -File Foton-Collect.ps1' Write-Host '' Write-Host ' Baseline (known-state snapshot, different file):' Write-Host ' .\build\Build-BaselineStandalone.ps1' Write-Host ' Copy dist\Foton-Baseline_v*_schema*.ps1 (or Foton-Baseline.ps1) to the target, then run it.' Write-Host ' Open Foton_Baseline.html inside FotonBaseline_HOSTNAME_...Z' Write-Host '' Write-Host ' On this repo (workstation). Extract a ZIP first, then parse, compose, analyze (last):' Write-Host ' Foton.cmd parse D:\Cases\Foton_HOSTNAME_...Z' Write-Host ' Foton.cmd compose D:\Cases\Foton_HOSTNAME_...Z' Write-Host ' Foton.cmd analyze D:\Cases\Foton_HOSTNAME_...Z' Write-Host ' Foton.cmd ioc D:\Cases\Foton_HOSTNAME_...Z D:\intel\iocs.txt' Write-Host ' Foton.cmd baseline D:\Baselines' Write-Host ' Foton.cmd baseline D:\Baselines\this-pc.json' Write-Host ' Foton.cmd compare D:\Baselines\day0.json D:\Baselines\day1.json' Write-Host ' Foton.cmd tools Hayabusa (one-time workstation setup; does not change PATH)' Write-Host ' Foton.cmd tools EZTools C:\Tools\EZTools (register an existing install; also Chainsaw <dir>)' Write-Host ' Foton.cmd tools (list pinned and registered tools)' Write-Host ' Foton.cmd carve D:\blob.bin' Write-Host ' Foton.cmd collect D:\Cases (runs dist\Foton-Collect.ps1 if built)' Write-Host '' Write-Host ' Open Foton_Report.html after analyze. Open analysis\Foton_Parse.html after parse.' Write-Host ' Findings are observations, not conclusions. Full command list: docs\USAGE.md' Write-Host '' } $cmd = $Command.ToLower() if ($cmd -notin @('collect', 'baseline', 'compare') -and (Test-Path -LiteralPath $banner)) { # The banner reads the version from Foton.psd1 under FotonModuleRoot; without it, # dot-sourcing outside the module fell back to a stale hard-coded version. $script:FotonModuleRoot = $repoRoot . $banner Write-FotonBanner -Kind 'Easy' } if ($cmd -in @('help', '-h', '/h', '/?', '')) { Show-FotonEasyHelp return } if ($cmd -eq 'collect') { if (-not (Test-Path -LiteralPath $collect)) { Write-Host ' dist\Foton-Collect.ps1 is missing. Run .\build\Build-Standalone.ps1 first.' -ForegroundColor Yellow exit 2 } $out = $Target if (-not $out) { $out = Join-Path $env:USERPROFILE 'Desktop' } & $collect -OutputPath $out -NoZip @Rest return } Import-Module $psd1 -Force switch ($cmd) { 'analyze' { if (-not $Target) { throw 'Usage: Foton.cmd analyze <case-folder-or-zip>' } Get-FotonPackage -Path $Target | Out-Null Invoke-FotonAnalysis $reportPath = New-FotonReport Write-Host " Report: $reportPath" -ForegroundColor Green } 'baseline' { if (-not $Target) { throw 'Usage: Foton.cmd baseline <output-folder-or.json>' } if ($Target -like '*.json') { New-FotonBaseline -Path $Target } else { New-FotonBaseline -OutputPath $Target } } 'compare' { $b = $Rest | Select-Object -First 1 if (-not $Target -or -not $b) { throw 'Usage: Foton.cmd compare <day0.json-or-folder> <day1.json-or-folder>' } Compare-FotonBaseline -ReferencePath $Target -DifferencePath $b | Format-Table -AutoSize Write-Host ' Open Foton_BaselineCompare.html next to the second baseline JSON.' -ForegroundColor Green } 'parse' { if (-not $Target) { throw 'Usage: Foton.cmd parse <case-folder-or-zip | file.pf | file.lnk | jumplist | Amcache.hve>' } $rows = @(Invoke-FotonParse -Path $Target) if ($rows.Count -eq 0) { Write-Host ' Nothing to show. Parse needs copied .pf/.lnk inside the package (08_Filesystem\prefetch), not a listing CSV.' -ForegroundColor Yellow return } $rows | Select-Object SourcePath, Format, Supported, ExecutableName, LocalBasePath, Note | Format-Table -AutoSize -Wrap Write-Host ' HTML: analysis\Foton_Parse.html (folder) or <zip>_Parse.html (ZIP). Not findings.csv.' -ForegroundColor Green Write-Host ' CSV: analysis\parsed_records.csv. Win10+ Prefetch is often MAM-compressed (file seen, name not decoded). Amcache LinkDate is a stored string, not converted to UTC.' -ForegroundColor DarkGray } 'compose' { if (-not $Target) { throw 'Usage: Foton.cmd compose <case-folder-or-zip>' } # Invoke-FotonExternalParse opens the package itself; loading it here too # just prints the "Loaded package" line twice. $rows = @(Invoke-FotonExternalParse -PackagePath $Target) $rows | Select-Object Tool, Version, Status, DestRelative, Note | Format-Table -AutoSize -Wrap Write-Host ' Inventory: analysis\external\external_parse_inventory.csv. Native Invoke-FotonParse if tools are missing.' -ForegroundColor Green Write-Host ' Missing Hayabusa: Foton.cmd tools Hayabusa. Existing EZ Tools / Chainsaw folder: Foton.cmd tools EZTools <dir>' -ForegroundColor DarkGray } 'tools' { # One-time workstation setup. Never runs inside compose (offline invariant). if (-not $Target -or $Target -in @('list', '-list', '/list')) { Install-FotonTool -List | Format-Table -AutoSize -Wrap | Out-Host return } $archive = $null $existing = $null if ($Rest -and $Rest.Count -ge 2 -and $Rest[0] -eq '-ArchivePath') { $archive = $Rest[1] } elseif ($Rest -and $Rest.Count -ge 1 -and (Test-Path -LiteralPath $Rest[0])) { # A .zip is a release archive to install; a folder or .exe is an existing install to register. if ([IO.Path]::GetExtension($Rest[0]) -eq '.zip') { $archive = $Rest[0] } else { $existing = $Rest[0] } } if ($existing) { Install-FotonTool -Name $Target -Path $existing -Force | Out-Null } elseif ($archive) { Install-FotonTool -Name $Target -ArchivePath $archive -Force } else { Install-FotonTool -Name $Target } } 'ioc' { $iocFile = $Rest | Select-Object -First 1 if (-not $Target -or -not $iocFile) { throw 'Usage: Foton.cmd ioc <case-folder> <ioc-file>' } Invoke-FotonIocMatch -Path $Target -IocPath $iocFile | Format-Table -AutoSize } 'carve' { if (-not $Target) { throw 'Usage: Foton.cmd carve <blob>' } Invoke-FotonCarve -Path $Target | Format-Table -AutoSize } default { Show-FotonEasyHelp throw "Unknown command: $Command" } } |