PS 5.1 parses a BOM-less .ps1 as the system ANSI codepage, garbling the Chinese / em-dash string literals in five scripts. verify-doc-facts.ps1 failed four checks under 5.1 (CI only ran it under pwsh). Add a BOM to the five files and a CI guard that fails any non-ASCII .ps1 lacking one.
147 lines
3.9 KiB
PowerShell
147 lines
3.9 KiB
PowerShell
#requires -Version 5
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$Package,
|
|
|
|
[string]$Process,
|
|
|
|
[string]$RemoteHost = '127.0.0.1:27042',
|
|
|
|
[string]$ScriptPath,
|
|
|
|
[switch]$Usb,
|
|
|
|
[switch]$Spawn,
|
|
|
|
[switch]$Pause,
|
|
|
|
[switch]$ListDevices,
|
|
|
|
[switch]$ListProcesses
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
[Console]::InputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
|
|
function Get-PythonScriptCandidates {
|
|
param([Parameter(Mandatory = $true)][string]$ExecutableName)
|
|
|
|
$roots = @(
|
|
(Join-Path $env:APPDATA 'Python'),
|
|
(Join-Path $env:LOCALAPPDATA 'Programs\Python')
|
|
)
|
|
|
|
$candidates = New-Object System.Collections.Generic.List[string]
|
|
foreach ($root in $roots) {
|
|
if (-not (Test-Path -LiteralPath $root)) {
|
|
continue
|
|
}
|
|
|
|
$matches = Get-ChildItem -LiteralPath $root -Directory -ErrorAction SilentlyContinue
|
|
foreach ($dir in $matches) {
|
|
$candidate = Join-Path $dir.FullName (Join-Path 'Scripts' $ExecutableName)
|
|
if (Test-Path -LiteralPath $candidate) {
|
|
$candidates.Add($candidate)
|
|
}
|
|
}
|
|
}
|
|
|
|
return $candidates
|
|
}
|
|
|
|
function Get-ToolPath {
|
|
param([Parameter(Mandatory = $true)][string]$Name)
|
|
|
|
$cmd = Get-Command $Name -ErrorAction SilentlyContinue
|
|
if ($cmd) {
|
|
return $cmd.Source
|
|
}
|
|
|
|
foreach ($candidate in Get-PythonScriptCandidates -ExecutableName ($Name + '.exe')) {
|
|
if (Test-Path -LiteralPath $candidate) {
|
|
return $candidate
|
|
}
|
|
}
|
|
|
|
# Attempt auto-bootstrap for frida tools
|
|
$bootstrapScript = Join-Path $PSScriptRoot '..\..\scripts\bootstrap-reverse.ps1'
|
|
if (($Name -in @('frida', 'frida-ps', 'frida-ls-devices')) -and (Test-Path -LiteralPath $bootstrapScript)) {
|
|
Write-Host "INFO: $Name not found, attempting auto-bootstrap (pip install frida-tools)..." -ForegroundColor Yellow
|
|
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $bootstrapScript -Capability @('frida') -SkipRefresh
|
|
$cmd = Get-Command $Name -ErrorAction SilentlyContinue
|
|
if ($cmd) {
|
|
Write-Host "INFO: $Name bootstrapped successfully." -ForegroundColor Green
|
|
return $cmd.Source
|
|
}
|
|
foreach ($candidate in Get-PythonScriptCandidates -ExecutableName ($Name + '.exe')) {
|
|
if (Test-Path -LiteralPath $candidate) {
|
|
return $candidate
|
|
}
|
|
}
|
|
}
|
|
|
|
throw "Missing required CLI tool: $Name — install with: pip install frida-tools"
|
|
}
|
|
|
|
$fridaLsDevices = Get-ToolPath -Name 'frida-ls-devices'
|
|
$fridaPs = Get-ToolPath -Name 'frida-ps'
|
|
$frida = Get-ToolPath -Name 'frida'
|
|
$python = Get-Command python -ErrorAction SilentlyContinue
|
|
|
|
if (-not $python) {
|
|
throw 'Missing required CLI tool: python'
|
|
}
|
|
|
|
$pythonExe = $python.Source
|
|
|
|
if ($ListDevices) {
|
|
& $pythonExe -c "import frida; [print(f'{d.id}`t{d.type}`t{d.name}') for d in frida.enumerate_devices()]"
|
|
exit $LASTEXITCODE
|
|
}
|
|
|
|
$target = if ($Package) { $Package } elseif ($Process) { $Process } else { '' }
|
|
if ([string]::IsNullOrWhiteSpace($target) -and -not $ListProcesses) {
|
|
throw 'Provide -Package or -Process, or use -ListProcesses.'
|
|
}
|
|
|
|
$deviceFlag = if ($Usb) { '-U' } else { '-H' }
|
|
|
|
if ($ListProcesses) {
|
|
$processArgs = @()
|
|
if ($Usb) {
|
|
$processArgs += '-U'
|
|
}
|
|
else {
|
|
$processArgs += @('-H', $RemoteHost)
|
|
}
|
|
& $fridaPs @processArgs
|
|
exit $LASTEXITCODE
|
|
}
|
|
|
|
if (-not (Test-Path -LiteralPath $ScriptPath)) {
|
|
throw "Frida script not found: $ScriptPath"
|
|
}
|
|
|
|
$fridaArgs = @($deviceFlag)
|
|
if (-not $Usb) {
|
|
$fridaArgs += $RemoteHost
|
|
}
|
|
if ($Spawn) {
|
|
$fridaArgs += '-f'
|
|
} else {
|
|
$fridaArgs += '-n'
|
|
}
|
|
$fridaArgs += $target
|
|
$fridaArgs += '-l'
|
|
$fridaArgs += $ScriptPath
|
|
if (-not $Pause) {
|
|
$fridaArgs += '--no-pause'
|
|
}
|
|
|
|
& $frida @fridaArgs
|
|
exit $LASTEXITCODE
|