142 lines
5.5 KiB
PowerShell
142 lines
5.5 KiB
PowerShell
#Requires -Version 5.1
|
|
# reverse-skill smoke entrypoint: verify + script parse + master-route sample matrix.
|
|
# Usage:
|
|
# powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/smoke.ps1
|
|
# powershell -File skills/scripts/smoke.ps1 -LogDir C:\path\to\logs
|
|
param(
|
|
[string] $LogDir = '',
|
|
[string] $PackageRoot = ''
|
|
)
|
|
$ErrorActionPreference = 'Continue'
|
|
|
|
$scriptDir = $PSScriptRoot
|
|
if (-not $scriptDir) { $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path }
|
|
$skillsRoot = Split-Path -Parent $scriptDir
|
|
if (-not $PackageRoot) { $PackageRoot = Split-Path -Parent $skillsRoot }
|
|
|
|
if ([string]::IsNullOrWhiteSpace($LogDir)) {
|
|
$stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|
$tmpBase = if ($env:TEMP) { $env:TEMP } else { [System.IO.Path]::GetTempPath() }
|
|
$LogDir = Join-Path $tmpBase ("rs-smoke-{0}" -f $stamp)
|
|
}
|
|
New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
|
|
|
|
$fail = New-Object System.Collections.Generic.List[string]
|
|
function Ok([string] $m) { Write-Host ("[OK] {0}" -f $m) -ForegroundColor Green }
|
|
function Bad([string] $m) {
|
|
Write-Host ("[FAIL] {0}" -f $m) -ForegroundColor Red
|
|
[void]$fail.Add($m)
|
|
}
|
|
|
|
Write-Host ("=== reverse-skill smoke | LogDir={0} ===" -f $LogDir)
|
|
|
|
# --- 1) routing coherence ---
|
|
$verify = Join-Path $scriptDir 'verify-routing-coherence.ps1'
|
|
if (-not (Test-Path -LiteralPath $verify)) {
|
|
Bad 'verify-routing-coherence.ps1 missing'
|
|
$verifyExit = 1
|
|
} else {
|
|
$vLog = Join-Path $LogDir '01-verify.txt'
|
|
& powershell -NoProfile -ExecutionPolicy Bypass -File $verify 2>&1 | Tee-Object -FilePath $vLog | Out-Null
|
|
$verifyExit = $LASTEXITCODE
|
|
if ($verifyExit -eq 0) { Ok 'verify-routing-coherence exit 0' } else { Bad ("verify-routing-coherence exit {0}" -f $verifyExit) }
|
|
}
|
|
|
|
# --- 2) parse key scripts ---
|
|
$scripts = @(
|
|
'verify-routing-coherence.ps1',
|
|
'master-route.ps1',
|
|
'case-init.ps1',
|
|
'lib\WorkRoot.ps1',
|
|
'bootstrap-reverse.ps1',
|
|
'refresh-tool-index.ps1',
|
|
'smoke.ps1',
|
|
'append-evidence.ps1',
|
|
'case-guard.ps1',
|
|
'test-routing.ps1',
|
|
'extract-summaries.ps1'
|
|
)
|
|
$parseOk = 0
|
|
$parseFail = 0
|
|
$parseLog = New-Object System.Collections.Generic.List[string]
|
|
foreach ($name in $scripts) {
|
|
$p = Join-Path $scriptDir $name
|
|
if (-not (Test-Path -LiteralPath $p)) {
|
|
# append-evidence is required for P0; others should exist
|
|
if ($name -eq 'append-evidence.ps1' -or $name -eq 'smoke.ps1') {
|
|
Bad ("script missing: {0}" -f $name)
|
|
$parseFail++
|
|
[void]$parseLog.Add("MISSING $name")
|
|
}
|
|
continue
|
|
}
|
|
$errs = $null
|
|
$tokens = $null
|
|
$null = [System.Management.Automation.Language.Parser]::ParseFile($p, [ref]$tokens, [ref]$errs)
|
|
if ($errs -and $errs.Count -gt 0) {
|
|
Bad ("parse fail {0}: {1}" -f $name, $errs[0].Message)
|
|
$parseFail++
|
|
[void]$parseLog.Add("FAIL $name $($errs[0].Message)")
|
|
} else {
|
|
Ok ("parse {0}" -f $name)
|
|
$parseOk++
|
|
[void]$parseLog.Add("OK $name")
|
|
}
|
|
}
|
|
$parseLog -join [Environment]::NewLine | Set-Content (Join-Path $LogDir '02-parse.txt') -Encoding UTF8
|
|
|
|
# --- 3) master-route sample matrix ---
|
|
$mr = Join-Path $scriptDir 'master-route.ps1'
|
|
$cases = @(
|
|
@{ Name = 'apk'; Hint = 'decompile APK with jadx apktool smali'; Expect = 'apk-reverse' },
|
|
@{ Name = 'js'; Hint = 'js reverse frontend sign jshook encrypted param'; Expect = 'js-reverse' },
|
|
@{ Name = 'ida'; Hint = 'IDA decompile PE binary disassemble'; Expect = 'ida-reverse' },
|
|
@{ Name = 'pentest'; Hint = 'nmap nuclei sqlmap ffuf pentest bug bounty'; Expect = 'pentest-tools' },
|
|
@{ Name = 'llm'; Hint = 'LLM prompt inject jailbreak agent security garak'; Expect = 'llm-security' },
|
|
@{ Name = 'zh-apk'; Hint = '安卓 APK 加固 反编译'; Expect = 'apk-reverse' },
|
|
@{ Name = 'zh-pentest'; Hint = '渗透测试 端口扫描 SQL注入'; Expect = 'pentest-tools' },
|
|
@{ Name = 'zh-js'; Hint = '前端签名 JS逆向 加密参数'; Expect = 'js-reverse' },
|
|
@{ Name = 'evidence'; Hint = 'case review evidence chain traceability'; Expect = 'case-review' }
|
|
)
|
|
$routeOk = 0
|
|
$routeFail = 0
|
|
$routeSummary = New-Object System.Collections.Generic.List[string]
|
|
if (-not (Test-Path -LiteralPath $mr)) {
|
|
Bad 'master-route.ps1 missing'
|
|
} else {
|
|
foreach ($c in $cases) {
|
|
$outFile = Join-Path $LogDir ("route-{0}.txt" -f $c.Name)
|
|
$raw = & powershell -NoProfile -ExecutionPolicy Bypass -File $mr -Hint $c.Hint 2>&1 | Out-String
|
|
$raw | Set-Content -Path $outFile -Encoding UTF8
|
|
if ($raw -match [regex]::Escape($c.Expect)) {
|
|
Ok ("route {0} -> {1}" -f $c.Name, $c.Expect)
|
|
$routeOk++
|
|
[void]$routeSummary.Add("PASS $($c.Name)")
|
|
} else {
|
|
Bad ("route {0} expect {1}" -f $c.Name, $c.Expect)
|
|
$routeFail++
|
|
[void]$routeSummary.Add("FAIL $($c.Name)")
|
|
}
|
|
}
|
|
}
|
|
$routeSummary -join [Environment]::NewLine | Set-Content (Join-Path $LogDir '03-route-summary.txt') -Encoding UTF8
|
|
|
|
# --- summary ---
|
|
$summary = @(
|
|
"VERIFY_EXIT=$verifyExit",
|
|
"PARSE ok=$parseOk fail=$parseFail",
|
|
"ROUTE ok=$routeOk fail=$routeFail / $($cases.Count)",
|
|
"FAIL_COUNT=$($fail.Count)",
|
|
"LogDir=$LogDir"
|
|
)
|
|
$summary -join [Environment]::NewLine | Set-Content (Join-Path $LogDir 'SUMMARY.txt') -Encoding UTF8
|
|
Write-Host '=== SMOKE SUMMARY ==='
|
|
$summary | ForEach-Object { Write-Host $_ }
|
|
if ($fail.Count -gt 0) {
|
|
$fail | Set-Content (Join-Path $LogDir 'failures.txt') -Encoding UTF8
|
|
Write-Host 'OVERALL: FAIL' -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
Write-Host 'OVERALL: ALL PASS' -ForegroundColor Green
|
|
exit 0
|