From 81f23a6a54c9381c5318dc2a00cc76481117921f Mon Sep 17 00:00:00 2001 From: zhaoyilun Date: Fri, 10 Jul 2026 11:34:14 +0800 Subject: [PATCH] fix: package live probe recorder compatibility variants --- .../2026-07-10-live-probe-recorder.md | 16 ++++ scripts/package-live-probe-recorder.ps1 | 72 ++++++++++++++++-- scripts/verify-live-probe-recorder.ps1 | 76 +++++++++++++++++++ 3 files changed, 156 insertions(+), 8 deletions(-) create mode 100644 scripts/verify-live-probe-recorder.ps1 diff --git a/docs/source-discovery/2026-07-10-live-probe-recorder.md b/docs/source-discovery/2026-07-10-live-probe-recorder.md index 7d03a20..beeae64 100644 --- a/docs/source-discovery/2026-07-10-live-probe-recorder.md +++ b/docs/source-discovery/2026-07-10-live-probe-recorder.md @@ -29,6 +29,20 @@ Zip package: runs/live-probe-recorder-package.zip ``` +Compatibility layout: + +```text +ISphereLiveProbeRecorder.exe # top-level x86 build, use this first +variants/ISphereLiveProbeRecorder-x86.exe # same x86 fallback copy +variants/ISphereLiveProbeRecorder-anycpu.exe # AnyCPU fallback +variants/ISphereLiveProbeRecorder-x64.exe # x64 fallback +check-and-run.bat # prints environment and tries the top-level recorder +run-recorder.bat # runs the top-level recorder +run-x86-fallback.bat # runs the x86 fallback +``` + +The top-level executable is intentionally x86 because it can start on both 32-bit and 64-bit Windows and is more compatible with older enterprise desktop clients. + The package is generated by: ```powershell @@ -51,6 +65,8 @@ probe-output/isphere-live-probe-/ 8. Compress that generated folder and return it. +If Windows shows `System.BadImageFormatException`, delete the extracted folder, re-extract the latest zip package, and run `check-and-run.bat`. The previous package used an AnyCPU top-level executable; the current package uses x86 at the top level and keeps other builds under `variants/`. + ## What it records The recorder writes: diff --git a/scripts/package-live-probe-recorder.ps1 b/scripts/package-live-probe-recorder.ps1 index 03c884d..8ac5396 100644 --- a/scripts/package-live-probe-recorder.ps1 +++ b/scripts/package-live-probe-recorder.ps1 @@ -1,4 +1,4 @@ -param( +param( [string]$OutputDir = "runs/live-probe-recorder-package", [switch]$NoZip ) @@ -7,26 +7,54 @@ $ErrorActionPreference = "Stop" $repo = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..") $packageDir = Join-Path $repo $OutputDir -$buildDir = Join-Path $repo "runs/live-probe-recorder-build" -$helperExe = Join-Path $buildDir "ISphereWinHelper.exe" +$buildRoot = Join-Path $repo "runs/live-probe-recorder-build" +$buildX86Dir = Join-Path $repo "runs/live-probe-recorder-build-x86" +$buildX64Dir = Join-Path $repo "runs/live-probe-recorder-build-x64" +$helperExe = Join-Path $buildX86Dir "ISphereWinHelper.exe" $recorderExe = Join-Path $packageDir "ISphereLiveProbeRecorder.exe" +$variantsDir = Join-Path $packageDir "variants" +if (Test-Path -LiteralPath $packageDir) { + Remove-Item -LiteralPath $packageDir -Recurse -Force +} +if (Test-Path -LiteralPath "$packageDir.zip") { + Remove-Item -LiteralPath "$packageDir.zip" -Force +} New-Item -ItemType Directory -Force -Path $packageDir | Out-Null +New-Item -ItemType Directory -Force -Path $variantsDir | Out-Null -& powershell -NoProfile -ExecutionPolicy Bypass -File (Join-Path $repo "scripts\build-win-helper.ps1") -OutputDir "runs/live-probe-recorder-build" +& powershell -NoProfile -ExecutionPolicy Bypass -File (Join-Path $repo "scripts\build-win-helper.ps1") -OutputDir "runs/live-probe-recorder-build-x86" -Platform x86 if ($LASTEXITCODE -ne 0) { - throw "build-win-helper.ps1 failed with exit code $LASTEXITCODE" + throw "build-win-helper.ps1 x86 failed with exit code $LASTEXITCODE" } if (-not (Test-Path -LiteralPath $helperExe)) { - throw "built helper not found: $helperExe" + throw "built x86 helper not found: $helperExe" } Copy-Item -LiteralPath $helperExe -Destination $recorderExe -Force +Copy-Item -LiteralPath $helperExe -Destination (Join-Path $variantsDir "ISphereLiveProbeRecorder-x86.exe") -Force + +& powershell -NoProfile -ExecutionPolicy Bypass -File (Join-Path $repo "scripts\build-win-helper.ps1") -OutputDir "runs/live-probe-recorder-build" -Platform anycpu +if ($LASTEXITCODE -ne 0) { + throw "build-win-helper.ps1 anycpu failed with exit code $LASTEXITCODE" +} +Copy-Item -LiteralPath (Join-Path $buildRoot "ISphereWinHelper.exe") -Destination (Join-Path $variantsDir "ISphereLiveProbeRecorder-anycpu.exe") -Force + +& powershell -NoProfile -ExecutionPolicy Bypass -File (Join-Path $repo "scripts\build-win-helper.ps1") -OutputDir "runs/live-probe-recorder-build-x64" -Platform x64 +if ($LASTEXITCODE -ne 0) { + throw "build-win-helper.ps1 x64 failed with exit code $LASTEXITCODE" +} +Copy-Item -LiteralPath (Join-Path $buildX64Dir "ISphereWinHelper.exe") -Destination (Join-Path $variantsDir "ISphereLiveProbeRecorder-x64.exe") -Force @" ISphereLiveProbeRecorder +默认说明: +- 顶层 ISphereLiveProbeRecorder.exe 是 x86 版,兼容性最好,建议优先用它。 +- variants 目录里保留 anycpu/x86/x64 备用版本。 +- 如果现场遇到 BadImageFormatException,请先确认解压后的 exe 大小和 hash,再运行 variants\ISphereLiveProbeRecorder-x86.exe。 + 使用方式: 1. 把本目录复制到可以正常登录 iSphere/IMPlatformClient 的电脑。 2. 先手工打开并登录 iSphere/IMPlatformClient。 @@ -56,7 +84,7 @@ ISphereLiveProbeRecorder - 点击或输入; - 注入或 hook; - 修改客户端文件或数据。 -"@ | Set-Content -LiteralPath (Join-Path $packageDir "README-使用说明.txt") -Encoding UTF8 +"@ | Set-Content -LiteralPath (Join-Path $packageDir "README.txt") -Encoding UTF8 @" @echo off @@ -64,7 +92,34 @@ setlocal cd /d "%~dp0" ISphereLiveProbeRecorder.exe pause -"@ | Set-Content -LiteralPath (Join-Path $packageDir "双击运行-采集.bat") -Encoding ASCII +"@ | Set-Content -LiteralPath (Join-Path $packageDir "run-recorder.bat") -Encoding ASCII + +@" +@echo off +setlocal +cd /d "%~dp0" +variants\ISphereLiveProbeRecorder-x86.exe +pause +"@ | Set-Content -LiteralPath (Join-Path $packageDir "run-x86-fallback.bat") -Encoding ASCII + +@" +@echo off +setlocal +cd /d "%~dp0" +echo === Windows version === +ver +echo. +echo === File sizes === +dir ISphereLiveProbeRecorder.exe variants\ISphereLiveProbeRecorder-*.exe +echo. +echo === .NET Framework v4 runtime === +reg query "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" /v Release +echo. +echo === Try top-level recorder === +ISphereLiveProbeRecorder.exe --no-pause +echo exit code: %ERRORLEVEL% +pause +"@ | Set-Content -LiteralPath (Join-Path $packageDir "check-and-run.bat") -Encoding ASCII $zipPath = "$packageDir.zip" if (-not $NoZip) { @@ -78,5 +133,6 @@ if (-not $NoZip) { ok = $true package_dir = (Resolve-Path -LiteralPath $packageDir).Path recorder_exe = (Resolve-Path -LiteralPath $recorderExe).Path + recorder_platform = "x86" zip = if (Test-Path -LiteralPath $zipPath) { (Resolve-Path -LiteralPath $zipPath).Path } else { $null } } | ConvertTo-Json -Depth 4 -Compress diff --git a/scripts/verify-live-probe-recorder.ps1 b/scripts/verify-live-probe-recorder.ps1 new file mode 100644 index 0000000..9704445 --- /dev/null +++ b/scripts/verify-live-probe-recorder.ps1 @@ -0,0 +1,76 @@ +param( + [string]$PackageDir = "runs/live-probe-recorder-package" +) + +$ErrorActionPreference = "Stop" + +$repo = Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..") +$packagePath = Join-Path $repo $PackageDir +$verifyRoot = Join-Path $repo "runs/live-probe-recorder-verify-output" + +if (-not (Test-Path -LiteralPath $packagePath)) { + throw "package directory not found: $packagePath" +} + +$executables = @( + Join-Path $packagePath "ISphereLiveProbeRecorder.exe" + Join-Path $packagePath "variants\ISphereLiveProbeRecorder-x86.exe" + Join-Path $packagePath "variants\ISphereLiveProbeRecorder-anycpu.exe" + Join-Path $packagePath "variants\ISphereLiveProbeRecorder-x64.exe" +) + +$results = @() +foreach ($exe in $executables) { + if (-not (Test-Path -LiteralPath $exe)) { + throw "recorder executable missing: $exe" + } + + $variantName = [System.IO.Path]::GetFileNameWithoutExtension($exe) + $safeVariantName = $variantName -replace '[^A-Za-z0-9_.-]', '_' + $probeRoot = Join-Path $verifyRoot $safeVariantName + if (Test-Path -LiteralPath $probeRoot) { + Remove-Item -LiteralPath $probeRoot -Recurse -Force + } + New-Item -ItemType Directory -Force -Path $probeRoot | Out-Null + + $output = & $exe --out $probeRoot --no-pause 2>&1 + $exit = $LASTEXITCODE + if ($exit -ne 0) { + throw "recorder failed: $exe exit=$exit output=$($output -join "`n")" + } + + $created = Get-ChildItem -LiteralPath $probeRoot -Directory | Sort-Object LastWriteTime -Descending | Select-Object -First 1 -ExpandProperty FullName + if (-not $created) { + throw "recorder did not create a probe output directory: $exe" + } + + foreach ($required in @( + "manifest.json", + "probe_client_runtime.json", + "process_details.json", + "network_inventory.json", + "filesystem_inventory.json", + "scan_windows.json", + "feasibility_summary.json" + )) { + $path = Join-Path $created $required + if (-not (Test-Path -LiteralPath $path)) { + throw "required output missing for ${exe}: $required" + } + } + + $results += [ordered]@{ + exe = (Resolve-Path -LiteralPath $exe).Path + sha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $exe).Hash + length = (Get-Item -LiteralPath $exe).Length + output_dir = $created + ok = $true + } +} + +[ordered]@{ + ok = $true + package_dir = (Resolve-Path -LiteralPath $packagePath).Path + verify_output_dir = (Resolve-Path -LiteralPath $verifyRoot).Path + results = $results +} | ConvertTo-Json -Depth 6 -Compress