Files
reverse-engineering-anything/scripts/verify/managed/conformance.mjs
T
morluto c0dd084376 refactor(verify): give seven verifier directories' fixture roots to VerifierFixture (#11055)
* refactor(verify): give the android, electron, firmware, ghidra-seed, harmony, inspector and managed verifiers' roots to VerifierFixture

Each root is removed only after the MCP clients, transports, owned processes
and file handles that may still use it confirm cleanup; a failed cleanup
retains and names the root. The verifier-fixture-root baseline shrinks from
90 files / 95 sites to 80 / 85.

* fix(verify): keep nested Electron and inspector children owned by the fixture, and plain roots where Windows creates directories

The Electron cancellation CLI and application, and each inspector target,
now register their stop with the fixture (onceConfirmed keeps the early stop),
so the root is removed only after they confirm. The android and inspector
verifiers keep a plain directory as before: tools create directories beneath
the root, which a private root blocks on Windows.
2026-11-15 19:33:03 +08:00

416 lines
13 KiB
JavaScript

import assert from "node:assert/strict";
import { inspectManagedArtifactBytes } from "../../../dist/dotnet/ManagedArtifactInspector.js";
import { inspectManagedMembersBytes } from "../../../dist/dotnet/ManagedMemberInspector.js";
import { inspectManagedNativeBoundariesBytes } from "../../../dist/dotnet/ManagedNativeBoundaryInspector.js";
import { compareManagedMemberPaths } from "../../../dist/application/managed/ManagedMemberComparisonService.js";
import { executeManagedNativeBoundaries } from "../../../dist/application/managed/ManagedNativeVerificationService.js";
import { importManagedReconstructionEvidence } from "../../../dist/application/managed/ManagedReconstructionService.js";
import { projectManagedApplicationGraphEvidence } from "../../../dist/application/managed/ManagedApplicationGraphService.js";
import { traceApplicationFeatureEvidence } from "../../../dist/application/javascript/JavaScriptApplicationWorkflowService.js";
import { MANAGED_STATIC_PROVIDER } from "../../../dist/domain/investigationProviders.js";
import { createEvidence } from "../../../dist/domain/evidence.js";
import { functionDossier } from "../../fixtures/managed/function-dossier.mjs";
import {
alternateMvid,
buildNativePeFixture,
} from "../../fixtures/managed/pe.mjs";
import { createManagedConformanceSupport } from "./support.mjs";
import { defaultIlBody } from "./config.mjs";
import { createManagedCompletionReport } from "./completion-report.mjs";
import {
completeVerifierRun,
createVerifierRun,
} from "../../lib/verifier-run.mjs";
import {
VerifierFixture,
withVerifierFixture,
} from "../../lib/verifier-fixture.mjs";
const verifierRun = createVerifierRun();
const workspaceFixture = await VerifierFixture.open({
prefix: "rea-managed-conformance-",
});
const workspace = workspaceFixture.path;
let completionReportInput;
let finalReport;
const {
fixture,
fixtureBytes,
runManagedAppManifestSelfTest,
runOptionalManagedAppManifest,
runOptionalIlspyOracle,
sha256,
} = createManagedConformanceSupport({
workspace,
defaultIlBody,
});
await withVerifierFixture(workspaceFixture, async () => {
const modern = await fixture("modern-anycpu.exe", {
references: ["System.Runtime"],
resourceData: Buffer.from("source-owned managed resource"),
});
const modernArtifact = inspectManagedArtifactBytes(
modern.bytes,
modern.target,
);
assert.equal(modernArtifact.classification.status, "managed");
assert.equal(modernArtifact.classification.runtime_family, "modern-dotnet");
assert.equal(modernArtifact.classification.managed_architecture, "anycpu");
assert.deepEqual(modernArtifact.target_frameworks, [
".NETCoreApp,Version=v8.0",
]);
assert.equal(
modernArtifact.resources[0]?.data_sha256,
sha256(Buffer.from("source-owned managed resource")),
);
const framework = await fixture("framework-x86-pinvoke.exe", {
cliFlags: 0x0000_0003,
targetFramework: ".NETFramework,Version=v4.8",
pinvoke: {
moduleName: "user32.dll",
importName: "MessageBoxW",
mappingFlags: 0x0345,
},
});
const frameworkArtifact = inspectManagedArtifactBytes(
framework.bytes,
framework.target,
);
assert.equal(
frameworkArtifact.classification.runtime_family,
"dotnet-framework",
);
assert.equal(frameworkArtifact.classification.managed_architecture, "x86");
const frameworkBoundaries = inspectManagedNativeBoundariesBytes(
framework.bytes,
framework.target,
);
assert.equal(frameworkBoundaries.pinvoke_imports.length, 1);
assert.equal(
frameworkBoundaries.pinvoke_imports[0]?.verification,
"managed-declaration-only",
);
assert.equal(frameworkBoundaries.pinvoke_imports[0]?.char_set, "unicode");
assert.equal(
frameworkBoundaries.pinvoke_imports[0]?.call_convention,
"stdcall",
);
const frameworkMembers = inspectManagedMembersBytes(
framework.bytes,
framework.target,
);
const frameworkArtifactEvidence = createEvidence(
framework.target,
MANAGED_STATIC_PROVIDER,
{
operation: "inspect_managed_artifact",
parameters: {},
result: frameworkArtifact,
rawResult: null,
limitations: frameworkArtifact.limitations,
locations: [{ kind: "artifact-path", path: framework.target.path }],
},
);
const frameworkMemberEvidence = createEvidence(
framework.target,
MANAGED_STATIC_PROVIDER,
{
operation: "inspect_managed_members",
parameters: {},
result: frameworkMembers,
rawResult: null,
limitations: frameworkMembers.limitations,
locations: [{ kind: "artifact-path", path: framework.target.path }],
},
);
const frameworkBoundaryEvidence = createEvidence(
framework.target,
MANAGED_STATIC_PROVIDER,
{
operation: "inspect_managed_native_boundaries",
parameters: {},
result: frameworkBoundaries,
rawResult: null,
limitations: frameworkBoundaries.limitations,
locations: [{ kind: "artifact-path", path: framework.target.path }],
},
);
const nativeFunctionTarget = {
path: "/system/user32.dll",
sha256: "9".repeat(64),
format: "pe",
architecture: "x86",
};
const nativeFunctionEvidence = createEvidence(
nativeFunctionTarget,
{
id: "ghidra",
name: "Ghidra",
version: "12.1.4",
},
{
operation: "analyze_function",
parameters: { procedure: "MessageBoxW" },
result: functionDossier("MessageBoxW"),
rawResult: null,
limitations: [],
locations: [{ kind: "address", address: "0x401000" }],
},
);
const nativeVerification = executeManagedNativeBoundaries({
managed_boundaries: frameworkBoundaryEvidence,
native_observations: [nativeFunctionEvidence],
});
assert.equal(nativeVerification.ok, true);
assert.equal(
nativeVerification.value.evidence.normalized_result.summary.verified,
1,
);
const applicationGraph = projectManagedApplicationGraphEvidence({
managed_artifact: frameworkArtifactEvidence,
managed_members: frameworkMemberEvidence,
managed_native_boundaries: frameworkBoundaryEvidence,
});
assert.equal(applicationGraph.ok, true);
assert.equal(
applicationGraph.value.normalized_result.summary.pinvoke_imports,
1,
);
assert.equal(
applicationGraph.value.normalized_result.graph.nodes.some(
({ kind }) => kind === "managed-pinvoke-import",
),
true,
);
const applicationTrace = traceApplicationFeatureEvidence({
application: applicationGraph.value,
native_observations: [],
seed: {
kind: "string",
value: "MessageBoxW",
match: "exact",
case_sensitive: true,
},
direction: "incoming",
});
assert.equal(applicationTrace.ok, true);
assert.equal(applicationTrace.value.result.summary.matched_seeds, 1);
const readyToRun = await fixture("r2r-x64.exe", {
machine: 0x8664,
readyToRun: true,
methods: [
{
name: "NativeBody",
implFlags: 0x0001,
body: Buffer.from([0x2a]),
},
],
});
const r2rArtifact = inspectManagedArtifactBytes(
readyToRun.bytes,
readyToRun.target,
);
assert.equal(r2rArtifact.pe.architecture, "x86_64");
assert.equal(
r2rArtifact.classification.implementation,
"cil-and-ready-to-run",
);
const r2rBoundaries = inspectManagedNativeBoundariesBytes(
readyToRun.bytes,
readyToRun.target,
);
assert.equal(r2rBoundaries.summary.ready_to_run, true);
assert.equal(r2rBoundaries.native_implementations[0]?.code_type, "native");
assert.equal(
r2rBoundaries.native_implementations[0]?.boundary_kind,
"native-body",
);
const obfuscated = await fixture("obfuscated.exe", {
typeName: "ꙮType",
methodName: "λ⛧",
fieldName: "字段",
});
const obfuscatedMembers = inspectManagedMembersBytes(
obfuscated.bytes,
obfuscated.target,
);
assert.equal(obfuscatedMembers.types[0]?.full_name, "Fixture.ꙮType");
assert.equal(obfuscatedMembers.methods[0]?.name, "λ⛧");
assert.equal(obfuscatedMembers.fields[0]?.name, "字段");
const reconstructionMethod = obfuscatedMembers.methods[0];
assert.ok(reconstructionMethod);
const obfuscatedMembersEvidence = createEvidence(
undefined,
MANAGED_STATIC_PROVIDER,
{
operation: "inspect_managed_members",
parameters: { path: obfuscated.path },
result: obfuscatedMembers,
rawResult: null,
limitations: obfuscatedMembers.limitations,
},
);
const reconstructionImport = importManagedReconstructionEvidence({
static_members: obfuscatedMembersEvidence,
decompiler: {
name: "ilspycmd",
version: "9.1.0.7988",
family: "ilspy",
executable_sha256: null,
options: ["--type", "Fixture.ꙮType"],
},
methods: [
{
token: reconstructionMethod.token,
signature_sha256: reconstructionMethod.signature.raw_sha256,
normalized_il_sha256: reconstructionMethod.body.normalized_il_sha256,
reconstruction: {
kind: "decompiled-csharp",
language: "csharp",
text: "internal static void λ⛧() { /* synthetic fixture */ }",
},
},
],
notes: ["source-owned synthetic decompiler reconstruction"],
});
assert.equal(reconstructionImport.ok, true);
assert.equal(
reconstructionImport.value.normalized_result.methods[0].validation
.canonical_observation,
false,
);
assert.equal(reconstructionImport.value.confidence, "inferred");
const left = await fixture("token-drift-left.exe", {
methodName: "StableSemanticSlice",
});
const right = await fixture("token-drift-right.exe", {
mvid: alternateMvid,
methods: [
{ name: "InsertedHelper", body: Buffer.from([0x2a]) },
{ name: "RenamedSemanticSlice", body: defaultIlBody },
],
});
const comparison = await compareManagedMemberPaths({
leftPath: left.path,
rightPath: right.path,
});
assert.equal(comparison.ok, true);
const comparisonResult = comparison.value.normalized_result;
assert.equal(
comparisonResult.algorithm.name_matching,
"exact-signature-fallback",
);
assert.equal(comparisonResult.matching.exact_il_signature, 1);
assert.equal(
comparisonResult.methods.some(
({ left, right, match }) =>
left.token === "0x06000001" &&
right?.token === "0x06000002" &&
match.basis === "exact-il-signature",
),
true,
);
const unavailableBodyLeft = await fixture("partial-body-left.exe", {
methods: [{ name: "PartialBodyTarget", body: Buffer.from([0xff]) }],
});
const unavailableBodyRight = await fixture("partial-body-right.exe", {
methods: [{ name: "PartialBodyTarget", body: defaultIlBody }],
});
const partialBodyComparison = await compareManagedMemberPaths({
leftPath: unavailableBodyLeft.path,
rightPath: unavailableBodyRight.path,
});
assert.equal(partialBodyComparison.ok, true);
const partialBodyMethod =
partialBodyComparison.value.normalized_result.methods.find(
({ left }) => left?.name === "PartialBodyTarget",
);
assert.equal(partialBodyMethod?.status, "unknown");
assert.equal(partialBodyMethod?.match.basis, "exact-signature");
assert.equal(partialBodyMethod?.dimensions.includes("body-coverage"), true);
const nativeOnly = await fixtureBytes(
"native-only.exe",
buildNativePeFixture(),
);
const nativeResult = inspectManagedArtifactBytes(
nativeOnly.bytes,
nativeOnly.target,
);
assert.equal(nativeResult.classification.status, "not-managed");
const malformed = await fixture("malformed-metadata.exe", {
corruptMetadataSignature: true,
});
const malformedResult = inspectManagedArtifactBytes(
malformed.bytes,
malformed.target,
);
assert.equal(malformedResult.classification.status, "malformed");
const manifestSelfTest = await runManagedAppManifestSelfTest();
const operatorManifest = await runOptionalManagedAppManifest();
const ilspyOracle = await runOptionalIlspyOracle();
completionReportInput = {
modern,
framework,
nativeFunctionTarget,
readyToRun,
obfuscated,
left,
right,
nativeOnly,
malformed,
manifestSelfTest,
operatorManifest,
ilspyOracle,
};
finalReport = {
verified:
11 + (operatorManifest === null ? 0 : 1) + (ilspyOracle === null ? 0 : 1),
managedSurfaces: [
"inspect_managed_artifact",
"inspect_managed_members",
"inspect_managed_native_boundaries",
"compare_managed_members",
"verify_managed_native_boundaries",
"import_managed_reconstruction",
"project_managed_application_graph",
],
coverage: [
"modern-dotnet-anycpu",
"dotnet-framework-x86-pinvoke",
"x64-ready-to-run-native-body",
"managed-native-verification",
"managed-application-graph-projection",
"unicode-obfuscated-identifiers",
"decompiler-reconstruction-import",
"mvid-and-token-drift",
"not-managed",
"malformed-metadata",
"operator-local-managed-manifest",
...(ilspyOracle === null ? [] : ["ilspy-reconstruction-oracle"]),
],
managedAppManifest: {
env: "REA_MANAGED_APP_MANIFEST_PATH",
selfTest: manifestSelfTest,
operator: operatorManifest ?? { configured: false },
},
ilspyOracle: ilspyOracle ?? {
env: "REA_ILSPY_CMD_PATH",
configured: false,
},
};
});
finalReport.completionReport = createManagedCompletionReport(
completionReportInput,
await completeVerifierRun(verifierRun),
);
process.stdout.write(`${JSON.stringify(finalReport)}\n`);