Files
reverse-engineering-anything/scripts/verify-managed-conformance.mjs
T
morluto b5e98915c6 fix(tools)!: simplify direct invocation and harden boundary contracts (#555)
Remove REA permission grants, scope ceilings, approval confirmations, and inert settings. Preserve selected local evidence, accept caller-chosen commands and paths, and report actual runtime failures.

Harden provider results, schema serialization, snapshot evidence binding, archive paths, source maps, native screenshots, managed EH parsing, and cancellation cleanup. Regenerate tool metadata and document direct invocation.

BREAKING CHANGE: Removed permission configuration and policy commands, approval fields, filesystem scope inputs, and fixed confirmation options. Process capture inherits the host environment and accepts command names; callers must refresh tool schemas and migrate removed fields.
2026-10-05 20:16:44 +08:00

456 lines
14 KiB
JavaScript

import { mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
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/ManagedMemberComparisonService.js";
import { verifyManagedNativeBoundariesEvidence } from "../dist/application/ManagedNativeVerificationService.js";
import { importManagedReconstructionEvidence } from "../dist/application/ManagedReconstructionService.js";
import { planManagedRuntimeCorrelationEvidence } from "../dist/application/ManagedRuntimeCorrelationService.js";
import { projectManagedApplicationGraphEvidence } from "../dist/application/ManagedApplicationGraphService.js";
import { traceApplicationFeatureEvidence } from "../dist/application/JavaScriptApplicationWorkflowService.js";
import { MANAGED_STATIC_PROVIDER } from "../dist/application/InvestigationProviders.js";
import { createEvidence } from "../dist/domain/evidence.js";
import {
alternateMvid,
buildNativePeFixture,
} from "./lib/managed-pe-fixture.mjs";
import { createManagedConformanceSupport } from "./lib/managed-conformance-support.mjs";
import {
comparisonLimits,
defaultIlBody,
functionDossier,
inspectionLimits,
memberLimits,
nativeBoundaryLimits,
} from "./lib/managed-conformance-config.mjs";
import { createManagedCompletionReport } from "./lib/managed-completion-report.mjs";
import { completeVerifierRun, createVerifierRun } from "./lib/verifier-run.mjs";
const verifierRun = createVerifierRun();
const workspace = await mkdtemp(join(tmpdir(), "rea-managed-conformance-"));
const {
fixture,
fixtureBytes,
runManagedAppManifestSelfTest,
runOptionalManagedAppManifest,
runOptionalIlspyOracle,
sha256,
} = createManagedConformanceSupport({
workspace,
inspectionLimits,
memberLimits,
defaultIlBody,
});
try {
const modern = await fixture("modern-anycpu.exe", {
references: ["System.Runtime"],
resourceData: Buffer.from("source-owned managed resource"),
});
const modernArtifact = inspectManagedArtifactBytes(
modern.bytes,
modern.target,
inspectionLimits,
);
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,
inspectionLimits,
);
assert.equal(
frameworkArtifact.classification.runtime_family,
"dotnet-framework",
);
assert.equal(frameworkArtifact.classification.managed_architecture, "x86");
const frameworkBoundaries = inspectManagedNativeBoundariesBytes(
framework.bytes,
framework.target,
nativeBoundaryLimits,
);
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,
memberLimits,
);
const frameworkArtifactEvidence = createEvidence(
framework.target,
MANAGED_STATIC_PROVIDER,
{
operation: "inspect_managed_artifact",
parameters: inspectionLimits,
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: memberLimits,
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: nativeBoundaryLimits,
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 = verifyManagedNativeBoundariesEvidence({
managed_boundaries: frameworkBoundaryEvidence,
native_observations: [nativeFunctionEvidence],
});
assert.equal(nativeVerification.ok, true);
assert.equal(nativeVerification.value.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.normalized_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,
inspectionLimits,
);
assert.equal(r2rArtifact.pe.architecture, "x86_64");
assert.equal(
r2rArtifact.classification.implementation,
"cil-and-ready-to-run",
);
const r2rBoundaries = inspectManagedNativeBoundariesBytes(
readyToRun.bytes,
readyToRun.target,
nativeBoundaryLimits,
);
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,
memberLimits,
);
assert.equal(obfuscatedMembers.types[0]?.full_name, "Fixture.ꙮType");
assert.equal(obfuscatedMembers.methods[0]?.name, "λ⛧");
assert.equal(obfuscatedMembers.fields[0]?.name, "字段");
const runtimeExecutable = process.execPath;
const runtimeMethod = obfuscatedMembers.methods[0];
assert.ok(runtimeMethod);
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: runtimeMethod.token,
signature_sha256: runtimeMethod.signature.raw_sha256,
normalized_il_sha256: runtimeMethod.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 runtimePlan = await planManagedRuntimeCorrelationEvidence(
{ configuration: () => ({ executablePath: runtimeExecutable }) },
{
static_members: obfuscatedMembersEvidence,
method: {
token: runtimeMethod.token,
signature_sha256: runtimeMethod.signature.raw_sha256,
normalized_il_sha256: runtimeMethod.body.normalized_il_sha256,
},
requested_effect: "debugger",
host: {
os: "linux",
clr_family: "dotnet",
architecture: "x86_64",
},
bounds: {
timeout_ms: 5_000,
max_threads: 32,
max_output_bytes: 65_536,
allow_network: false,
allow_ui: false,
},
},
);
assert.equal(runtimePlan.ok, true);
assert.equal(runtimePlan.value.normalized_result.executed, false);
assert.equal(
runtimePlan.value.normalized_result.unsupported_until_executor_exists,
true,
);
assert.equal(
runtimePlan.value.normalized_result.effect_taxonomy.uses_debugger,
true,
);
assert.equal(
runtimePlan.value.normalized_result.requested_runtime.confinement,
"not-established",
);
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,
memberLimits: {
maxFileBytes: 1024 * 1024,
...memberLimits,
},
comparisonLimits,
});
assert.equal(comparison.ok, true);
const comparisonResult = comparison.value.normalized_result;
assert.equal(comparisonResult.algorithm.name_matching, "not-used");
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 nativeOnly = await fixtureBytes(
"native-only.exe",
buildNativePeFixture(),
);
const nativeResult = inspectManagedArtifactBytes(
nativeOnly.bytes,
nativeOnly.target,
inspectionLimits,
);
assert.equal(nativeResult.classification.status, "not-managed");
const malformed = await fixture("malformed-metadata.exe", {
corruptMetadataSignature: true,
});
const malformedResult = inspectManagedArtifactBytes(
malformed.bytes,
malformed.target,
inspectionLimits,
);
assert.equal(malformedResult.classification.status, "malformed");
const manifestSelfTest = await runManagedAppManifestSelfTest();
const operatorManifest = await runOptionalManagedAppManifest();
const ilspyOracle = await runOptionalIlspyOracle();
const completionReport = createManagedCompletionReport(
{
modern,
framework,
nativeFunctionTarget,
readyToRun,
obfuscated,
left,
right,
nativeOnly,
malformed,
manifestSelfTest,
operatorManifest,
ilspyOracle,
},
await completeVerifierRun(verifierRun),
);
process.stdout.write(
`${JSON.stringify({
verified:
12 +
(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",
"plan_managed_runtime_correlation",
"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",
"runtime-correlation-admission-plan",
"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,
},
completionReport,
})}\n`,
);
} finally {
await rm(workspace, { recursive: true, force: true });
}