rea-agents 6.3.0 → 6.4.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 +7 -4
- package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
- package/bridge/ghidra/ReaGhidraBridge.java +597 -209
- package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
- package/dist/adb/AdbConfiguration.js +88 -0
- package/dist/adb/AdbDeviceOutput.js +186 -0
- package/dist/adb/AdbProvider.js +1190 -0
- package/dist/adb/AdbShellOutput.js +309 -0
- package/dist/android/AndroidTargetSnapshot.js +104 -22
- package/dist/android/JadxConfiguration.js +44 -24
- package/dist/android/JadxProvider.js +51 -19
- package/dist/apktool/ApktoolConfiguration.js +84 -0
- package/dist/apktool/ApktoolDecodeOutput.js +59 -0
- package/dist/apktool/ApktoolProvider.js +506 -0
- package/dist/application/AnalysisProvider.js +8 -2
- package/dist/application/AppBundleExecutable.js +27 -22
- package/dist/application/BinaryTargetResolver.js +22 -2
- package/dist/application/CapabilityInventory.js +11 -1
- package/dist/application/ClientConfigurationDocument.js +70 -0
- package/dist/application/ClientConfigurationFiles.js +91 -0
- package/dist/application/ClientRegistrationEnvironment.js +35 -0
- package/dist/application/ClientRegistrationStatus.js +66 -31
- package/dist/application/DirectAnalysis.js +2 -2
- package/dist/application/DirectAnalysisCleanup.js +1 -1
- package/dist/application/DirectAnalysisStatus.js +1 -1
- package/dist/application/Doctor.js +5 -3
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleCommands.js +6 -12
- package/dist/application/GeminiClientSettings.js +139 -0
- package/dist/application/HermesClientHome.js +115 -0
- package/dist/application/HopperDownload.js +39 -0
- package/dist/application/InvestigationProviders.js +6 -0
- package/dist/application/JsonFiles.js +6 -5
- package/dist/{cliJsonFile.js → application/JsonInputFile.js} +108 -35
- package/dist/application/LinuxHopper.js +4 -12
- package/dist/application/MacHopper.js +172 -149
- package/dist/application/MipsElfAbiFlags.js +140 -0
- package/dist/application/ProviderOperationExecution.js +31 -0
- package/dist/application/ReconstructionObligationCandidates.js +9 -3
- package/dist/application/ReferenceSourceImport.js +76 -29
- package/dist/application/ReferenceSourceImportEntries.js +18 -9
- package/dist/application/ReferenceSourceImportPolicy.js +99 -23
- package/dist/application/ReferenceSourceImportTypes.js +30 -22
- package/dist/application/ReferenceSourceVcsAdapter.js +145 -30
- package/dist/application/RegularFileRead.js +93 -7
- package/dist/application/Setup.js +54 -6
- package/dist/application/SetupClientConfiguration.js +116 -16
- package/dist/application/SetupHost.js +102 -24
- package/dist/application/SetupPlan.js +5 -8
- package/dist/application/SetupSkill.js +58 -39
- package/dist/application/SupportedClients.js +290 -65
- package/dist/application/Uninstall.js +158 -10
- package/dist/application/UpdateMaintenance.js +17 -21
- package/dist/application/Utf8JsonInput.js +7 -0
- package/dist/application/WebScriptExportService.js +131 -65
- package/dist/application/WebSourceLocationService.js +3 -0
- package/dist/application/adb/AdbDeviceAnalysisPort.js +1 -0
- package/dist/application/adb/AdbDeviceAnalysisService.js +13 -0
- package/dist/application/analysisView/AnalysisViewService.js +40 -2
- package/dist/application/apktool/ApktoolResourceAnalysisPort.js +1 -0
- package/dist/application/apktool/ApktoolResourceAnalysisService.js +13 -0
- package/dist/application/binary/AnalysisClientCleanup.js +0 -24
- package/dist/application/binary/BinarySession.js +2 -1
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +2 -1
- package/dist/application/binaryDiagnostics/PeResourcesPort.js +1 -0
- package/dist/application/binaryDiagnostics/PeResourcesService.js +111 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +2 -1
- package/dist/application/evm/EvmInterfaceService.js +3 -0
- package/dist/application/firmware/FirmwareAnalysisService.js +3 -0
- package/dist/application/investigation/InspectEvidenceBundle.js +18 -0
- package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
- package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +19 -6
- package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
- package/dist/application/javascript/JavaScriptApplicationService.js +22 -11
- package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -30
- package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +67 -19
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +19 -16
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +258 -235
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +115 -26
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -1
- package/dist/application/javascript/JavaScriptModuleRelationships.js +6 -4
- package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +9 -3
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +199 -61
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +12 -19
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +4 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -3
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +5 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +19 -8
- package/dist/application/jeb/JebAnalysisPort.js +1 -0
- package/dist/application/jeb/JebAnalysisService.js +13 -0
- package/dist/application/managed/ManagedApplicationGraphService.js +1 -1
- package/dist/application/native/NativeUiActionTrace.js +16 -8
- package/dist/application/native/NativeValueTrace.js +23 -6
- package/dist/application/process/ProcessCli.js +25 -20
- package/dist/artifacts/ArtifactPaths.js +129 -8
- package/dist/artifacts/ArtifactProvider.js +20 -15
- package/dist/artifacts/ArtifactReader.js +23 -0
- package/dist/artifacts/ArtifactResourceScope.js +100 -0
- package/dist/artifacts/AsarArtifactReader.js +176 -102
- package/dist/artifacts/AsarHeader.js +24 -0
- package/dist/artifacts/DirectoryArtifactReader.js +168 -65
- package/dist/artifacts/MachOSliceArtifactReader.js +116 -39
- package/dist/artifacts/NativeDmgArtifactReader.js +29 -22
- package/dist/artifacts/SafeOutputTree.js +245 -70
- package/dist/artifacts/SafeOutputTreeCleanup.js +45 -0
- package/dist/artifacts/SafeOutputTreeCreationFailure.js +20 -0
- package/dist/artifacts/SafeOutputTreeIdentity.js +42 -0
- package/dist/artifacts/SafeOutputTreeReadback.js +33 -0
- package/dist/artifacts/ZipArtifactReader.js +77 -27
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +58 -18
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +62 -24
- package/dist/artifacts/apple/KeyedArchiveReader.js +32 -13
- package/dist/artifacts/extraction/ArtifactExtraction.js +110 -86
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +110 -43
- package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
- package/dist/artifacts/inventory/classify.js +75 -32
- package/dist/artifacts/inventory/hashStableRootArtifact.js +48 -15
- package/dist/artifacts/inventory/reader.js +13 -5
- package/dist/artifacts/inventory/scanCanonical.js +62 -25
- package/dist/artifacts/inventory/scanReader.js +38 -11
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +15 -9
- package/dist/artifacts/javascript/JavaScriptSourceAnalysis.js +3 -0
- package/dist/browser/BrowserScenarioPartialObservation.js +8 -2
- package/dist/browser/BrowserScenarioSecrets.js +52 -37
- package/dist/browser/CdpBrowserProvider.js +5 -0
- package/dist/browser/CdpCaptureDocuments.js +40 -6
- package/dist/browser/CdpCaptureDomSvg.js +210 -0
- package/dist/browser/CdpCaptureEventBodyShapes.js +4 -8
- package/dist/browser/CdpCaptureEventHandlers.js +26 -9
- package/dist/browser/CdpCaptureEvents.js +4 -9
- package/dist/browser/CdpConnection.js +22 -5
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpTargetSession.js +30 -34
- package/dist/browser/CdpWebMcpDiscovery.js +32 -10
- package/dist/browser/ElectronFileScope.js +99 -9
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +60 -4
- package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
- package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
- package/dist/browser/PlaywrightScenarioBrowser.js +69 -7
- package/dist/browser/PlaywrightScenarioSession.js +127 -54
- package/dist/browser/PlaywrightScenarioStorage.js +507 -0
- package/dist/browser/PngVisualDiff.js +198 -29
- package/dist/browser/WebSourceMapFetcher.js +3 -3
- package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
- package/dist/browser/assets/PublishWebScripts.js +75 -20
- package/dist/browser/assets/WebArtifactReads.js +23 -1
- package/dist/browser/assets/WebSourceLocationArtifacts.js +1 -0
- package/dist/browser/execution/CdpExecutionCapture.js +3 -3
- package/dist/browser/execution/CdpPreciseCoverage.js +5 -8
- package/dist/browser/history/HarCapture.js +14 -0
- package/dist/browser/history/HarCaptureProcess.js +2 -10
- package/dist/browser/history/MitmproxyCaptureAdapter.js +3 -1
- package/dist/browser/modules/WebModuleArtifacts.js +1 -0
- package/dist/cli/adbCommands.js +337 -0
- package/dist/cli/analysisViewCommands.js +39 -1
- package/dist/cli/apktoolCommands.js +53 -0
- package/dist/cli/artifactCommands.js +8 -11
- package/dist/cli/binaryDiagnosticsCommands.js +19 -1
- package/dist/cli/browserAdvancedCommands.js +65 -36
- package/dist/cli/coreBinaryCommands.js +0 -5
- package/dist/cli/coreNativeCommands.js +1 -14
- package/dist/cli/electronCommands.js +6 -1
- package/dist/cli/evmCommands.js +13 -4
- package/dist/cli/firmwareCommands.js +7 -2
- package/dist/cli/javascriptApplicationAnalysis.js +17 -1
- package/dist/cli/javascriptRecoveryCommands.js +22 -15
- package/dist/cli/jebCommands.js +99 -0
- package/dist/cli/jsonOutput.js +11 -4
- package/dist/cli/referenceSourceImportStatus.js +7 -0
- package/dist/cli/setupCommands.js +15 -3
- package/dist/cli/utilityCommands.js +66 -18
- package/dist/cli/webScriptCommands.js +20 -1
- package/dist/cli/webSourceLocationCommands.js +21 -9
- package/dist/cli.js +6 -0
- package/dist/cliBrowserScenarioCommands.js +2 -1
- package/dist/cliCommandNames.js +32 -0
- package/dist/cliJsonInput.js +2 -2
- package/dist/cliObservationOptions.js +3 -0
- package/dist/composition/adb.js +3 -0
- package/dist/composition/apktool.js +3 -0
- package/dist/composition/binaryDiagnostics.js +4 -0
- package/dist/composition/directAnalysis.js +12 -4
- package/dist/composition/javascriptAnalysisWorkerProcess.js +48 -0
- package/dist/composition/jeb.js +6 -0
- package/dist/config/environment.js +10 -0
- package/dist/config/ghidraLanguageOverride.js +9 -0
- package/dist/config/mcpInputSchemaProfile.js +27 -0
- package/dist/config/parseConfig.js +28 -1
- package/dist/contracts/adb/adbToolContracts.js +353 -0
- package/dist/contracts/advertisedInputExamples.js +48 -0
- package/dist/contracts/analysisDetail.js +10 -0
- package/dist/contracts/analysisViewToolContracts.js +17 -2
- package/dist/contracts/apktool/apktoolToolContracts.js +33 -0
- package/dist/contracts/artifactToolContracts.js +8 -5
- package/dist/contracts/browserToolContracts.js +1 -1
- package/dist/contracts/compactInputSchema.js +256 -0
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/inputSchemaPresentation.js +10 -10
- package/dist/contracts/javascript/electronToolContracts.js +15 -3
- package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
- package/dist/contracts/jeb/jebToolContracts.js +64 -0
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
- package/dist/contracts/officialToolContracts.js +5 -5
- package/dist/contracts/sessionToolContracts.js +2 -2
- package/dist/contracts/sessionToolSchemas.js +6 -2
- package/dist/contracts/toolContractExamples.js +6 -0
- package/dist/contracts/toolContractTypes.js +3 -0
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +167 -0
- package/dist/contracts/toolOutputSchemaGroups.js +5 -3
- package/dist/contracts/toolSchemaMetadata.js +82 -7
- package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
- package/dist/domain/analysisErrorCleanup.js +29 -0
- package/dist/domain/analysisErrorPresentation.js +18 -6
- package/dist/domain/analysisErrorProjection.js +4 -1
- package/dist/domain/analysisSnapshot.js +2 -1
- package/dist/domain/analysisView/analysisView.js +52 -2
- package/dist/domain/analysisView/binaryLayoutView.js +2 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +2 -0
- package/dist/domain/analysisView/nativeFunctionView.js +155 -0
- package/dist/domain/android/androidApplication.js +25 -20
- package/dist/domain/apktool/apktoolResourceAnalysis.js +77 -0
- package/dist/domain/apple/appleApplication.js +40 -23
- package/dist/domain/apple/appleBundleAnatomy.js +95 -28
- package/dist/domain/apple/dyldPaths.js +9 -1
- package/dist/domain/apple/dylibResolution.js +2 -2
- package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
- package/dist/domain/artifactComparison.js +35 -7
- package/dist/domain/artifactGraph.js +5 -3
- package/dist/domain/artifactIdentity.js +30 -2
- package/dist/domain/artifactInspection.js +3 -43
- package/dist/domain/artifactIntegrityPolicy.js +10 -0
- package/dist/domain/artifactInventoryEvidence.js +11 -12
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/binaryTarget.js +16 -0
- package/dist/domain/binaryTargetTypes.js +8 -1
- package/dist/domain/browserObservationSchemas.js +8 -4
- package/dist/domain/canonicalJsonDigestSteps.js +34 -12
- package/dist/domain/compactStringIdentity.js +9 -0
- package/dist/domain/evidence.js +2 -1
- package/dist/domain/evidenceRecordSummary.js +144 -0
- package/dist/domain/inputIssueProjection.js +16 -1
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +12 -13
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +11 -20
- package/dist/domain/javascript/electronStaticAnalysisNative.js +70 -40
- package/dist/domain/javascript/electronStaticAnalysisValues.js +16 -0
- package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +4 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +6 -6
- package/dist/domain/javascript/javascriptApplicationGraph.js +79 -18
- package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +28 -12
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +9 -1
- package/dist/domain/javascript/javascriptAstFingerprint.js +58 -31
- package/dist/domain/javascript/javascriptAstValues.js +32 -0
- package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
- package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
- package/dist/domain/javascript/javascriptNativeHandoff.js +6 -1
- package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +7 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +8 -11
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +190 -33
- package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
- package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
- package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
- package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +42 -41
- package/dist/domain/javascript/javascriptSemanticGraph.js +69 -23
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +2 -10
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +40 -7
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +341 -87
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +78 -35
- package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
- package/dist/domain/javascript/javascriptSemanticObjects.js +7 -1
- package/dist/domain/javascript/javascriptSemanticProjection.js +52 -14
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +77 -0
- package/dist/domain/javascript/javascriptSemanticQuery.js +27 -29
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +1 -3
- package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
- package/dist/domain/javascript/javascriptSemanticReturns.js +13 -23
- package/dist/domain/javascript/javascriptSemanticState.js +22 -2
- package/dist/domain/javascript/javascriptSemanticTraversal.js +19 -1
- package/dist/domain/javascript/javascriptSemanticValues.js +47 -19
- package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
- package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +8 -6
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
- package/dist/domain/jeb/jebAnalysis.js +114 -0
- package/dist/domain/jsonShape.js +63 -52
- package/dist/domain/jsonValue.js +3 -0
- package/dist/domain/managed/managedApplicationGraph.js +37 -0
- package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
- package/dist/domain/managed/managedApplicationGraphNodes.js +32 -22
- package/dist/domain/managed/managedArtifact.js +1 -0
- package/dist/domain/managed/managedInspectionEvidence.js +13 -0
- package/dist/domain/native/nativeAotPe.js +1408 -0
- package/dist/domain/native/nativeInstruction.js +21 -0
- package/dist/domain/native/nativeMetadataRecovery.js +79 -6
- package/dist/domain/native/peResources.js +94 -0
- package/dist/domain/nativeConvention.js +33 -0
- package/dist/domain/process/processCapture.js +91 -1
- package/dist/domain/process/processCaptureExample.js +24 -0
- package/dist/domain/process/processCaptureValidation.js +79 -0
- package/dist/domain/process/processScenario.js +59 -7
- package/dist/domain/propertyListKeys.js +3 -1
- package/dist/domain/referenceSourceGraph.js +25 -16
- package/dist/domain/referenceSourceImportParsing.js +6 -3
- package/dist/domain/referenceSourcePathIdentity.js +22 -0
- package/dist/domain/referenceSourceRequireBindings.js +137 -0
- package/dist/domain/webBundleAnalyzerInspection.js +14 -2
- package/dist/domain/webCaptureDiff.js +102 -4
- package/dist/domain/webScriptExportError.js +10 -4
- package/dist/domain/webScriptExportPlan.js +7 -13
- package/dist/domain/zipPackageFormat.js +4 -1
- package/dist/domain/zodCollectionSteps.js +24 -0
- package/dist/dotnet/ManagedArtifactInspector.js +55 -43
- package/dist/dotnet/ManagedDecodeBudget.js +80 -0
- package/dist/dotnet/ManagedMemberInspector.js +13 -6
- package/dist/dotnet/ManagedMemberInspectorCore.js +2 -2
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +4 -2
- package/dist/dotnet/ManagedMemberRows.js +9 -4
- package/dist/dotnet/ManagedMetadataHeaps.js +15 -5
- package/dist/dotnet/ManagedMetadataInventoryRows.js +20 -11
- package/dist/dotnet/ManagedMetadataLayout.js +10 -4
- package/dist/dotnet/ManagedMethodBodyReader.js +8 -3
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +3 -2
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +49 -34
- package/dist/dotnet/ManagedPeReader.js +41 -25
- package/dist/dotnet/ManagedReaderFailure.js +2 -1
- package/dist/dotnet/ManagedStaticProvider.js +55 -24
- package/dist/evaluation/AgentEvaluationReport.js +9 -5
- package/dist/evaluation/CodexAgentEval.js +43 -13
- package/dist/evm/EvmoleFailures.js +0 -2
- package/dist/evm/EvmoleInterfaceProvider.js +67 -2
- package/dist/filesystem/OwnedDirectoryHandle.js +29 -0
- package/dist/filesystem/OwnedFileHandle.js +36 -0
- package/dist/filesystem/RegularFile.js +33 -1
- package/dist/filesystem/StableFileHash.js +46 -0
- package/dist/filesystem/readFileHandleChunks.js +26 -0
- package/dist/firmware/FirmwareCommand.js +25 -3
- package/dist/firmware/FirmwareFiles.js +23 -8
- package/dist/firmware/FirmwareProvider.js +156 -32
- package/dist/firmware/FirmwarePublication.js +24 -3
- package/dist/firmware/FirmwareRelease.js +1 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +55 -4
- package/dist/ghidra/GhidraAnalysisSeeds.js +211 -0
- package/dist/ghidra/GhidraClient.js +76 -4
- package/dist/ghidra/GhidraDiagnostics.js +11 -8
- package/dist/ghidra/GhidraFunctionValues.js +26 -2
- package/dist/ghidra/GhidraInstallation.js +1 -1
- package/dist/ghidra/GhidraInventoryValues.js +23 -1
- package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
- package/dist/ghidra/GhidraLauncher.js +80 -39
- package/dist/ghidra/GhidraLoadImageAttest.js +49 -2
- package/dist/ghidra/GhidraMipsProfile.js +79 -0
- package/dist/ghidra/GhidraProvider.js +57 -9
- package/dist/ghidra/GhidraProviderCapabilities.js +18 -8
- package/dist/ghidra/GhidraProviderClient.js +282 -21
- package/dist/ghidra/GhidraSessionValues.js +9 -2
- package/dist/hopper/HopperAnalysisProfile.js +2 -0
- package/dist/hopper/HopperClient.js +15 -6
- package/dist/hopper/HopperMachOImage.js +2 -0
- package/dist/hopper/HopperProvider.js +13 -2
- package/dist/ida/IdaOperationRunner.js +8 -2
- package/dist/ida/IdaProvider.js +7 -0
- package/dist/ida/IdaSessionClient.js +3 -1
- package/dist/ida/IdaWorkspace.js +4 -2
- package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +326 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +520 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +63 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +521 -0
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +116 -0
- package/dist/javascript/recovery/RecoveryFiles.js +18 -7
- package/dist/javascript/recovery/WakaruCommand.js +22 -9
- package/dist/javascript/recovery/WakaruExecution.js +11 -7
- package/dist/javascript/recovery/WakaruProvider.js +139 -16
- package/dist/javascript/recovery/WakaruPublication.js +14 -4
- package/dist/javascript/recovery/WakaruRelease.js +10 -3
- package/dist/javascript/recovery/WakaruReport.js +12 -7
- package/dist/javascript/recovery/WakaruVersion.js +24 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -3
- package/dist/javascript/sourceMaps/SourceMapDecoder.js +63 -7
- package/dist/javascript/sourceMaps/SourceMapFormat.js +15 -4
- package/dist/jeb/JebMcpConnection.js +179 -0
- package/dist/jeb/JebMcpEndpoint.js +40 -0
- package/dist/jeb/JebProvider.js +299 -0
- package/dist/mcpDoctor.js +15 -6
- package/dist/native/AppleDispatchCoverage.js +25 -12
- package/dist/native/AppleDispatchMetadata.js +14 -7
- package/dist/native/AppleMachoFixups.js +71 -15
- package/dist/native/AppleMachoSelection.js +23 -3
- package/dist/native/NativeMacOSProvider.js +91 -16
- package/dist/native/NativeMachoInspection.js +11 -7
- package/dist/native/NativeUiHelperRuntime.js +6 -1
- package/dist/native/NativeUiObservation.js +4 -3
- package/dist/native/pe/PeResourceLayout.js +120 -0
- package/dist/native/pe/PeResourceParser.js +286 -0
- package/dist/native/pe/PeResourcesProvider.js +63 -0
- package/dist/process/BoundedFileBytes.js +30 -7
- package/dist/process/DarwinProcessRunTokenReader.js +8 -3
- package/dist/process/OwnedCommand.js +4 -3
- package/dist/process/ProcessOwnership.js +104 -112
- package/dist/process/ProcessOwnershipObservation.js +96 -39
- package/dist/process/ProcessOwnershipProcessTree.js +4 -4
- package/dist/process/ProcessRunTokenObservations.js +48 -0
- package/dist/process/ProviderDiagnosticRedaction.js +17 -0
- package/dist/process/ProviderProcess.js +4 -3
- package/dist/process/capture/FilesystemSnapshot.js +28 -4
- package/dist/process/capture/ProcessCaptureLifecycle.js +350 -59
- package/dist/process/capture/ProcessCaptureProgress.js +62 -0
- package/dist/process/capture/ProcessHarness.js +194 -26
- package/dist/process/capture/ProcessNormalization.js +3 -1
- package/dist/process/capture/ProcessScenarioRuntimeValidation.js +5 -2
- package/dist/process/capture/TerminalRenderer.js +24 -7
- package/dist/reference/ReferenceSourceReader.js +22 -5
- package/dist/reference/ReferenceSourceReaderEntries.js +114 -51
- package/dist/reference/ReferenceSourceReaderErrors.js +12 -0
- package/dist/reference/ReferenceSourceReaderFile.js +50 -10
- package/dist/reference/ReferenceSourceReaderValidate.js +4 -4
- package/dist/server/EvidenceMcpServer.js +36 -1
- package/dist/server/admittedToolOperation.js +9 -0
- package/dist/server/contractToolHandler.js +21 -0
- package/dist/server/createServer.js +97 -25
- package/dist/server/registerAdbTools.js +36 -0
- package/dist/server/registerAnalysisViewTool.js +4 -9
- package/dist/server/registerAndroidTools.js +3 -12
- package/dist/server/registerApktoolTools.js +14 -0
- package/dist/server/registerApplicationTools/compareExportShapes.js +4 -6
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +4 -5
- package/dist/server/registerApplicationTools/compareVersions.js +3 -2
- package/dist/server/registerApplicationTools/coverage.js +3 -2
- package/dist/server/registerApplicationTools/obligationLedger.js +3 -2
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +3 -2
- package/dist/server/registerApplicationTools/traceFeature.js +3 -2
- package/dist/server/registerApplicationTools/traceSemantics.js +4 -5
- package/dist/server/registerArtifactComparisonTool.js +5 -2
- package/dist/server/registerBinaryDiagnosticsTools.js +16 -4
- package/dist/server/registerBrowserScenarioTool.js +10 -7
- package/dist/server/registerBrowserTools.js +12 -9
- package/dist/server/registerBundleComparisonTool.js +16 -2
- package/dist/server/registerCloseLifecycleTool.js +32 -3
- package/dist/server/registerElectronTools.js +28 -10
- package/dist/server/registerEvmTools.js +4 -9
- package/dist/server/registerFirmwareTools.js +3 -11
- package/dist/server/registerFunctionComparisonTool.js +5 -2
- package/dist/server/registerJavaScriptRecoveryTool.js +4 -9
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +9 -6
- package/dist/server/registerJebTools.js +16 -0
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -6
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -2
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +3 -2
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +3 -2
- package/dist/server/registerPeResourcesTool.js +9 -0
- package/dist/server/registerProcessComparisonTool.js +5 -2
- package/dist/server/registerRecordedCrashTools.js +4 -9
- package/dist/server/registerSessionRecordTools.js +2 -1
- package/dist/server/registerSessionTools.js +49 -18
- package/dist/server/registerWebModuleTool.js +4 -9
- package/dist/server/registerWebNetworkCaptureTool.js +4 -9
- package/dist/server/registerWebRuntimeTools.js +6 -5
- package/dist/server/registerWebScriptTool.js +6 -3
- package/dist/server/registerWebSourceLocationTool.js +4 -9
- package/dist/server/toolResult.js +21 -2
- package/dist/windows/WindowsPrivateRuntime.js +12 -5
- package/install.sh +7 -4
- package/licenses/nativeaot-parser-MIT.txt +28 -0
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +33 -5
- package/scripts/rea.mjs +16 -1
- package/skills/reverse-engineer-anything/SKILL.md +52 -51
- package/skills/reverse-engineer-anything/references/connection-and-recovery.md +127 -0
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +8 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +92 -13
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +22 -1
|
@@ -1,24 +1,45 @@
|
|
|
1
1
|
import { createAnalysisProfile } from "../domain/analysisProfile.js";
|
|
2
|
-
import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
|
|
2
|
+
import { AnalysisCancelledError, AnalysisUnsupportedTargetError, } from "../domain/analysisErrorCore.js";
|
|
3
3
|
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
|
|
4
4
|
import {} from "../domain/analysisErrorBase.js";
|
|
5
5
|
import { err, ok } from "../domain/result.js";
|
|
6
|
+
import { ghidraMipsProfileParameters, ghidraMipsUnsupportedReason, } from "./GhidraMipsProfile.js";
|
|
7
|
+
import { NATIVE_AOT_MAX_REPORT_BYTES, NATIVE_AOT_MAX_SOURCE_BYTES, NATIVE_AOT_MAX_WORKING_MEMORY_BYTES, NATIVE_AOT_MAX_WORK_UNITS, NATIVE_AOT_PROFILE_CONTRACT_REVISION, } from "../domain/native/nativeAotPe.js";
|
|
6
8
|
/** Resolve version-bound, deterministic semantics before Ghidra imports a target. */
|
|
7
|
-
export const resolveGhidraAnalysisProfile = (target, identity, installation, signal) => {
|
|
9
|
+
export const resolveGhidraAnalysisProfile = (target, identity, installation, signal, languageOverride) => {
|
|
8
10
|
if (signal?.aborted === true)
|
|
9
11
|
return Promise.resolve(err(new AnalysisCancelledError("open_binary")));
|
|
10
12
|
if (target.kind !== "executable")
|
|
11
13
|
return Promise.resolve(ok({ profile: null }));
|
|
12
14
|
if (installation.status === "unavailable")
|
|
13
15
|
return Promise.resolve(err(new ProviderAdapterError(identity.id, "resolve_analysis_profile")));
|
|
16
|
+
const mipsReason = ghidraMipsUnsupportedReason(target);
|
|
17
|
+
if (mipsReason !== null)
|
|
18
|
+
return Promise.resolve(err(new AnalysisUnsupportedTargetError("resolve_analysis_profile", target.path, mipsReason)));
|
|
14
19
|
const provider = { ...identity, version: installation.providerVersion };
|
|
15
20
|
const dosMz = target.format === "dos-mz";
|
|
16
21
|
const dosCom = target.format === "dos-com";
|
|
17
22
|
const dos = dosMz || dosCom;
|
|
23
|
+
// DOS imports already force an admitted loader, language, and context.
|
|
24
|
+
if (dos && languageOverride !== undefined)
|
|
25
|
+
return Promise.resolve(err(new AnalysisUnsupportedTargetError("resolve_analysis_profile", target.path, "REA_GHIDRA_LANGUAGE_ID cannot override the admitted DOS real-mode import.")));
|
|
18
26
|
return Promise.resolve(ok({
|
|
19
27
|
profile: createAnalysisProfile(provider, {
|
|
20
28
|
target_kind: target.kind,
|
|
21
29
|
target_format: target.format,
|
|
30
|
+
...(target.format === "pe"
|
|
31
|
+
? {
|
|
32
|
+
executable_role: target.executableRole ?? null,
|
|
33
|
+
managed: target.managed ?? null,
|
|
34
|
+
native_aot_metadata: {
|
|
35
|
+
contract_revision: NATIVE_AOT_PROFILE_CONTRACT_REVISION,
|
|
36
|
+
source_bytes: NATIVE_AOT_MAX_SOURCE_BYTES,
|
|
37
|
+
work_units: NATIVE_AOT_MAX_WORK_UNITS,
|
|
38
|
+
working_memory_bytes: NATIVE_AOT_MAX_WORKING_MEMORY_BYTES,
|
|
39
|
+
report_bytes: NATIVE_AOT_MAX_REPORT_BYTES,
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
: {}),
|
|
22
43
|
architecture: target.architecture ?? null,
|
|
23
44
|
available_architectures: [
|
|
24
45
|
...(target.availableArchitectures ?? []),
|
|
@@ -28,8 +49,13 @@ export const resolveGhidraAnalysisProfile = (target, identity, installation, sig
|
|
|
28
49
|
load_image_observations: "source-mappings-entry-context-v2",
|
|
29
50
|
function_body_evidence: "complete-inclusive-ranges-v1",
|
|
30
51
|
function_references: "complete-body-and-entry-reference-manager-v2",
|
|
52
|
+
string_inventory_evidence: "defined-data-coverage-v1",
|
|
31
53
|
location_resolution: "explicit-address-exact-entry-symbol-first-v3",
|
|
32
54
|
instruction_flow_evidence: "decoded-return-pcode-v1",
|
|
55
|
+
function_boundary_observations: "ghidra-terminal-call-limitations-v1",
|
|
56
|
+
no_return_repair: installation.platform === "win32"
|
|
57
|
+
? "disabled-windows-p0"
|
|
58
|
+
: "returning-imports-decoded-return-v2",
|
|
33
59
|
process_launch: installation.platform === "win32"
|
|
34
60
|
? "official-headless-script-v1"
|
|
35
61
|
: "inspected-jvm-launch-support-v1",
|
|
@@ -47,8 +73,17 @@ export const resolveGhidraAnalysisProfile = (target, identity, installation, sig
|
|
|
47
73
|
: dosCom
|
|
48
74
|
? "BinaryLoader"
|
|
49
75
|
: "auto-from-header",
|
|
50
|
-
language_id: dos
|
|
51
|
-
|
|
76
|
+
language_id: dos
|
|
77
|
+
? "x86:LE:16:Real Mode"
|
|
78
|
+
: (languageOverride?.languageId ?? "auto-from-header"),
|
|
79
|
+
compiler_spec_id: dos
|
|
80
|
+
? "default"
|
|
81
|
+
: languageOverride === undefined
|
|
82
|
+
? "auto-default"
|
|
83
|
+
: (languageOverride.compilerSpecId ?? "language-default"),
|
|
84
|
+
...(languageOverride === undefined
|
|
85
|
+
? {}
|
|
86
|
+
: { language_selection: "configured-v1" }),
|
|
52
87
|
...(dos
|
|
53
88
|
? {
|
|
54
89
|
load_segment: "0x1000",
|
|
@@ -68,6 +103,22 @@ export const resolveGhidraAnalysisProfile = (target, identity, installation, sig
|
|
|
68
103
|
}
|
|
69
104
|
: {}),
|
|
70
105
|
analyzer_preset: "ghidra-default",
|
|
106
|
+
...ghidraMipsProfileParameters(target),
|
|
71
107
|
}),
|
|
72
108
|
}));
|
|
73
109
|
};
|
|
110
|
+
/** Read the import-language commitment back from a resolved profile. */
|
|
111
|
+
export const ghidraProfileLanguageOverride = (parameters) => {
|
|
112
|
+
if (parameters.language_selection !== "configured-v1")
|
|
113
|
+
return undefined;
|
|
114
|
+
const languageId = parameters.language_id;
|
|
115
|
+
const compilerSpecId = parameters.compiler_spec_id;
|
|
116
|
+
if (typeof languageId !== "string" || typeof compilerSpecId !== "string")
|
|
117
|
+
return undefined;
|
|
118
|
+
return compilerSpecId === "language-default"
|
|
119
|
+
? { languageId }
|
|
120
|
+
: { languageId, compilerSpecId };
|
|
121
|
+
};
|
|
122
|
+
/** Whether a committed profile and the active configuration select the same language. */
|
|
123
|
+
export const sameGhidraLanguageOverride = (left, right) => left?.languageId === right?.languageId &&
|
|
124
|
+
left?.compilerSpecId === right?.compilerSpecId;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { mkdir, open, realpath, writeFile } from "node:fs/promises";
|
|
4
|
+
import { isAbsolute, join } from "node:path";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { ConfigurationError } from "../domain/configurationErrors.js";
|
|
7
|
+
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
|
|
8
|
+
import { err, ok } from "../domain/result.js";
|
|
9
|
+
/** Seed file format admitted by this adapter. */
|
|
10
|
+
export const GHIDRA_SEED_FORMAT = "rea-ghidra-seeds-v1";
|
|
11
|
+
export const GHIDRA_SEED_SCRIPT = "ReaGhidraApplySeeds.java";
|
|
12
|
+
export const MAX_GHIDRA_SEED_BYTES = 32 * 1024 * 1024;
|
|
13
|
+
export const MAX_GHIDRA_SEED_ENTRIES = 1_000_000;
|
|
14
|
+
const MAX_SEED_NAME_LENGTH = 2000;
|
|
15
|
+
const digest = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
16
|
+
const count = z.number().int().nonnegative();
|
|
17
|
+
/** Caller-declared seeds committed into the analysis profile before import. */
|
|
18
|
+
export const ghidraSeedCommitmentSchema = z.strictObject({
|
|
19
|
+
format: z.literal(GHIDRA_SEED_FORMAT),
|
|
20
|
+
path: z.string().refine(isAbsolute, "Seed path must be absolute"),
|
|
21
|
+
configured_path: z.string().refine(isAbsolute, "Seed path must be absolute"),
|
|
22
|
+
sha256: digest,
|
|
23
|
+
entries: z.strictObject({ function: count, code: count, label: count }),
|
|
24
|
+
});
|
|
25
|
+
/** What the pre-analysis script applied, as reported by the bridge handshake. */
|
|
26
|
+
export const ghidraSeedReportSchema = z.strictObject({
|
|
27
|
+
format: z.literal(GHIDRA_SEED_FORMAT),
|
|
28
|
+
sha256: digest,
|
|
29
|
+
entries: count,
|
|
30
|
+
function_created: count,
|
|
31
|
+
function_existing: count,
|
|
32
|
+
function_failed: count,
|
|
33
|
+
code_decoded: count,
|
|
34
|
+
code_failed: count,
|
|
35
|
+
label_applied: count,
|
|
36
|
+
label_failed: count,
|
|
37
|
+
unmapped: count,
|
|
38
|
+
});
|
|
39
|
+
const seedLineError = (line, constraint) => new ConfigurationError("Invalid REA environment configuration", {
|
|
40
|
+
settings: [
|
|
41
|
+
{
|
|
42
|
+
setting: "REA_GHIDRA_SEED_FILE",
|
|
43
|
+
constraint: `line ${line}: ${constraint}`,
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Parse `address<TAB>kind[<TAB>name]` lines. Blank lines and `#` comments are
|
|
49
|
+
* ignored. Addresses are hexadecimal offsets in the default address space.
|
|
50
|
+
*/
|
|
51
|
+
export const parseGhidraSeeds = (text) => {
|
|
52
|
+
const entries = [];
|
|
53
|
+
const seen = new Set();
|
|
54
|
+
const lines = text.split("\n");
|
|
55
|
+
for (const [index, raw] of lines.entries()) {
|
|
56
|
+
const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
|
|
57
|
+
if (line.trim() === "" || line.startsWith("#"))
|
|
58
|
+
continue;
|
|
59
|
+
const number = index + 1;
|
|
60
|
+
const fields = line.split("\t");
|
|
61
|
+
if (fields.length < 2 || fields.length > 3)
|
|
62
|
+
return err(seedLineError(number, "expected address<TAB>kind[<TAB>name]"));
|
|
63
|
+
const [address, kind, name] = fields;
|
|
64
|
+
if (address === undefined || !/^0x[0-9a-fA-F]{1,16}$/u.test(address))
|
|
65
|
+
return err(seedLineError(number, "address must be 0x-prefixed hex"));
|
|
66
|
+
if (kind !== "function" && kind !== "code" && kind !== "label")
|
|
67
|
+
return err(seedLineError(number, "kind must be function, code or label"));
|
|
68
|
+
if (name !== undefined &&
|
|
69
|
+
(name.length === 0 ||
|
|
70
|
+
name.length > MAX_SEED_NAME_LENGTH ||
|
|
71
|
+
/[\s\0]/u.test(name)))
|
|
72
|
+
return err(seedLineError(number, `name must be 1..${MAX_SEED_NAME_LENGTH} characters without whitespace`));
|
|
73
|
+
if (kind === "label" && name === undefined)
|
|
74
|
+
return err(seedLineError(number, "a label seed requires a name"));
|
|
75
|
+
if (kind === "code" && name !== undefined)
|
|
76
|
+
return err(seedLineError(number, "a code seed takes no name; add a label seed"));
|
|
77
|
+
const value = BigInt(address);
|
|
78
|
+
const key = `${value.toString(16)}:${kind}`;
|
|
79
|
+
if (seen.has(key))
|
|
80
|
+
return err(seedLineError(number, `duplicate ${kind} seed at ${address}`));
|
|
81
|
+
seen.add(key);
|
|
82
|
+
entries.push({
|
|
83
|
+
address: value,
|
|
84
|
+
kind,
|
|
85
|
+
...(name === undefined ? {} : { name }),
|
|
86
|
+
});
|
|
87
|
+
if (entries.length > MAX_GHIDRA_SEED_ENTRIES)
|
|
88
|
+
return err(seedLineError(number, `more than ${MAX_GHIDRA_SEED_ENTRIES} seed entries`));
|
|
89
|
+
}
|
|
90
|
+
return ok(entries);
|
|
91
|
+
};
|
|
92
|
+
/** Canonical script input: lowercase addresses, fixed field order, LF endings. */
|
|
93
|
+
const normalizedSeeds = (entries) => entries
|
|
94
|
+
.map((entry) => `0x${entry.address.toString(16)}\t${entry.kind}${entry.name === undefined ? "" : `\t${entry.name}`}\n`)
|
|
95
|
+
.join("");
|
|
96
|
+
/** Read a bounded regular file through one handle without following links. */
|
|
97
|
+
const readSeedFile = async (path) => {
|
|
98
|
+
const file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
99
|
+
try {
|
|
100
|
+
const stat = await file.stat();
|
|
101
|
+
if (!stat.isFile() || stat.size > MAX_GHIDRA_SEED_BYTES)
|
|
102
|
+
throw new Error(`Ghidra seed file must be a regular file of at most ${MAX_GHIDRA_SEED_BYTES} bytes: ${path}`);
|
|
103
|
+
const bytes = Buffer.alloc(stat.size);
|
|
104
|
+
let offset = 0;
|
|
105
|
+
while (offset < bytes.length) {
|
|
106
|
+
const read = await file.read(bytes, offset, bytes.length - offset, offset);
|
|
107
|
+
if (read.bytesRead === 0)
|
|
108
|
+
throw new Error(`Incomplete Ghidra seed file read: ${path}`);
|
|
109
|
+
offset += read.bytesRead;
|
|
110
|
+
}
|
|
111
|
+
return bytes;
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
await file.close();
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const sha256 = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
|
118
|
+
const decodeSeeds = (bytes) => {
|
|
119
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
120
|
+
return parseGhidraSeeds(text);
|
|
121
|
+
};
|
|
122
|
+
/** Resolve the configured seed file into an immutable profile commitment. */
|
|
123
|
+
export const resolveGhidraAnalysisSeeds = async (configured) => {
|
|
124
|
+
if (configured === undefined)
|
|
125
|
+
return ok(undefined);
|
|
126
|
+
let bytes;
|
|
127
|
+
let path;
|
|
128
|
+
try {
|
|
129
|
+
path = await realpath(configured);
|
|
130
|
+
bytes = await readSeedFile(path);
|
|
131
|
+
}
|
|
132
|
+
catch (cause) {
|
|
133
|
+
return err(new ProviderAdapterError("ghidra", "resolve_analysis_profile", {
|
|
134
|
+
cause,
|
|
135
|
+
diagnostics: {
|
|
136
|
+
setting: "REA_GHIDRA_SEED_FILE",
|
|
137
|
+
path: configured,
|
|
138
|
+
reason: cause instanceof Error ? cause.message : String(cause),
|
|
139
|
+
},
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
let parsed;
|
|
143
|
+
try {
|
|
144
|
+
parsed = decodeSeeds(bytes);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return err(seedLineError(0, "file is not valid UTF-8"));
|
|
148
|
+
}
|
|
149
|
+
if (!parsed.ok)
|
|
150
|
+
return parsed;
|
|
151
|
+
const normalized = normalizedSeeds(parsed.value);
|
|
152
|
+
const tally = { function: 0, code: 0, label: 0 };
|
|
153
|
+
for (const entry of parsed.value)
|
|
154
|
+
tally[entry.kind] += 1;
|
|
155
|
+
return ok({
|
|
156
|
+
format: GHIDRA_SEED_FORMAT,
|
|
157
|
+
path,
|
|
158
|
+
configured_path: configured,
|
|
159
|
+
sha256: sha256(normalized),
|
|
160
|
+
entries: tally,
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
/** Re-read the committed seeds and write the canonical copy the script applies. */
|
|
164
|
+
export const snapshotGhidraAnalysisSeeds = async (commitment, runtimeRoot) => {
|
|
165
|
+
ghidraSeedCommitmentSchema.parse(commitment);
|
|
166
|
+
if ((await realpath(commitment.configured_path)) !== commitment.path)
|
|
167
|
+
throw new Error("Ghidra seed file resolved path differs from explicit configuration");
|
|
168
|
+
const parsed = decodeSeeds(await readSeedFile(commitment.path));
|
|
169
|
+
if (!parsed.ok)
|
|
170
|
+
throw parsed.error;
|
|
171
|
+
const normalized = normalizedSeeds(parsed.value);
|
|
172
|
+
if (sha256(normalized) !== commitment.sha256)
|
|
173
|
+
throw new Error(`Ghidra seed file changed after the analysis profile was committed: ${commitment.path}`);
|
|
174
|
+
const directory = join(runtimeRoot, "seeds");
|
|
175
|
+
await mkdir(directory, { mode: 0o700 });
|
|
176
|
+
const path = join(directory, "seeds.tsv");
|
|
177
|
+
await writeFile(path, normalized, { flag: "wx", mode: 0o600 });
|
|
178
|
+
return path;
|
|
179
|
+
};
|
|
180
|
+
const totalEntries = (commitment) => commitment.entries.function +
|
|
181
|
+
commitment.entries.code +
|
|
182
|
+
commitment.entries.label;
|
|
183
|
+
/** Fail closed when the session did not apply exactly the committed seeds. */
|
|
184
|
+
export const ghidraSeedFailure = (commitment, report, operation) => {
|
|
185
|
+
if (commitment === undefined && report === undefined)
|
|
186
|
+
return undefined;
|
|
187
|
+
const reason = commitment === undefined
|
|
188
|
+
? "The Ghidra session reported analysis seeds that the profile did not commit."
|
|
189
|
+
: report === undefined
|
|
190
|
+
? "The Ghidra session did not report the committed analysis seeds."
|
|
191
|
+
: report.sha256 !== commitment.sha256 ||
|
|
192
|
+
report.entries !== totalEntries(commitment)
|
|
193
|
+
? "The Ghidra session applied analysis seeds that differ from the committed profile."
|
|
194
|
+
: undefined;
|
|
195
|
+
return reason === undefined
|
|
196
|
+
? undefined
|
|
197
|
+
: new ProviderAdapterError("ghidra", operation, {
|
|
198
|
+
diagnostics: { reason },
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
/** Session limitations that keep seeded facts distinct from Ghidra discoveries. */
|
|
202
|
+
export const ghidraSeedLimitations = (commitment, report) => commitment === undefined
|
|
203
|
+
? []
|
|
204
|
+
: [
|
|
205
|
+
`Ghidra analysis was seeded before auto-analysis from ${commitment.path} (sha256 ${commitment.sha256}: ${commitment.entries.function} function, ${commitment.entries.code} code, ${commitment.entries.label} label entries). Seeded functions, code and names are caller assertions, not Ghidra discoveries.`,
|
|
206
|
+
...(report === undefined
|
|
207
|
+
? []
|
|
208
|
+
: [
|
|
209
|
+
`Seed outcome: ${report.function_created} functions created, ${report.function_existing} already present, ${report.function_failed} failed; ${report.code_decoded} code seeds decoded, ${report.code_failed} failed; ${report.label_applied} labels applied, ${report.label_failed} failed; ${report.unmapped} seeds outside initialized memory.`,
|
|
210
|
+
]),
|
|
211
|
+
];
|
|
@@ -9,7 +9,7 @@ import { ProviderStartupDeadline } from "../process/ProviderDeadline.js";
|
|
|
9
9
|
import { ProviderRunLineage } from "../process/ProviderRunLineage.js";
|
|
10
10
|
import { ProviderProcessSupervisor, } from "../process/ProviderProcess.js";
|
|
11
11
|
import { DEFAULT_GHIDRA_STARTUP_TIMEOUT_MS } from "../config/ghidraStartupTimeout.js";
|
|
12
|
-
import { createGhidraDiagnostics } from "./GhidraDiagnostics.js";
|
|
12
|
+
import { createGhidraDiagnostics, GHIDRA_PROCESS_DIAGNOSTIC_BYTES, } from "./GhidraDiagnostics.js";
|
|
13
13
|
import { GhidraLaunchError } from "./GhidraLauncher.js";
|
|
14
14
|
import { GhidraResponseBuffer } from "./GhidraResponseBuffer.js";
|
|
15
15
|
import { GhidraResponseRouter } from "./GhidraResponseRouter.js";
|
|
@@ -18,6 +18,9 @@ import { bindGhidraSessionFailure, GhidraSessionError, } from "./GhidraSessionEr
|
|
|
18
18
|
import { isGhidraShutdownAcknowledgement, parseGhidraSessionInfo, } from "./GhidraSessionValues.js";
|
|
19
19
|
import { createGhidraTargetSnapshot } from "./GhidraTargetSnapshot.js";
|
|
20
20
|
import { readFile } from "node:fs/promises";
|
|
21
|
+
import { readBoundedFileBytes } from "../process/BoundedFileBytes.js";
|
|
22
|
+
import { openRegularFile, RegularFileChangedError, sameRegularFileState, } from "../filesystem/RegularFile.js";
|
|
23
|
+
import { OwnedFileHandle } from "../filesystem/OwnedFileHandle.js";
|
|
21
24
|
import { connectGhidraSocket } from "./GhidraSocketConnection.js";
|
|
22
25
|
import { createGhidraEndpoint, } from "./GhidraTransport.js";
|
|
23
26
|
import { GhidraWire } from "./GhidraClientWire.js";
|
|
@@ -38,6 +41,7 @@ export class GhidraClient {
|
|
|
38
41
|
#socketRoot;
|
|
39
42
|
#endpointPath;
|
|
40
43
|
#snapshotPath;
|
|
44
|
+
#snapshotOwners = new Set();
|
|
41
45
|
#targetAdmission;
|
|
42
46
|
#token;
|
|
43
47
|
// Retain authentication identities for diagnostics from late request settlement.
|
|
@@ -147,14 +151,76 @@ export class GhidraClient {
|
|
|
147
151
|
return this.#requestQueue.run(operation, parameters, options.signal === undefined ? {} : { signal: options.signal });
|
|
148
152
|
}
|
|
149
153
|
/** Read the private immutable source for independent import verification. */
|
|
150
|
-
async readTargetSnapshot() {
|
|
154
|
+
async readTargetSnapshot(maximumBytes, signal) {
|
|
151
155
|
if (this.#snapshotPath === undefined)
|
|
152
156
|
return err(this.#failure("protocol", "Ghidra target snapshot is unavailable before startup or after close"));
|
|
153
157
|
try {
|
|
154
|
-
|
|
158
|
+
if (maximumBytes !== undefined) {
|
|
159
|
+
signal?.throwIfAborted();
|
|
160
|
+
if (!Number.isSafeInteger(maximumBytes) || maximumBytes < 0)
|
|
161
|
+
throw new RangeError("Snapshot byte limit must be a safe integer");
|
|
162
|
+
const handle = await openRegularFile(this.#snapshotPath, {
|
|
163
|
+
symlinks: "reject",
|
|
164
|
+
});
|
|
165
|
+
const owner = new OwnedFileHandle(handle);
|
|
166
|
+
this.#snapshotOwners.add(owner);
|
|
167
|
+
let result;
|
|
168
|
+
let readFailure;
|
|
169
|
+
try {
|
|
170
|
+
const metadata = await handle.stat();
|
|
171
|
+
signal?.throwIfAborted();
|
|
172
|
+
if (metadata.size > maximumBytes)
|
|
173
|
+
result = {
|
|
174
|
+
kind: "over-capacity",
|
|
175
|
+
sourceBytesAtLeast: metadata.size,
|
|
176
|
+
maximumBytes,
|
|
177
|
+
};
|
|
178
|
+
else {
|
|
179
|
+
const bytes = await readBoundedFileBytes(handle, maximumBytes, signal, metadata.size);
|
|
180
|
+
signal?.throwIfAborted();
|
|
181
|
+
const after = await handle.stat();
|
|
182
|
+
if (bytes !== undefined &&
|
|
183
|
+
bytes.length === metadata.size &&
|
|
184
|
+
sameRegularFileState(metadata, after)) {
|
|
185
|
+
result = { kind: "captured", bytes };
|
|
186
|
+
}
|
|
187
|
+
else if (bytes === undefined &&
|
|
188
|
+
after.isFile() &&
|
|
189
|
+
after.size > maximumBytes) {
|
|
190
|
+
result = {
|
|
191
|
+
kind: "over-capacity",
|
|
192
|
+
sourceBytesAtLeast: after.size,
|
|
193
|
+
maximumBytes,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
throw new RegularFileChangedError(this.#snapshotPath);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch (cause) {
|
|
202
|
+
readFailure = cause;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
await owner.close();
|
|
206
|
+
this.#snapshotOwners.delete(owner);
|
|
207
|
+
}
|
|
208
|
+
catch (closeFailure) {
|
|
209
|
+
throw new AggregateError(readFailure === undefined
|
|
210
|
+
? [closeFailure]
|
|
211
|
+
: [readFailure, closeFailure], "Ghidra target snapshot read or descriptor cleanup failed");
|
|
212
|
+
}
|
|
213
|
+
if (readFailure !== undefined)
|
|
214
|
+
throw readFailure;
|
|
215
|
+
return ok(result);
|
|
216
|
+
}
|
|
217
|
+
return ok({
|
|
218
|
+
kind: "captured",
|
|
219
|
+
bytes: await readFile(this.#snapshotPath),
|
|
220
|
+
});
|
|
155
221
|
}
|
|
156
222
|
catch (cause) {
|
|
157
|
-
return err(this.#failure("protocol", "Ghidra target snapshot could not be read for load-image verification", cause));
|
|
223
|
+
return err(this.#failure(signal?.aborted === true ? "cancelled" : "protocol", "Ghidra target snapshot could not be read for load-image verification", cause));
|
|
158
224
|
}
|
|
159
225
|
}
|
|
160
226
|
/** Stop the owned process group and remove all project/runtime artifacts. */
|
|
@@ -297,6 +363,7 @@ export class GhidraClient {
|
|
|
297
363
|
if (partialLaunch !== undefined) {
|
|
298
364
|
this.#launch = partialLaunch;
|
|
299
365
|
this.#process = new ProviderProcessSupervisor(partialLaunch, {
|
|
366
|
+
maxDiagnosticBytes: GHIDRA_PROCESS_DIAGNOSTIC_BYTES,
|
|
300
367
|
onDiagnostic: (event) => this.#onProcessDiagnostic(event),
|
|
301
368
|
});
|
|
302
369
|
}
|
|
@@ -309,6 +376,7 @@ export class GhidraClient {
|
|
|
309
376
|
}
|
|
310
377
|
this.#launch = launched.value;
|
|
311
378
|
this.#process = new ProviderProcessSupervisor(launched.value, {
|
|
379
|
+
maxDiagnosticBytes: GHIDRA_PROCESS_DIAGNOSTIC_BYTES,
|
|
312
380
|
onDiagnostic: (event) => this.#onProcessDiagnostic(event),
|
|
313
381
|
});
|
|
314
382
|
const connected = await this.#connect(endpoint, deadline);
|
|
@@ -433,6 +501,10 @@ export class GhidraClient {
|
|
|
433
501
|
this.#lastDiagnostics = this.#diagnostics();
|
|
434
502
|
this.#process = undefined;
|
|
435
503
|
this.#launch = undefined;
|
|
504
|
+
for (const owner of this.#snapshotOwners) {
|
|
505
|
+
await owner.close();
|
|
506
|
+
this.#snapshotOwners.delete(owner);
|
|
507
|
+
}
|
|
436
508
|
try {
|
|
437
509
|
await this.#removeRuntimeRoots();
|
|
438
510
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import { redactCapturedTransportCredential } from "../process/ProviderDiagnosticRedaction.js";
|
|
2
|
+
/** Aggregate in-memory retention budget for this provider's launcher output. */
|
|
3
|
+
export const GHIDRA_PROCESS_DIAGNOSTIC_BYTES = 8 * 1024 * 1024;
|
|
1
4
|
/** Preserve actionable runtime coordinates after cleanup and redact bearer data. */
|
|
2
5
|
export const createGhidraDiagnostics = (options) => {
|
|
3
6
|
if (options.runtimeRoot === undefined &&
|
|
4
7
|
options.launch === undefined &&
|
|
5
8
|
Object.keys(options.previous).length > 0)
|
|
6
9
|
return options.previous;
|
|
7
|
-
const redacted = (value) => options.token === undefined
|
|
8
|
-
? value
|
|
9
|
-
: value.replaceAll(options.token, "[REDACTED]");
|
|
10
10
|
return {
|
|
11
11
|
target_path: options.targetPath,
|
|
12
12
|
target_sha256: options.targetSha256,
|
|
@@ -39,12 +39,15 @@ export const createGhidraDiagnostics = (options) => {
|
|
|
39
39
|
: {
|
|
40
40
|
exit_code: options.snapshot.exitCode ?? null,
|
|
41
41
|
exit_signal: options.snapshot.signal ?? null,
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
diagnostic_truncated: options.snapshot.diagnosticTruncated === true,
|
|
43
|
+
stdout: boundedStream(options.snapshot.stdout, options.token),
|
|
44
|
+
stderr: boundedStream(options.snapshot.stderr, options.token),
|
|
44
45
|
}),
|
|
45
46
|
};
|
|
46
47
|
};
|
|
47
|
-
const boundedStream = (stream,
|
|
48
|
-
text:
|
|
49
|
-
|
|
48
|
+
const boundedStream = (stream, token) => ({
|
|
49
|
+
text: redactCapturedTransportCredential(stream, token, "[REDACTED]"),
|
|
50
|
+
// Preserve the historical total-byte counter; text is now bounded separately.
|
|
51
|
+
bytes: stream.observedBytes,
|
|
52
|
+
retained_bytes: stream.bytes,
|
|
50
53
|
});
|
|
@@ -285,11 +285,35 @@ const resultSchemas = {
|
|
|
285
285
|
procedure_references: procedureReferences,
|
|
286
286
|
xrefs: z.array(ghidraCanonicalAddressSchema),
|
|
287
287
|
};
|
|
288
|
+
const functionBoundaryObservationOperations = new Set([
|
|
289
|
+
"analyze_function",
|
|
290
|
+
"procedure_assembly",
|
|
291
|
+
"procedure_info",
|
|
292
|
+
"procedure_pseudo_code",
|
|
293
|
+
"read_function_instructions",
|
|
294
|
+
]);
|
|
295
|
+
const functionObservationEnvelope = z.strictObject({
|
|
296
|
+
value: z.unknown(),
|
|
297
|
+
limitations: z.array(z.string()),
|
|
298
|
+
});
|
|
288
299
|
/** Require exact, bounded Java-bridge function output before creating Evidence. */
|
|
289
300
|
export const parseGhidraFunctionResult = (operation, value) => {
|
|
290
|
-
|
|
301
|
+
let observation;
|
|
302
|
+
if (functionBoundaryObservationOperations.has(operation)) {
|
|
303
|
+
const envelope = functionObservationEnvelope.safeParse(value);
|
|
304
|
+
if (!envelope.success)
|
|
305
|
+
return err(new AnalysisOutputError(operation, "Ghidra bridge omitted the function observation envelope", { cause: envelope.error }));
|
|
306
|
+
observation = envelope.data;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
observation = { value, limitations: [] };
|
|
310
|
+
}
|
|
311
|
+
const parsed = resultSchemas[operation].safeParse(observation.value);
|
|
291
312
|
return parsed.success
|
|
292
|
-
? ok(
|
|
313
|
+
? ok({
|
|
314
|
+
value: jsonValueSchema.parse(parsed.data),
|
|
315
|
+
limitations: observation.limitations,
|
|
316
|
+
})
|
|
293
317
|
: err(new AnalysisOutputError(operation, "Ghidra bridge output did not match the function-analysis contract", { cause: parsed.error }));
|
|
294
318
|
};
|
|
295
319
|
const referenceAddresses = (edge) => [
|
|
@@ -53,7 +53,7 @@ const assessNativeDecompiler = (path, platform, architecture, probe) => {
|
|
|
53
53
|
continue;
|
|
54
54
|
const alternative = parseExecutableHeader(probe.bytes, node, probe.size);
|
|
55
55
|
if (alternative.ok &&
|
|
56
|
-
!alternative.value.availableArchitectures.
|
|
56
|
+
!alternative.value.availableArchitectures.some((available) => available === expectedArchitecture)) {
|
|
57
57
|
parsed = alternative;
|
|
58
58
|
break;
|
|
59
59
|
}
|
|
@@ -5,7 +5,10 @@ import { functionBodySchema, functionBodyEntryAgrees, } from "../domain/hopperVa
|
|
|
5
5
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
6
6
|
import { err, ok } from "../domain/result.js";
|
|
7
7
|
import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js";
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Direct inventory operations admitted by the Ghidra adapter. All are reads
|
|
10
|
+
* except the naming operations, which edit the ephemeral session database.
|
|
11
|
+
*/
|
|
9
12
|
export const GHIDRA_INVENTORY_OPERATIONS = [
|
|
10
13
|
"inspect_native_load_image",
|
|
11
14
|
"read_bytes",
|
|
@@ -20,6 +23,13 @@ export const GHIDRA_INVENTORY_OPERATIONS = [
|
|
|
20
23
|
"resolve_containing_procedure",
|
|
21
24
|
"search_procedures",
|
|
22
25
|
"search_strings",
|
|
26
|
+
"set_address_name",
|
|
27
|
+
"set_addresses_names",
|
|
28
|
+
];
|
|
29
|
+
/** Inventory operations that write analyst names into the session database. */
|
|
30
|
+
export const GHIDRA_NAMING_OPERATIONS = [
|
|
31
|
+
"set_address_name",
|
|
32
|
+
"set_addresses_names",
|
|
23
33
|
];
|
|
24
34
|
const operationSet = new Set(GHIDRA_INVENTORY_OPERATIONS);
|
|
25
35
|
/** Narrow an application operation to the Ghidra inventory surface. */
|
|
@@ -62,6 +72,16 @@ const inputSchemas = {
|
|
|
62
72
|
.strict(),
|
|
63
73
|
search_procedures: z.object(searchInput).strict(),
|
|
64
74
|
search_strings: z.object(searchInput).strict(),
|
|
75
|
+
set_address_name: z
|
|
76
|
+
.object({ document, address: explicitAddress, name: z.string().min(1) })
|
|
77
|
+
.strict(),
|
|
78
|
+
set_addresses_names: z
|
|
79
|
+
.object({
|
|
80
|
+
document,
|
|
81
|
+
names: z.record(explicitAddress, z.string().min(1)),
|
|
82
|
+
})
|
|
83
|
+
.strict()
|
|
84
|
+
.refine((value) => Object.keys(value.names).length > 0, "Supply at least one address name"),
|
|
65
85
|
};
|
|
66
86
|
/** Validate and default one provider request before it crosses the socket. */
|
|
67
87
|
export const parseGhidraInventoryInput = (operation, value) => {
|
|
@@ -230,6 +250,8 @@ const resultSchemas = {
|
|
|
230
250
|
resolve_containing_procedure: containingProcedure,
|
|
231
251
|
search_procedures: z.array(searchItem),
|
|
232
252
|
search_strings: z.array(searchItem),
|
|
253
|
+
set_address_name: z.boolean(),
|
|
254
|
+
set_addresses_names: z.record(z.string(), z.boolean()),
|
|
233
255
|
};
|
|
234
256
|
/** Validate exact Java-bridge output before creating Evidence. */
|
|
235
257
|
export const parseGhidraInventoryResult = (operation, value) => {
|