rea-agents 1.6.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -66
- package/bridge/ghidra/ReaGhidraBridge.java +2075 -0
- package/bridge/hopper_bridge.py +13 -3
- package/dist/application/AbortablePromise.js +25 -0
- package/dist/application/AnalysisProvider.js +3 -0
- package/dist/application/AnalysisProviderEvaluation.js +60 -0
- package/dist/application/AnalysisProviderRegistry.js +228 -0
- package/dist/application/AnalysisSnapshotCache.js +41 -21
- package/dist/application/AnalysisSnapshotFiles.js +5 -6
- package/dist/application/BinarySession.js +218 -101
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/CompositeProvider.js +20 -8
- package/dist/application/CrossVersionInvestigation.js +10 -6
- package/dist/application/DirectAnalysis.js +49 -35
- package/dist/application/Doctor.js +110 -8
- package/dist/application/ElectronBoundaryAnalysis.js +96 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
- package/dist/application/EnhancedTools.js +39 -14
- package/dist/application/InvestigationProviders.js +41 -0
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +305 -0
- package/dist/application/JavaScriptArtifactAnalysisTypes.js +1 -0
- package/dist/application/JavaScriptArtifactFiles.js +231 -0
- package/dist/application/JavaScriptArtifactGraphAccumulator.js +54 -0
- package/dist/application/JavaScriptArtifactGraphBuilder.js +144 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +205 -0
- package/dist/application/JavaScriptArtifactGraphDocuments.js +108 -0
- package/dist/application/JavaScriptArtifactGraphEvidence.js +99 -0
- package/dist/application/JavaScriptArtifactGraphFindings.js +271 -0
- package/dist/application/JavaScriptArtifactGraphStructure.js +409 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +77 -0
- package/dist/application/JavaScriptArtifactReconstructionInput.js +18 -0
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +266 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/MacHopper.js +20 -4
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/PermissionAuthority.js +1 -1
- package/dist/application/ProcessCaptureLifecycle.js +1 -1
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessSampling.js +16 -12
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/SessionProviderRouter.js +219 -0
- package/dist/application/Setup.js +84 -60
- package/dist/application/SetupClients.js +1 -1
- package/dist/application/SetupPlan.js +9 -2
- package/dist/application/SupportedClients.js +40 -16
- package/dist/application/Upgrade.js +1 -1
- package/dist/application/runtime.js +11 -6
- package/dist/artifacts/AsarArtifactReader.js +23 -3
- package/dist/browser/CdpBrowserProvider.js +4 -2
- package/dist/browser/CdpCaptureEvents.js +49 -0
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +9 -3
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpEndpoint.js +14 -1
- package/dist/browser/CdpPageCapture.js +8 -4
- package/dist/catalogIdentity.js +6 -42
- package/dist/cli.js +446 -34
- package/dist/cliApplicationCommands.js +62 -0
- package/dist/cliBrowserAdvancedCommands.js +5 -4
- package/dist/cliBrowserCommands.js +5 -4
- package/dist/cliCommandNames.js +56 -0
- package/dist/cliElectronCommands.js +106 -3
- package/dist/cliEvidenceCommands.js +4 -3
- package/dist/cliInvestigationCommands.js +2 -1
- package/dist/cliJsonInput.js +54 -0
- package/dist/cliPolicyCommands.js +2 -1
- package/dist/cliProcessCommands.js +3 -2
- package/dist/config.js +101 -2
- package/dist/contracts/applicationToolContracts.js +91 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/enhancedInputs.js +2 -2
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/providerSelection.js +28 -0
- package/dist/contracts/sessionLifecycleInputs.js +2 -0
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +69 -65
- package/dist/contracts/toolEffects.js +160 -0
- package/dist/contracts/toolOutputSchemas.js +152 -42
- package/dist/doctorRuntime.js +47 -0
- package/dist/domain/analysisProfile.js +78 -0
- package/dist/domain/analysisSnapshot.js +92 -46
- package/dist/domain/artifactComparison.js +3 -4
- package/dist/domain/artifactGraph.js +1 -0
- package/dist/domain/binaryTarget.js +4 -29
- package/dist/domain/browserObservation.js +3 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +148 -7
- package/dist/domain/evidence.js +44 -5
- package/dist/domain/evidenceBundle.js +9 -7
- package/dist/domain/functionComparison.js +9 -3
- package/dist/domain/functionComparisonNormalization.js +37 -0
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/functionDossierEvidence.js +4 -1
- package/dist/domain/hopperValues.js +66 -9
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/investigationWorkspace.js +2 -1
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +379 -0
- package/dist/domain/javascriptApplicationGraph.js +282 -0
- package/dist/domain/javascriptApplicationGraphSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +221 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptAstFingerprint.js +143 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +88 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
- package/dist/domain/javascriptStaticAnalysis.js +346 -0
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +274 -0
- package/dist/domain/javascriptStaticAnalysisState.js +23 -0
- package/dist/domain/javascriptStaticAnalysisTypes.js +1 -0
- package/dist/domain/managedApplicationGraph.js +556 -0
- package/dist/domain/managedArtifact.js +444 -0
- package/dist/domain/managedMemberComparison.js +565 -0
- package/dist/domain/managedNativeVerification.js +408 -0
- package/dist/domain/managedReconstruction.js +183 -0
- package/dist/domain/managedRuntimeCorrelation.js +175 -0
- package/dist/domain/reconstructionVerificationSchemas.js +1 -3
- package/dist/dotnet/ManagedArtifactInspector.js +318 -0
- package/dist/dotnet/ManagedMemberInspector.js +887 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +368 -0
- package/dist/dotnet/ManagedMetadataLayout.js +322 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
- package/dist/dotnet/ManagedPeReader.js +157 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +37 -0
- package/dist/ghidra/GhidraClient.js +400 -0
- package/dist/ghidra/GhidraClientTypes.js +1 -0
- package/dist/ghidra/GhidraDefaults.js +20 -0
- package/dist/ghidra/GhidraDiagnostics.js +43 -0
- package/dist/ghidra/GhidraDoctor.js +59 -0
- package/dist/ghidra/GhidraFunctionValues.js +264 -0
- package/dist/ghidra/GhidraInstallation.js +239 -0
- package/dist/ghidra/GhidraInventoryValues.js +217 -0
- package/dist/ghidra/GhidraLauncher.js +139 -0
- package/dist/ghidra/GhidraProvider.js +366 -0
- package/dist/ghidra/GhidraRequestQueue.js +98 -0
- package/dist/ghidra/GhidraResponseBuffer.js +31 -0
- package/dist/ghidra/GhidraResponseRouter.js +24 -0
- package/dist/ghidra/GhidraSessionError.js +39 -0
- package/dist/ghidra/GhidraSessionValues.js +62 -0
- package/dist/ghidra/GhidraSocketConnection.js +46 -0
- package/dist/ghidra/protocol.js +69 -0
- package/dist/hopper/BridgeLauncher.js +19 -54
- package/dist/hopper/HopperAnalysisProfile.js +106 -0
- package/dist/hopper/HopperClient.js +154 -162
- package/dist/hopper/HopperProvider.js +99 -7
- package/dist/hopper/HopperSessionValues.js +27 -0
- package/dist/hopper/HopperSocketConnection.js +31 -0
- package/dist/main.js +14 -0
- package/dist/native/NativeMacOSProvider.js +3 -1
- package/dist/process/PendingOperations.js +59 -0
- package/dist/process/PrivateRuntimeRoot.js +33 -0
- package/dist/process/ProviderDeadline.js +95 -0
- package/dist/process/ProviderProcess.js +275 -0
- package/dist/replay/JavaScriptReplayWorker.js +286 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/createServer.js +53 -0
- package/dist/server/promptCompletion.js +9 -3
- package/dist/server/registerApplicationTools.js +115 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +33 -8
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +45 -3
- package/dist/server/registerEnhancedTools.js +67 -19
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools.js +21 -17
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools.js +277 -0
- package/dist/server/registerOfficialTools.js +11 -8
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionStatusTool.js +7 -7
- package/dist/server/registerSessionTools.js +57 -87
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +79 -2
- package/dist/server/toolResult.js +25 -17
- package/package.json +17 -7
- package/scripts/rea.mjs +36 -2
- package/skills/rea-analysis/SKILL.md +59 -3
- /package/dist/{application → process}/ProcessOwnership.js +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import canonicalize from "canonicalize";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { evidenceSchema, parseEvidence } from "./evidence.js";
|
|
5
|
+
import { managedMemberInspectionSchema } from "./managedArtifact.js";
|
|
6
|
+
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
7
|
+
const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
|
|
8
|
+
const tokenSchema = z.string().regex(/^0x[0-9a-f]{8}$/u);
|
|
9
|
+
const boundedTextSchema = z.string().min(1).max(4_096);
|
|
10
|
+
const managedRuntimeEffectSchema = z.enum([
|
|
11
|
+
"attach",
|
|
12
|
+
"load",
|
|
13
|
+
"debugger",
|
|
14
|
+
"reflection",
|
|
15
|
+
"instrumentation",
|
|
16
|
+
]);
|
|
17
|
+
const managedRuntimeHostSchema = z.strictObject({
|
|
18
|
+
os: z.enum(["linux", "macos", "windows"]),
|
|
19
|
+
clr_family: z.enum(["dotnet", "dotnet-framework", "mono", "unknown"]),
|
|
20
|
+
architecture: z.enum(["x86", "x86_64", "arm", "arm64"]),
|
|
21
|
+
});
|
|
22
|
+
const managedRuntimeBoundsSchema = z.strictObject({
|
|
23
|
+
timeout_ms: z.number().int().min(1).max(60_000).default(5_000),
|
|
24
|
+
max_threads: z.number().int().min(1).max(256).default(32),
|
|
25
|
+
max_output_bytes: z.number().int().min(0).max(1_048_576).default(65_536),
|
|
26
|
+
allow_network: z.literal(false).default(false),
|
|
27
|
+
allow_ui: z.literal(false).default(false),
|
|
28
|
+
});
|
|
29
|
+
export const managedRuntimeCorrelationInputSchema = z.strictObject({
|
|
30
|
+
static_members: evidenceSchema,
|
|
31
|
+
method: z.strictObject({
|
|
32
|
+
token: tokenSchema,
|
|
33
|
+
signature_sha256: digestSchema,
|
|
34
|
+
normalized_il_sha256: digestSchema.nullable(),
|
|
35
|
+
}),
|
|
36
|
+
requested_effect: managedRuntimeEffectSchema,
|
|
37
|
+
host: managedRuntimeHostSchema,
|
|
38
|
+
bounds: managedRuntimeBoundsSchema.default({
|
|
39
|
+
timeout_ms: 5_000,
|
|
40
|
+
max_threads: 32,
|
|
41
|
+
max_output_bytes: 65_536,
|
|
42
|
+
allow_network: false,
|
|
43
|
+
allow_ui: false,
|
|
44
|
+
}),
|
|
45
|
+
unknown_registry_approved: z.literal(true).optional(),
|
|
46
|
+
});
|
|
47
|
+
export const managedRuntimeCorrelationResultSchema = z.strictObject({
|
|
48
|
+
schema_version: z.literal(1),
|
|
49
|
+
correlation_id: z.string().regex(/^mrc_[a-f0-9]{64}$/u),
|
|
50
|
+
phase: z.literal("admission-plan"),
|
|
51
|
+
executed: z.literal(false),
|
|
52
|
+
authority_model: z.strictObject({
|
|
53
|
+
capability: z.literal("managed_runtime"),
|
|
54
|
+
permission_grant_id: z.string().min(1),
|
|
55
|
+
default_enabled: z.literal(false),
|
|
56
|
+
per_call_approval_required: z.literal(true),
|
|
57
|
+
}),
|
|
58
|
+
static_observation: z.strictObject({
|
|
59
|
+
evidence_id: evidenceIdSchema,
|
|
60
|
+
artifact_sha256: digestSchema,
|
|
61
|
+
artifact_path: z.string().min(1),
|
|
62
|
+
byte_length: z.number().int().min(0),
|
|
63
|
+
module_name: z.string().nullable(),
|
|
64
|
+
mvid: z.string().uuid().nullable(),
|
|
65
|
+
metadata_status: z.enum(["absent", "complete", "partial", "malformed"]),
|
|
66
|
+
}),
|
|
67
|
+
method_lock: z.strictObject({
|
|
68
|
+
token: tokenSchema,
|
|
69
|
+
declaring_type: z.string().nullable(),
|
|
70
|
+
name: z.string(),
|
|
71
|
+
signature_sha256: digestSchema,
|
|
72
|
+
normalized_il_sha256: digestSchema.nullable(),
|
|
73
|
+
body_sha256: digestSchema.nullable(),
|
|
74
|
+
il_size: z.number().int().min(0),
|
|
75
|
+
body_status: z.enum(["present", "absent", "malformed", "too-large"]),
|
|
76
|
+
exact_build_required: z.literal(true),
|
|
77
|
+
}),
|
|
78
|
+
requested_runtime: z.strictObject({
|
|
79
|
+
effect: managedRuntimeEffectSchema,
|
|
80
|
+
host: managedRuntimeHostSchema,
|
|
81
|
+
executable_path: z.string().min(1),
|
|
82
|
+
network: z.literal("none"),
|
|
83
|
+
filesystem: z.literal("owned-artifacts-only"),
|
|
84
|
+
}),
|
|
85
|
+
effect_taxonomy: z.strictObject({
|
|
86
|
+
attaches_process: z.boolean(),
|
|
87
|
+
loads_target: z.boolean(),
|
|
88
|
+
uses_debugger: z.boolean(),
|
|
89
|
+
uses_reflection: z.boolean(),
|
|
90
|
+
instruments_code: z.boolean(),
|
|
91
|
+
invokes_target_code: z.literal(false),
|
|
92
|
+
}),
|
|
93
|
+
bounds: managedRuntimeBoundsSchema,
|
|
94
|
+
unsupported_until_executor_exists: z.literal(true),
|
|
95
|
+
evidence_links: z.array(evidenceIdSchema).length(1),
|
|
96
|
+
limitations: z.array(boundedTextSchema).max(1_000),
|
|
97
|
+
});
|
|
98
|
+
const sha256 = (value) => {
|
|
99
|
+
const serialized = canonicalize(value);
|
|
100
|
+
if (serialized === undefined)
|
|
101
|
+
throw new TypeError("Managed runtime correlation canonicalization failed");
|
|
102
|
+
return createHash("sha256").update(serialized).digest("hex");
|
|
103
|
+
};
|
|
104
|
+
/** Authenticate static managed Evidence and build a non-executing runtime plan. */
|
|
105
|
+
export const planManagedRuntimeCorrelation = (input, executablePath, permissionGrantId) => {
|
|
106
|
+
const staticEvidence = parseEvidence(input.static_members);
|
|
107
|
+
if (staticEvidence.operation !== "inspect_managed_members")
|
|
108
|
+
throw new TypeError("Evidence operation is not inspect_managed_members");
|
|
109
|
+
const members = managedMemberInspectionSchema.parse(staticEvidence.normalized_result);
|
|
110
|
+
const method = members.methods.items.find((item) => item.token === input.method.token &&
|
|
111
|
+
item.signature.raw_sha256 === input.method.signature_sha256 &&
|
|
112
|
+
item.body.normalized_il_sha256 === input.method.normalized_il_sha256);
|
|
113
|
+
if (method === undefined)
|
|
114
|
+
throw new TypeError("Requested method lock does not match a static managed member observation");
|
|
115
|
+
const withoutId = {
|
|
116
|
+
schema_version: 1,
|
|
117
|
+
phase: "admission-plan",
|
|
118
|
+
executed: false,
|
|
119
|
+
authority_model: {
|
|
120
|
+
capability: "managed_runtime",
|
|
121
|
+
permission_grant_id: permissionGrantId,
|
|
122
|
+
default_enabled: false,
|
|
123
|
+
per_call_approval_required: true,
|
|
124
|
+
},
|
|
125
|
+
static_observation: {
|
|
126
|
+
evidence_id: staticEvidence.evidence_id,
|
|
127
|
+
artifact_sha256: members.artifact.sha256,
|
|
128
|
+
artifact_path: members.artifact.path,
|
|
129
|
+
byte_length: members.artifact.byte_length,
|
|
130
|
+
module_name: members.module?.name ?? null,
|
|
131
|
+
mvid: members.module?.mvid ?? null,
|
|
132
|
+
metadata_status: members.metadata.status,
|
|
133
|
+
},
|
|
134
|
+
method_lock: {
|
|
135
|
+
token: method.token,
|
|
136
|
+
declaring_type: method.declaring_type,
|
|
137
|
+
name: method.name,
|
|
138
|
+
signature_sha256: method.signature.raw_sha256,
|
|
139
|
+
normalized_il_sha256: method.body.normalized_il_sha256,
|
|
140
|
+
body_sha256: method.body.il_sha256,
|
|
141
|
+
il_size: method.body.il_size,
|
|
142
|
+
body_status: method.body.status,
|
|
143
|
+
exact_build_required: true,
|
|
144
|
+
},
|
|
145
|
+
requested_runtime: {
|
|
146
|
+
effect: input.requested_effect,
|
|
147
|
+
host: input.host,
|
|
148
|
+
executable_path: executablePath,
|
|
149
|
+
network: "none",
|
|
150
|
+
filesystem: "owned-artifacts-only",
|
|
151
|
+
},
|
|
152
|
+
effect_taxonomy: effectTaxonomy(input.requested_effect),
|
|
153
|
+
bounds: input.bounds,
|
|
154
|
+
unsupported_until_executor_exists: true,
|
|
155
|
+
evidence_links: [staticEvidence.evidence_id],
|
|
156
|
+
limitations: [
|
|
157
|
+
"This operation admits and records a runtime-correlation plan only; it did not attach, load, debug, reflect, instrument, invoke, or execute target code.",
|
|
158
|
+
"Runtime agreement would be a separate runtime observation and would not retroactively turn static inference into a byte observation.",
|
|
159
|
+
"The exact artifact SHA-256, MVID, method signature, and normalized IL shape must match before any future executor can run.",
|
|
160
|
+
"Network and UI effects are not admitted by this contract.",
|
|
161
|
+
],
|
|
162
|
+
};
|
|
163
|
+
return managedRuntimeCorrelationResultSchema.parse({
|
|
164
|
+
...withoutId,
|
|
165
|
+
correlation_id: `mrc_${sha256(withoutId)}`,
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
const effectTaxonomy = (effect) => ({
|
|
169
|
+
attaches_process: effect === "attach",
|
|
170
|
+
loads_target: effect === "load" || effect === "reflection",
|
|
171
|
+
uses_debugger: effect === "debugger",
|
|
172
|
+
uses_reflection: effect === "reflection",
|
|
173
|
+
instruments_code: effect === "instrumentation",
|
|
174
|
+
invokes_target_code: false,
|
|
175
|
+
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { evidenceBundleSchema } from "./evidenceBundle.js";
|
|
3
2
|
const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
|
|
4
3
|
const unknownIdSchema = z.string().regex(/^unk_[a-f0-9]{64}$/u);
|
|
5
4
|
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
@@ -69,9 +68,8 @@ export const reconstructionSpecificationSchema = z
|
|
|
69
68
|
});
|
|
70
69
|
});
|
|
71
70
|
/** Bounded reconstruction-verification input. */
|
|
72
|
-
export const reconstructionVerificationInputSchema = z.
|
|
71
|
+
export const reconstructionVerificationInputSchema = z.strictObject({
|
|
73
72
|
specification: reconstructionSpecificationSchema,
|
|
74
|
-
evidence_bundle: evidenceBundleSchema,
|
|
75
73
|
offset: z.number().int().min(0).default(0),
|
|
76
74
|
limit: z.number().int().min(1).max(100).default(100),
|
|
77
75
|
unknown_registry_approved: z.literal(true).optional(),
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { managedArtifactInspectionSchema, } from "../domain/managedArtifact.js";
|
|
2
|
+
import { readManagedPeLayout, } from "./ManagedPeReader.js";
|
|
3
|
+
import { managedTableRowCounts, readManagedMetadataInventory, } from "./ManagedMetadataInventory.js";
|
|
4
|
+
import { readManagedMetadataLayout, } from "./ManagedMetadataLayout.js";
|
|
5
|
+
import { ManagedReaderFailure } from "./ManagedReaderFailure.js";
|
|
6
|
+
const emptyPage = (offset, limit) => ({
|
|
7
|
+
items: [],
|
|
8
|
+
offset,
|
|
9
|
+
limit,
|
|
10
|
+
total: 0,
|
|
11
|
+
returned: 0,
|
|
12
|
+
dropped: 0,
|
|
13
|
+
complete: offset === 0,
|
|
14
|
+
});
|
|
15
|
+
const flagNames = (flags) => {
|
|
16
|
+
const names = [];
|
|
17
|
+
for (const [mask, name] of [
|
|
18
|
+
[0x0000_0001, "il-only"],
|
|
19
|
+
[0x0000_0002, "32-bit-required"],
|
|
20
|
+
[0x0000_0004, "il-library"],
|
|
21
|
+
[0x0000_0008, "strong-name-signed"],
|
|
22
|
+
[0x0000_0010, "native-entry-point"],
|
|
23
|
+
[0x0001_0000, "track-debug-data"],
|
|
24
|
+
[0x0002_0000, "32-bit-preferred"],
|
|
25
|
+
])
|
|
26
|
+
if ((flags & mask) !== 0)
|
|
27
|
+
names.push(name);
|
|
28
|
+
return names;
|
|
29
|
+
};
|
|
30
|
+
const cliProjection = (cli) => ({
|
|
31
|
+
header_offset: cli.headerOffset,
|
|
32
|
+
header_size: cli.headerSize,
|
|
33
|
+
runtime_version: `${String(cli.runtimeMajor)}.${String(cli.runtimeMinor)}`,
|
|
34
|
+
flags: cli.flags,
|
|
35
|
+
flag_names: flagNames(cli.flags),
|
|
36
|
+
entry_point: cli.entryPoint === 0
|
|
37
|
+
? { kind: "none", value: null }
|
|
38
|
+
: (cli.flags & 0x10) !== 0
|
|
39
|
+
? {
|
|
40
|
+
kind: "native-rva",
|
|
41
|
+
value: `0x${cli.entryPoint.toString(16)}`,
|
|
42
|
+
}
|
|
43
|
+
: {
|
|
44
|
+
kind: "metadata-token",
|
|
45
|
+
value: `0x${cli.entryPoint.toString(16).padStart(8, "0")}`,
|
|
46
|
+
},
|
|
47
|
+
metadata_rva: cli.metadata.rva,
|
|
48
|
+
metadata_size: cli.metadata.size,
|
|
49
|
+
resources_rva: cli.resources.rva,
|
|
50
|
+
resources_size: cli.resources.size,
|
|
51
|
+
strong_name_rva: cli.strongName.rva,
|
|
52
|
+
strong_name_size: cli.strongName.size,
|
|
53
|
+
managed_native_header_rva: cli.managedNativeHeader.rva,
|
|
54
|
+
managed_native_header_size: cli.managedNativeHeader.size,
|
|
55
|
+
ready_to_run_signature: cli.readyToRunSignature,
|
|
56
|
+
});
|
|
57
|
+
const peProjection = (layout) => ({
|
|
58
|
+
machine: layout.machine,
|
|
59
|
+
machine_hex: `0x${layout.machine.toString(16).padStart(4, "0")}`,
|
|
60
|
+
architecture: layout.architecture,
|
|
61
|
+
optional_header: layout.optionalHeader,
|
|
62
|
+
section_count: layout.sectionCount,
|
|
63
|
+
characteristics: layout.characteristics,
|
|
64
|
+
cli: layout.cli === null ? null : cliProjection(layout.cli),
|
|
65
|
+
});
|
|
66
|
+
const base = (target, bytes, layout) => ({
|
|
67
|
+
schema_version: 1,
|
|
68
|
+
artifact: {
|
|
69
|
+
path: target.path,
|
|
70
|
+
sha256: target.sha256,
|
|
71
|
+
byte_length: bytes.length,
|
|
72
|
+
format: "pe",
|
|
73
|
+
},
|
|
74
|
+
pe: peProjection(layout),
|
|
75
|
+
});
|
|
76
|
+
const unavailableResult = (target, bytes, layout, limits) => {
|
|
77
|
+
const malformed = layout.cliDirectoryPresent;
|
|
78
|
+
const issues = layout.cliIssue === null ? [] : [layout.cliIssue];
|
|
79
|
+
const limitations = malformed
|
|
80
|
+
? [
|
|
81
|
+
"The PE declares a CLI directory, but its CLI header could not be admitted.",
|
|
82
|
+
]
|
|
83
|
+
: [
|
|
84
|
+
"The PE has no CLI data directory; managed metadata and CIL are unavailable.",
|
|
85
|
+
];
|
|
86
|
+
return managedArtifactInspectionSchema.parse({
|
|
87
|
+
...base(target, bytes, layout),
|
|
88
|
+
classification: {
|
|
89
|
+
status: malformed ? "malformed" : "not-managed",
|
|
90
|
+
container: "pe",
|
|
91
|
+
runtime_family: "unknown",
|
|
92
|
+
implementation: malformed ? "unknown" : "not-managed",
|
|
93
|
+
managed_architecture: "unknown",
|
|
94
|
+
evidence: [
|
|
95
|
+
{
|
|
96
|
+
code: malformed ? "cli-directory-malformed" : "cli-directory-absent",
|
|
97
|
+
detail: limitations[0],
|
|
98
|
+
file_offset: layout.cliIssue?.offset ?? null,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
metadata: {
|
|
103
|
+
status: malformed ? "malformed" : "absent",
|
|
104
|
+
version: null,
|
|
105
|
+
stream_names: [],
|
|
106
|
+
table_row_counts: {},
|
|
107
|
+
},
|
|
108
|
+
module: null,
|
|
109
|
+
assembly: null,
|
|
110
|
+
target_frameworks: [],
|
|
111
|
+
references: emptyPage(limits.referenceOffset, limits.referenceLimit),
|
|
112
|
+
resources: emptyPage(limits.resourceOffset, limits.resourceLimit),
|
|
113
|
+
attributes: emptyPage(limits.attributeOffset, limits.attributeLimit),
|
|
114
|
+
coverage: {
|
|
115
|
+
state: malformed ? "partial" : "unavailable",
|
|
116
|
+
issues,
|
|
117
|
+
},
|
|
118
|
+
limitations,
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
const runtimeClassification = (layout, metadata, inventory) => {
|
|
122
|
+
const cli = layout.cli;
|
|
123
|
+
if (cli === null)
|
|
124
|
+
throw new TypeError("Managed classification requires CLI");
|
|
125
|
+
const evidence = [
|
|
126
|
+
{
|
|
127
|
+
code: "cli-header-observed",
|
|
128
|
+
detail: "A file-backed PE CLI header and metadata root were admitted.",
|
|
129
|
+
file_offset: cli.headerOffset,
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
const frameworks = inventory.targetFrameworks;
|
|
133
|
+
const hasUnity = inventory.referenceNames.some((name) => name === "UnityEngine" || name.startsWith("UnityEngine."));
|
|
134
|
+
let runtimeFamily = "unknown";
|
|
135
|
+
if ((cli.flags & 1) === 0) {
|
|
136
|
+
runtimeFamily = "mixed-clr-native";
|
|
137
|
+
evidence.push({
|
|
138
|
+
code: "cli-il-only-clear",
|
|
139
|
+
detail: "COMIMAGE_FLAGS_ILONLY is clear, so managed and native analysis must remain composed.",
|
|
140
|
+
file_offset: cli.headerOffset + 16,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
else if (hasUnity) {
|
|
144
|
+
runtimeFamily = "unity-mono";
|
|
145
|
+
evidence.push({
|
|
146
|
+
code: "unity-reference-observed",
|
|
147
|
+
detail: "The admitted AssemblyRef table contains a UnityEngine reference.",
|
|
148
|
+
file_offset: metadata.table(35)?.offset ?? null,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
else if (frameworks.some((value) => value.startsWith(".NETFramework,"))) {
|
|
152
|
+
runtimeFamily = "dotnet-framework";
|
|
153
|
+
evidence.push({
|
|
154
|
+
code: "target-framework-observed",
|
|
155
|
+
detail: "An assembly-level TargetFrameworkAttribute names .NET Framework.",
|
|
156
|
+
file_offset: metadata.table(12)?.offset ?? null,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
else if (frameworks.some((value) => value.startsWith(".NETCoreApp,") || value.startsWith(".NETStandard,")) ||
|
|
160
|
+
cli.readyToRunSignature) {
|
|
161
|
+
runtimeFamily = "modern-dotnet";
|
|
162
|
+
evidence.push({
|
|
163
|
+
code: cli.readyToRunSignature
|
|
164
|
+
? "ready-to-run-signature-observed"
|
|
165
|
+
: "target-framework-observed",
|
|
166
|
+
detail: cli.readyToRunSignature
|
|
167
|
+
? "The managed native header has the ReadyToRun signature."
|
|
168
|
+
: "An assembly-level TargetFrameworkAttribute names modern .NET.",
|
|
169
|
+
file_offset: cli.readyToRunSignature
|
|
170
|
+
? layout.rvaToOffset(cli.managedNativeHeader.rva, 4, "cli.managed-native-header")
|
|
171
|
+
: (metadata.table(12)?.offset ?? null),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
const implementation = (cli.flags & 1) === 0
|
|
175
|
+
? "cpp-cli-mixed"
|
|
176
|
+
: cli.readyToRunSignature
|
|
177
|
+
? "cil-and-ready-to-run"
|
|
178
|
+
: (metadata.rowCounts[6] ?? 0) === 0
|
|
179
|
+
? "metadata-only"
|
|
180
|
+
: "cil";
|
|
181
|
+
const managedArchitecture = layout.architecture === "x86" && (cli.flags & 1) !== 0
|
|
182
|
+
? (cli.flags & 0x0000_0002) !== 0
|
|
183
|
+
? "x86"
|
|
184
|
+
: (cli.flags & 0x0002_0000) !== 0
|
|
185
|
+
? "anycpu-prefer-32"
|
|
186
|
+
: "anycpu"
|
|
187
|
+
: layout.architecture;
|
|
188
|
+
evidence.push({
|
|
189
|
+
code: "managed-architecture-derived",
|
|
190
|
+
detail: `Managed architecture ${managedArchitecture} is derived from PE machine and CLI flags.`,
|
|
191
|
+
file_offset: cli.headerOffset + 16,
|
|
192
|
+
});
|
|
193
|
+
return {
|
|
194
|
+
runtime_family: runtimeFamily,
|
|
195
|
+
implementation,
|
|
196
|
+
managed_architecture: managedArchitecture,
|
|
197
|
+
evidence,
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
const partialMetadataResult = (target, bytes, layout, limits, issue) => ({
|
|
201
|
+
...base(target, bytes, layout),
|
|
202
|
+
classification: {
|
|
203
|
+
status: "malformed",
|
|
204
|
+
container: "pe",
|
|
205
|
+
runtime_family: (layout.cli?.flags ?? 1) & 1 ? "unknown" : "mixed-clr-native",
|
|
206
|
+
implementation: "unknown",
|
|
207
|
+
managed_architecture: "unknown",
|
|
208
|
+
evidence: [
|
|
209
|
+
{
|
|
210
|
+
code: "metadata-not-admitted",
|
|
211
|
+
detail: issue.detail,
|
|
212
|
+
file_offset: issue.offset,
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
metadata: {
|
|
217
|
+
status: issue.code === "limit-exceeded" ? "partial" : "malformed",
|
|
218
|
+
version: null,
|
|
219
|
+
stream_names: [],
|
|
220
|
+
table_row_counts: {},
|
|
221
|
+
},
|
|
222
|
+
module: null,
|
|
223
|
+
assembly: null,
|
|
224
|
+
target_frameworks: [],
|
|
225
|
+
references: emptyPage(limits.referenceOffset, limits.referenceLimit),
|
|
226
|
+
resources: emptyPage(limits.resourceOffset, limits.resourceLimit),
|
|
227
|
+
attributes: emptyPage(limits.attributeOffset, limits.attributeLimit),
|
|
228
|
+
coverage: { state: "partial", issues: [issue] },
|
|
229
|
+
limitations: [
|
|
230
|
+
"CLI metadata triage stopped at the reported bounded format or resource limit.",
|
|
231
|
+
],
|
|
232
|
+
});
|
|
233
|
+
const mapResources = (bytes, layout, issues) => {
|
|
234
|
+
const resources = layout.cli?.resources;
|
|
235
|
+
if (resources === undefined || (resources.rva === 0 && resources.size === 0))
|
|
236
|
+
return null;
|
|
237
|
+
try {
|
|
238
|
+
return {
|
|
239
|
+
offset: layout.rvaToOffset(resources.rva, resources.size, "cli.resources"),
|
|
240
|
+
size: resources.size,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
catch (cause) {
|
|
244
|
+
if (!(cause instanceof ManagedReaderFailure))
|
|
245
|
+
throw cause;
|
|
246
|
+
issues.push(cause.issue);
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
/** Inspect PE/CLI identity directly from bounded bytes without CLR loading. */
|
|
251
|
+
export const inspectManagedArtifactBytes = (bytes, target, limits) => {
|
|
252
|
+
const layout = readManagedPeLayout(bytes);
|
|
253
|
+
if (layout.cli === null)
|
|
254
|
+
return unavailableResult(target, bytes, layout, limits);
|
|
255
|
+
const cli = layout.cli;
|
|
256
|
+
if (cli.metadata.size > limits.maxMetadataBytes)
|
|
257
|
+
return managedArtifactInspectionSchema.parse(partialMetadataResult(target, bytes, layout, limits, {
|
|
258
|
+
code: "limit-exceeded",
|
|
259
|
+
scope: "cli.metadata",
|
|
260
|
+
offset: cli.headerOffset + 8,
|
|
261
|
+
detail: `CLI metadata size exceeds max_metadata_bytes ${String(limits.maxMetadataBytes)}`,
|
|
262
|
+
}));
|
|
263
|
+
let metadata;
|
|
264
|
+
try {
|
|
265
|
+
const metadataOffset = layout.rvaToOffset(cli.metadata.rva, cli.metadata.size, "cli.metadata");
|
|
266
|
+
metadata = readManagedMetadataLayout(bytes, metadataOffset, cli.metadata.size, limits.maxTableRows);
|
|
267
|
+
}
|
|
268
|
+
catch (cause) {
|
|
269
|
+
if (!(cause instanceof ManagedReaderFailure))
|
|
270
|
+
throw cause;
|
|
271
|
+
return managedArtifactInspectionSchema.parse(partialMetadataResult(target, bytes, layout, limits, cause.issue));
|
|
272
|
+
}
|
|
273
|
+
const resourceIssues = [];
|
|
274
|
+
const resourceDirectory = mapResources(bytes, layout, resourceIssues);
|
|
275
|
+
const inventory = readManagedMetadataInventory(bytes, metadata, limits, resourceDirectory);
|
|
276
|
+
const issues = [...resourceIssues, ...inventory.issues];
|
|
277
|
+
const pagesComplete = inventory.references.complete &&
|
|
278
|
+
inventory.resources.complete &&
|
|
279
|
+
inventory.attributes.complete;
|
|
280
|
+
const limitations = [
|
|
281
|
+
...(pagesComplete
|
|
282
|
+
? []
|
|
283
|
+
: [
|
|
284
|
+
"At least one caller-selected metadata page omits rows; use its offset and total to continue.",
|
|
285
|
+
]),
|
|
286
|
+
...(issues.length === 0
|
|
287
|
+
? []
|
|
288
|
+
: [
|
|
289
|
+
"At least one bounded metadata or resource item was unavailable; coverage is partial.",
|
|
290
|
+
]),
|
|
291
|
+
"Static inspection did not load the assembly, resolve dependencies through a CLR, decompile C#, or execute target code.",
|
|
292
|
+
];
|
|
293
|
+
return managedArtifactInspectionSchema.parse({
|
|
294
|
+
...base(target, bytes, layout),
|
|
295
|
+
classification: {
|
|
296
|
+
status: "managed",
|
|
297
|
+
container: "pe",
|
|
298
|
+
...runtimeClassification(layout, metadata, inventory),
|
|
299
|
+
},
|
|
300
|
+
metadata: {
|
|
301
|
+
status: issues.length === 0 ? "complete" : "partial",
|
|
302
|
+
version: metadata.version,
|
|
303
|
+
stream_names: metadata.streamNames,
|
|
304
|
+
table_row_counts: managedTableRowCounts(metadata),
|
|
305
|
+
},
|
|
306
|
+
module: inventory.module,
|
|
307
|
+
assembly: inventory.assembly,
|
|
308
|
+
target_frameworks: inventory.targetFrameworks,
|
|
309
|
+
references: inventory.references,
|
|
310
|
+
resources: inventory.resources,
|
|
311
|
+
attributes: inventory.attributes,
|
|
312
|
+
coverage: {
|
|
313
|
+
state: pagesComplete && issues.length === 0 ? "complete" : "partial",
|
|
314
|
+
issues,
|
|
315
|
+
},
|
|
316
|
+
limitations,
|
|
317
|
+
});
|
|
318
|
+
};
|