rea-agents 6.2.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 +24 -23
- package/bridge/ghidra/ReaGhidraApplySeeds.java +151 -0
- package/bridge/ghidra/ReaGhidraBridge.java +597 -209
- package/bridge/ghidra/ReaGhidraNoReturnFix.java +123 -0
- package/bridge/hopper_bridge.py +2 -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 +59 -21
- package/dist/android/JadxSession.js +51 -9
- 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 +85 -19
- package/dist/application/BrowserScenarioEvidence.js +2 -2
- package/dist/application/CapabilityInventory.js +11 -1
- package/dist/application/ClientConfigurationDocument.js +98 -0
- package/dist/application/ClientConfigurationFiles.js +91 -0
- package/dist/application/ClientRegistrationEnvironment.js +35 -0
- package/dist/application/ClientRegistrationStatus.js +75 -27
- package/dist/application/DirectAnalysis.js +14 -8
- package/dist/application/DirectAnalysisCleanup.js +1 -2
- package/dist/application/DirectAnalysisStatus.js +3 -6
- package/dist/application/Doctor.js +27 -34
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleCommands.js +6 -12
- package/dist/application/EvidenceBundleFiles.js +1 -1
- 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 +10 -4
- package/dist/application/JsonFiles.js +16 -15
- package/dist/application/JsonInputFile.js +252 -0
- package/dist/application/LinuxHopper.js +6 -13
- 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 +16 -3
- package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
- 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 +103 -0
- package/dist/application/Setup.js +69 -10
- package/dist/application/SetupClientConfiguration.js +134 -23
- package/dist/application/SetupHost.js +102 -22
- package/dist/application/SetupPlan.js +18 -17
- package/dist/application/SetupSkill.js +81 -13
- package/dist/application/SupportedClients.js +305 -37
- package/dist/application/Uninstall.js +172 -8
- package/dist/application/UpdateMaintenance.js +23 -23
- package/dist/application/Utf8JsonInput.js +71 -0
- package/dist/application/WebScriptExportService.js +130 -57
- 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/android/AndroidAnalysisService.js +1 -1
- 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/AnalysisSnapshotCache.js +5 -4
- package/dist/application/binary/BinarySession.js +18 -1
- package/dist/application/binary/BinarySessionOpen.js +9 -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/ElectronActiveEvidence.js +2 -2
- package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphContext.js +3 -2
- package/dist/application/javascript/ElectronBoundaryGraphIpc.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +20 -3
- package/dist/application/javascript/ElectronBoundaryGraphWindows.js +3 -3
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
- package/dist/application/javascript/JavaScriptApplicationService.js +23 -11
- package/dist/application/javascript/JavaScriptApplicationWorkflowEvidence.js +5 -6
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +171 -36
- package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +14 -16
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +74 -36
- package/dist/application/javascript/JavaScriptArtifactGraphBundlers.js +4 -3
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +11 -5
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +53 -42
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +92 -10
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +293 -238
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +120 -28
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +4 -0
- package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
- package/dist/application/javascript/JavaScriptModuleRelationships.js +10 -20
- package/dist/application/javascript/JavaScriptRecoveryService.js +3 -0
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +11 -5
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +206 -66
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +18 -23
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +5 -2
- package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +7 -5
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +6 -4
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +29 -15
- package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
- 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/NativeCallRoutes.js +2 -4
- 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 +34 -31
- package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
- package/dist/artifacts/ArtifactReader.js +23 -0
- package/dist/artifacts/ArtifactResourceScope.js +100 -0
- package/dist/artifacts/AsarArtifactReader.js +218 -80
- 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 +179 -87
- package/dist/artifacts/NativeDmgOwnership.js +109 -0
- 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 +76 -49
- package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
- package/dist/artifacts/extraction/ArtifactExtraction.js +134 -92
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +116 -50
- package/dist/artifacts/inventory/ArtifactInventory.js +5 -4
- package/dist/artifacts/inventory/classify.js +87 -25
- package/dist/artifacts/inventory/hashStableRootArtifact.js +70 -0
- package/dist/artifacts/inventory/reader.js +13 -5
- package/dist/artifacts/inventory/scanCanonical.js +73 -30
- package/dist/artifacts/inventory/scanReader.js +43 -20
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +72 -28
- 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 +9 -3
- 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/CdpCaptureStorageFingerprints.js +3 -3
- package/dist/browser/CdpConnection.js +22 -5
- package/dist/browser/CdpElectronInspection.js +2 -2
- package/dist/browser/CdpElectronProvider.js +4 -3
- package/dist/browser/CdpElectronScripts.js +2 -2
- package/dist/browser/CdpPageCapture.js +1 -1
- package/dist/browser/CdpTargetSession.js +30 -34
- package/dist/browser/CdpWebMcpDiscovery.js +48 -23
- package/dist/browser/ElectronFileScope.js +99 -9
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +63 -7
- package/dist/browser/PlaywrightElectronActiveProvider.js +11 -6
- package/dist/browser/PlaywrightScenarioArtifacts.js +5 -5
- package/dist/browser/PlaywrightScenarioBrowser.js +208 -43
- package/dist/browser/PlaywrightScenarioSession.js +130 -65
- package/dist/browser/PlaywrightScenarioStorage.js +507 -0
- package/dist/browser/PngVisualDiff.js +198 -29
- package/dist/browser/WebSourceMapFetcher.js +35 -9
- package/dist/browser/assets/LocalWebScriptArtifacts.js +3 -1
- package/dist/browser/assets/PublishWebScripts.js +75 -20
- package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
- 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/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +12 -13
- package/dist/cli/coreNativeCommands.js +1 -14
- package/dist/cli/electronCommands.js +14 -10
- package/dist/cli/evmCommands.js +13 -4
- package/dist/cli/firmwareCommands.js +7 -2
- package/dist/cli/javascriptApplicationAnalysis.js +19 -13
- package/dist/cli/javascriptRecoveryCommands.js +22 -15
- package/dist/cli/jebCommands.js +99 -0
- package/dist/cli/jsonOutput.js +12 -4
- package/dist/cli/referenceSourceImportStatus.js +7 -0
- package/dist/cli/setupCommands.js +15 -3
- package/dist/cli/streamedJsonOutput.js +83 -4
- package/dist/cli/utilityCommands.js +68 -22
- package/dist/cli/webScriptCommands.js +20 -1
- package/dist/cli/webSourceLocationCommands.js +21 -9
- package/dist/cli.js +11 -2
- package/dist/cliBrowserScenarioCommands.js +2 -1
- package/dist/cliCommandNames.js +32 -0
- package/dist/cliJsonInput.js +47 -34
- package/dist/cliObservationOptions.js +7 -0
- package/dist/composition/adb.js +3 -0
- package/dist/composition/apktool.js +3 -0
- package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
- package/dist/composition/binaryDiagnostics.js +4 -0
- package/dist/composition/browserScenario.js +2 -2
- package/dist/composition/directAnalysis.js +14 -7
- 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/artifactComparisonExample.js +5 -5
- package/dist/contracts/artifactToolContracts.js +8 -5
- package/dist/contracts/browserToolContracts.js +1 -1
- package/dist/contracts/compactInputSchema.js +256 -0
- package/dist/contracts/errorSchemas.js +3 -1
- package/dist/contracts/functionComparisonExample.js +8 -0
- package/dist/contracts/functionWorkflowToolContracts.js +1 -1
- package/dist/contracts/inputSchemaPresentation.js +104 -13
- package/dist/contracts/javascript/electronToolContracts.js +16 -3
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
- package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +1 -1
- package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
- package/dist/contracts/jeb/jebToolContracts.js +64 -0
- package/dist/contracts/managed/managedToolContracts.js +3 -2
- package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +25 -3
- package/dist/contracts/native/nativeToolContracts.js +1 -1
- package/dist/contracts/officialToolContracts.js +5 -5
- package/dist/contracts/sessionLifecycleInputs.js +4 -3
- package/dist/contracts/sessionStatusContract.js +3 -2
- package/dist/contracts/sessionToolContracts.js +5 -4
- package/dist/contracts/sessionToolSchemas.js +9 -4
- 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 +7 -5
- package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
- package/dist/contracts/toolSchemaMetadata.js +82 -7
- package/dist/domain/adb/adbDeviceAnalysis.js +583 -0
- package/dist/domain/analysisErrorBase.js +5 -0
- package/dist/domain/analysisErrorCleanup.js +29 -0
- package/dist/domain/analysisErrorPresentation.js +18 -4
- package/dist/domain/analysisErrorProjection.js +4 -1
- package/dist/domain/analysisSnapshot.js +5 -2
- package/dist/domain/analysisView/analysisView.js +53 -5
- 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/android/androidPartialObservation.js +36 -0
- 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 +3 -3
- package/dist/domain/apple/interfaceBuilderGraph.js +22 -19
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +10 -1
- package/dist/domain/artifactComparison.js +39 -11
- package/dist/domain/artifactGraph.js +6 -4
- package/dist/domain/artifactIdentity.js +37 -9
- package/dist/domain/artifactInspection.js +10 -50
- package/dist/domain/artifactIntegrityPolicy.js +10 -0
- package/dist/domain/artifactInventoryEvidence.js +16 -17
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/binaryTarget.js +16 -0
- package/dist/domain/binaryTargetTypes.js +8 -1
- package/dist/domain/browserCompleteness.js +3 -2
- package/dist/domain/browserObservationSchemas.js +8 -4
- package/dist/domain/browserScenarioCaptureValues.js +2 -2
- package/dist/domain/browserScenarioNormalization.js +3 -3
- package/dist/domain/browserScenarioValues.js +3 -2
- package/dist/domain/callPath.js +8 -10
- package/dist/domain/canonicalDigest.js +7 -1
- package/dist/domain/canonicalJsonDigestSteps.js +34 -12
- package/dist/domain/canonicalOrdering.js +1 -13
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/compactStringIdentity.js +9 -0
- package/dist/domain/comparisonSemantics.js +0 -5
- package/dist/domain/digests.js +0 -3
- package/dist/domain/evidence.js +12 -6
- package/dist/domain/evidenceBundle.js +51 -33
- package/dist/domain/evidenceRecordSummary.js +144 -0
- package/dist/domain/firmware/firmwareAnalysis.js +4 -3
- package/dist/domain/functionComparison.js +2 -1
- package/dist/domain/functionComparisonNormalization.js +4 -3
- package/dist/domain/functionComparisonResults.js +2 -2
- package/dist/domain/functionDossierEvidence.js +2 -1
- package/dist/domain/hopperValues.js +11 -15
- package/dist/domain/inputIssueProjection.js +16 -1
- package/dist/domain/javascript/electronActiveObservation.js +4 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +14 -15
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +20 -21
- package/dist/domain/javascript/electronStaticAnalysisNative.js +73 -41
- package/dist/domain/javascript/electronStaticAnalysisValues.js +24 -4
- package/dist/domain/javascript/javascriptAnalysisResourceControls.js +45 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +6 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +18 -14
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +91 -28
- package/dist/domain/javascript/javascriptApplicationProjectionResources.js +35 -0
- package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
- package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +72 -45
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +16 -8
- package/dist/domain/javascript/javascriptAstFingerprint.js +60 -33
- package/dist/domain/javascript/javascriptAstValues.js +54 -0
- package/dist/domain/javascript/javascriptElectronMemberWrites.js +50 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
- package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
- package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
- package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
- package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
- package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
- package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
- package/dist/domain/javascript/javascriptModuleSemanticIr.js +15 -0
- package/dist/domain/javascript/javascriptNativeHandoff.js +12 -7
- package/dist/domain/javascript/javascriptRpcEndpoints.js +253 -0
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +1 -3
- package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
- package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
- package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +12 -6
- package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
- package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +15 -17
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +379 -30
- package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
- package/dist/domain/javascript/javascriptSemanticCallableResults.js +42 -0
- package/dist/domain/javascript/javascriptSemanticCalls.js +8 -1
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
- package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +15 -4
- package/dist/domain/javascript/javascriptSemanticFileProjection.js +1 -0
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +43 -42
- package/dist/domain/javascript/javascriptSemanticGraph.js +205 -52
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +21 -11
- package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +139 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +774 -136
- package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +98 -41
- package/dist/domain/javascript/javascriptSemanticObjectReferences.js +381 -0
- package/dist/domain/javascript/javascriptSemanticObjects.js +9 -7
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
- package/dist/domain/javascript/javascriptSemanticProjection.js +72 -28
- package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +100 -0
- package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
- package/dist/domain/javascript/javascriptSemanticQuery.js +33 -29
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +4 -5
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
- package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
- package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +219 -0
- package/dist/domain/javascript/javascriptSemanticReturns.js +34 -48
- package/dist/domain/javascript/javascriptSemanticState.js +22 -2
- package/dist/domain/javascript/javascriptSemanticTraversal.js +25 -2
- package/dist/domain/javascript/javascriptSemanticValues.js +169 -30
- package/dist/domain/javascript/javascriptSourceAnalysis.js +1 -0
- package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
- package/dist/domain/javascript/javascriptSourceParser.js +34 -9
- package/dist/domain/javascript/javascriptStaticAnalysis.js +29 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +13 -12
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +49 -5
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +8 -4
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +1 -0
- package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
- package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
- package/dist/domain/jeb/jebAnalysis.js +114 -0
- package/dist/domain/jsonSerialization.js +109 -55
- package/dist/domain/jsonShape.js +69 -31
- package/dist/domain/jsonValue.js +3 -0
- package/dist/domain/localPath.js +10 -4
- package/dist/domain/managed/managedApplicationGraph.js +47 -6
- package/dist/domain/managed/managedApplicationGraphCoverage.js +8 -2
- package/dist/domain/managed/managedApplicationGraphNodes.js +94 -59
- package/dist/domain/managed/managedArtifact.js +1 -0
- package/dist/domain/managed/managedInspectionEvidence.js +13 -0
- package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
- package/dist/domain/native/nativeAotPe.js +1408 -0
- package/dist/domain/native/nativeCallObservation.js +2 -4
- package/dist/domain/native/nativeInstruction.js +21 -0
- package/dist/domain/native/nativeMetadataRecovery.js +79 -6
- package/dist/domain/native/nativeValueFlow.js +5 -11
- package/dist/domain/native/objcSwiftMetadata.js +15 -17
- package/dist/domain/native/peResources.js +94 -0
- package/dist/domain/nativeConvention.js +33 -0
- package/dist/domain/process/processCapture.js +102 -11
- package/dist/domain/process/processCaptureCoverage.js +8 -5
- package/dist/domain/process/processCaptureExample.js +67 -0
- package/dist/domain/process/processCaptureValidation.js +83 -3
- package/dist/domain/process/processComparison.js +0 -23
- package/dist/domain/process/processScenario.js +62 -10
- package/dist/domain/process/processTraceEvaluation.js +4 -4
- package/dist/domain/process/processTraceSpecification.js +1 -3
- package/dist/domain/propertyListKeys.js +3 -1
- package/dist/domain/providerCleanupError.js +6 -2
- package/dist/domain/reconstructionCoverage.js +2 -1
- package/dist/domain/reconstructionUnknowns.js +4 -3
- package/dist/domain/reconstructionVerification.js +3 -2
- package/dist/domain/referenceSourceGraph.js +32 -23
- package/dist/domain/referenceSourceImportParsing.js +40 -48
- package/dist/domain/referenceSourcePathIdentity.js +22 -0
- package/dist/domain/referenceSourceRequireBindings.js +137 -0
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +2 -1
- package/dist/domain/swiftSymbolClassification.js +6 -1
- package/dist/domain/symbolAnalysis.js +17 -2
- package/dist/domain/unicodeCodePointOrder.js +6 -0
- package/dist/domain/webBundleAnalyzerInspection.js +23 -3
- package/dist/domain/webCaptureDiff.js +170 -30
- package/dist/domain/webCaptureDiffSchemas.js +2 -8
- package/dist/domain/webInventory.js +3 -2
- package/dist/domain/webMcpDiscovery.js +4 -3
- package/dist/domain/webScriptExport.js +1 -1
- 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 +5 -4
- 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 +65 -31
- package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
- 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 +73 -0
- 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 +90 -8
- package/dist/ghidra/GhidraDiagnostics.js +11 -8
- package/dist/ghidra/GhidraFunctionValues.js +26 -2
- package/dist/ghidra/GhidraInstallation.js +111 -10
- package/dist/ghidra/GhidraInventoryValues.js +23 -1
- package/dist/ghidra/GhidraLanguageCatalog.js +99 -0
- package/dist/ghidra/GhidraLauncher.js +123 -58
- 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/HopperCleanup.js +1 -1
- 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 +10 -2
- package/dist/ida/IdaProvider.js +7 -0
- package/dist/ida/IdaSessionClient.js +7 -3
- package/dist/ida/IdaWorkspace.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
- package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
- package/dist/inspector/V8InspectorProvider.js +60 -8
- 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/main/shutdown.js +76 -32
- package/dist/main/transport.js +1 -1
- 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/AppleObjcDispatchFacets.js +3 -3
- package/dist/native/AppleObjcProperties.js +17 -7
- package/dist/native/LldbCallTracer.js +241 -75
- package/dist/native/NativeMacOSProvider.js +100 -20
- package/dist/native/NativeMacOSProviderMetadata.js +1 -2
- 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 +104 -51
- 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 +116 -22
- package/dist/process/capture/ProcessCaptureLifecycle.js +363 -86
- package/dist/process/capture/ProcessCaptureProgress.js +62 -0
- package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
- package/dist/process/capture/ProcessHarness.js +202 -47
- 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/analysisAdmission.js +8 -0
- package/dist/server/contractToolHandler.js +21 -0
- package/dist/server/createServer.js +118 -47
- 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 +6 -7
- 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/helpers.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/registerArtifactTools.js +2 -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 +36 -5
- package/dist/server/registerElectronTools.js +28 -10
- package/dist/server/registerEnhancedTools.js +78 -73
- package/dist/server/registerEvidenceTools.js +54 -46
- 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/registerManagedTools.js +7 -4
- 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/registerOfficialTools.js +31 -25
- 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 +58 -21
- 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 +38 -7
- 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 +31 -1
- package/dist/artifacts/inventory/policy.js +0 -2
- package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
- package/dist/server/registerNativeTools.js +0 -6
|
@@ -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,8 @@ 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
|
+
import { GhidraLaunchError } from "./GhidraLauncher.js";
|
|
13
14
|
import { GhidraResponseBuffer } from "./GhidraResponseBuffer.js";
|
|
14
15
|
import { GhidraResponseRouter } from "./GhidraResponseRouter.js";
|
|
15
16
|
import { GhidraRequestQueue } from "./GhidraRequestQueue.js";
|
|
@@ -17,6 +18,9 @@ import { bindGhidraSessionFailure, GhidraSessionError, } from "./GhidraSessionEr
|
|
|
17
18
|
import { isGhidraShutdownAcknowledgement, parseGhidraSessionInfo, } from "./GhidraSessionValues.js";
|
|
18
19
|
import { createGhidraTargetSnapshot } from "./GhidraTargetSnapshot.js";
|
|
19
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";
|
|
20
24
|
import { connectGhidraSocket } from "./GhidraSocketConnection.js";
|
|
21
25
|
import { createGhidraEndpoint, } from "./GhidraTransport.js";
|
|
22
26
|
import { GhidraWire } from "./GhidraClientWire.js";
|
|
@@ -37,6 +41,7 @@ export class GhidraClient {
|
|
|
37
41
|
#socketRoot;
|
|
38
42
|
#endpointPath;
|
|
39
43
|
#snapshotPath;
|
|
44
|
+
#snapshotOwners = new Set();
|
|
40
45
|
#targetAdmission;
|
|
41
46
|
#token;
|
|
42
47
|
// Retain authentication identities for diagnostics from late request settlement.
|
|
@@ -146,14 +151,76 @@ export class GhidraClient {
|
|
|
146
151
|
return this.#requestQueue.run(operation, parameters, options.signal === undefined ? {} : { signal: options.signal });
|
|
147
152
|
}
|
|
148
153
|
/** Read the private immutable source for independent import verification. */
|
|
149
|
-
async readTargetSnapshot() {
|
|
154
|
+
async readTargetSnapshot(maximumBytes, signal) {
|
|
150
155
|
if (this.#snapshotPath === undefined)
|
|
151
156
|
return err(this.#failure("protocol", "Ghidra target snapshot is unavailable before startup or after close"));
|
|
152
157
|
try {
|
|
153
|
-
|
|
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
|
+
});
|
|
154
221
|
}
|
|
155
222
|
catch (cause) {
|
|
156
|
-
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));
|
|
157
224
|
}
|
|
158
225
|
}
|
|
159
226
|
/** Stop the owned process group and remove all project/runtime artifacts. */
|
|
@@ -290,8 +357,18 @@ export class GhidraClient {
|
|
|
290
357
|
}, { signal: deadline.signal })
|
|
291
358
|
.catch((cause) => err(this.#failure("start", "Ghidra launcher failed", cause)));
|
|
292
359
|
if (!launched.ok) {
|
|
360
|
+
const partialLaunch = launched.error instanceof GhidraLaunchError
|
|
361
|
+
? launched.error.partialLaunch
|
|
362
|
+
: undefined;
|
|
363
|
+
if (partialLaunch !== undefined) {
|
|
364
|
+
this.#launch = partialLaunch;
|
|
365
|
+
this.#process = new ProviderProcessSupervisor(partialLaunch, {
|
|
366
|
+
maxDiagnosticBytes: GHIDRA_PROCESS_DIAGNOSTIC_BYTES,
|
|
367
|
+
onDiagnostic: (event) => this.#onProcessDiagnostic(event),
|
|
368
|
+
});
|
|
369
|
+
}
|
|
293
370
|
const failure = deadline.signal.aborted
|
|
294
|
-
? this.#interruptionFailure(deadline)
|
|
371
|
+
? this.#interruptionFailure(deadline, launched.error)
|
|
295
372
|
: launched.error instanceof GhidraSessionError
|
|
296
373
|
? launched.error
|
|
297
374
|
: this.#failure("start", launched.error.message, launched.error);
|
|
@@ -299,6 +376,7 @@ export class GhidraClient {
|
|
|
299
376
|
}
|
|
300
377
|
this.#launch = launched.value;
|
|
301
378
|
this.#process = new ProviderProcessSupervisor(launched.value, {
|
|
379
|
+
maxDiagnosticBytes: GHIDRA_PROCESS_DIAGNOSTIC_BYTES,
|
|
302
380
|
onDiagnostic: (event) => this.#onProcessDiagnostic(event),
|
|
303
381
|
});
|
|
304
382
|
const connected = await this.#connect(endpoint, deadline);
|
|
@@ -423,6 +501,10 @@ export class GhidraClient {
|
|
|
423
501
|
this.#lastDiagnostics = this.#diagnostics();
|
|
424
502
|
this.#process = undefined;
|
|
425
503
|
this.#launch = undefined;
|
|
504
|
+
for (const owner of this.#snapshotOwners) {
|
|
505
|
+
await owner.close();
|
|
506
|
+
this.#snapshotOwners.delete(owner);
|
|
507
|
+
}
|
|
426
508
|
try {
|
|
427
509
|
await this.#removeRuntimeRoots();
|
|
428
510
|
}
|
|
@@ -519,10 +601,10 @@ export class GhidraClient {
|
|
|
519
601
|
const failure = this.#interruptionFailure(deadline);
|
|
520
602
|
return this.#startupFailure(failure);
|
|
521
603
|
}
|
|
522
|
-
#interruptionFailure(deadline) {
|
|
604
|
+
#interruptionFailure(deadline, cause) {
|
|
523
605
|
return deadline.interruption === "cancelled"
|
|
524
|
-
? this.#failure("cancelled", "Ghidra startup was cancelled")
|
|
525
|
-
: this.#failure("timeout", "Ghidra startup deadline elapsed",
|
|
606
|
+
? this.#failure("cancelled", "Ghidra startup was cancelled", cause)
|
|
607
|
+
: this.#failure("timeout", "Ghidra startup deadline elapsed", cause, {
|
|
526
608
|
timeoutMs: deadline.timeoutMs,
|
|
527
609
|
});
|
|
528
610
|
}
|
|
@@ -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) => [
|
|
@@ -1,14 +1,84 @@
|
|
|
1
1
|
import { snapshotEnvironment } from "../process/snapshotEnvironment.js";
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
3
|
import { constants } from "node:fs";
|
|
4
|
-
import { accessSync, readFileSync } from "node:fs";
|
|
4
|
+
import { accessSync, closeSync, fstatSync, openSync, readFileSync, readSync, statSync, } from "node:fs";
|
|
5
5
|
import { posix, win32 } from "node:path";
|
|
6
|
+
import { parseExecutableHeader, } from "../domain/binaryTarget.js";
|
|
6
7
|
import { ghidraApplicationProperties, ghidraJavaMajorAccepted, ghidraJavaRangeLabel, ghidraJavaRequirement, ghidraReleaseAccepted, ghidraReleaseCompatibility, ghidraReleaseLine, ghidraVersionDetail, SUPPORTED_GHIDRA_JAVA_MAJOR, SUPPORTED_GHIDRA_VERSION, } from "./GhidraInstallationPolicy.js";
|
|
7
8
|
const NATIVE_PLATFORMS = {
|
|
8
9
|
linux: { x64: "linux_x86_64", arm64: "linux_arm_64" },
|
|
9
10
|
darwin: { x64: "mac_x86_64", arm64: "mac_arm_64" },
|
|
10
11
|
win32: { x64: "win_x86_64" },
|
|
11
12
|
};
|
|
13
|
+
/** Executable format each supported host runs its own Ghidra native tools as. */
|
|
14
|
+
const NATIVE_TOOL_FORMATS = {
|
|
15
|
+
linux: "elf",
|
|
16
|
+
darwin: "mach-o",
|
|
17
|
+
win32: "pe",
|
|
18
|
+
};
|
|
19
|
+
/** Node architecture identifiers as the executable-header parser reports them. */
|
|
20
|
+
const NATIVE_ARCHITECTURES = [
|
|
21
|
+
{ node: "x64", binary: "x86_64" },
|
|
22
|
+
{ node: "ia32", binary: "x86" },
|
|
23
|
+
{ node: "arm", binary: "arm" },
|
|
24
|
+
{ node: "arm64", binary: "arm64" },
|
|
25
|
+
];
|
|
26
|
+
/** Bound installation discovery reads; larger headers remain unknown. */
|
|
27
|
+
const EXECUTABLE_HEADER_PROBE_BYTES = 4096;
|
|
28
|
+
/**
|
|
29
|
+
* Judge a native decompiler by its own executable header instead of the
|
|
30
|
+
* directory name that admits it.
|
|
31
|
+
*
|
|
32
|
+
* Only a header that positively contradicts the host is `incompatible`. An
|
|
33
|
+
* absent, unreadable, truncated, or unrecognized header stays `unknown`, so a
|
|
34
|
+
* file the other checks already accept is never refused on missing evidence.
|
|
35
|
+
*/
|
|
36
|
+
const assessNativeDecompiler = (path, platform, architecture, probe) => {
|
|
37
|
+
const expectedFormat = NATIVE_TOOL_FORMATS[platform];
|
|
38
|
+
const expectedArchitecture = NATIVE_ARCHITECTURES.find(({ node }) => node === architecture)?.binary;
|
|
39
|
+
if (expectedFormat === undefined || expectedArchitecture === undefined)
|
|
40
|
+
return {
|
|
41
|
+
status: "unknown",
|
|
42
|
+
detail: `${path} is executable, but no native tool format is defined for ${platform}/${architecture}`,
|
|
43
|
+
};
|
|
44
|
+
let parsed = probe === undefined
|
|
45
|
+
? undefined
|
|
46
|
+
: parseExecutableHeader(probe.bytes, architecture, probe.size);
|
|
47
|
+
if (probe !== undefined && parsed !== undefined && !parsed.ok) {
|
|
48
|
+
// FAT parsing selects a host slice. A validated foreign slice can still
|
|
49
|
+
// prove that its complete architecture table excludes this host. If the
|
|
50
|
+
// host is listed but its slice is malformed, preserve the unknown outcome.
|
|
51
|
+
for (const { node } of NATIVE_ARCHITECTURES) {
|
|
52
|
+
if (node === architecture)
|
|
53
|
+
continue;
|
|
54
|
+
const alternative = parseExecutableHeader(probe.bytes, node, probe.size);
|
|
55
|
+
if (alternative.ok &&
|
|
56
|
+
!alternative.value.availableArchitectures.some((available) => available === expectedArchitecture)) {
|
|
57
|
+
parsed = alternative;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (parsed === undefined || !parsed.ok)
|
|
63
|
+
return {
|
|
64
|
+
status: "unknown",
|
|
65
|
+
detail: `${path} is executable, but its executable format for ${platform}/${architecture} could not be established`,
|
|
66
|
+
};
|
|
67
|
+
const observed = `${parsed.value.format} ${parsed.value.architecture}`;
|
|
68
|
+
const expected = `${expectedFormat} ${expectedArchitecture}`;
|
|
69
|
+
if (observed === expected)
|
|
70
|
+
return {
|
|
71
|
+
status: "compatible",
|
|
72
|
+
detail: `${path} reports ${observed}, which matches ${platform}/${architecture}`,
|
|
73
|
+
};
|
|
74
|
+
const nativeDirectory = NATIVE_PLATFORMS[platform]?.[architecture];
|
|
75
|
+
const executable = platform === "win32" ? "decompile.exe" : "decompile";
|
|
76
|
+
return {
|
|
77
|
+
status: "incompatible",
|
|
78
|
+
detail: `${path} reports ${observed}, but ${platform}/${architecture} requires ${expected}`,
|
|
79
|
+
remediation: `Provide an executable Ghidra/Features/Decompiler/os/${nativeDirectory ?? "<platform>"}/${executable} built for ${expected}, or its build/os equivalent. REA does not build or install native tools.`,
|
|
80
|
+
};
|
|
81
|
+
};
|
|
12
82
|
/** Inspect an installation without importing a target or modifying Ghidra. */
|
|
13
83
|
export const inspectGhidraInstallation = (options, host = systemGhidraInstallationHost()) => {
|
|
14
84
|
const platform = options.platform ?? process.platform;
|
|
@@ -137,14 +207,7 @@ const installationChecks = ({ coordinates, platform, architecture, javaHome, hos
|
|
|
137
207
|
detail: coordinates.analyzeHeadlessPath ?? "analyzeHeadless unavailable",
|
|
138
208
|
remediation: "Restore support/analyzeHeadless or support/analyzeHeadless.bat from the official Ghidra release.",
|
|
139
209
|
}),
|
|
140
|
-
|
|
141
|
-
name: "native_decompiler",
|
|
142
|
-
passed: coordinates.nativeDecompilerPath !== null,
|
|
143
|
-
code: "executable_missing",
|
|
144
|
-
detail: coordinates.nativeDecompilerPath ??
|
|
145
|
-
`Matching native decompiler for ${platform}/${architecture} was not found`,
|
|
146
|
-
remediation: `Provide an executable Ghidra/Features/Decompiler/os/${NATIVE_PLATFORMS[platform]?.[architecture] ?? "<platform>"}/${platform === "win32" ? "decompile.exe" : "decompile"}, or its build/os equivalent. REA does not build or install native tools.`,
|
|
147
|
-
}),
|
|
210
|
+
nativeDecompilerCheck({ coordinates, platform, architecture, host }),
|
|
148
211
|
javaCheck(coordinates.java, coordinates.javaCommand, javaHome, coordinates.properties),
|
|
149
212
|
];
|
|
150
213
|
/**
|
|
@@ -226,6 +289,23 @@ const installationCheck = (options) => options.passed
|
|
|
226
289
|
detail: options.detail,
|
|
227
290
|
remediation: options.remediation,
|
|
228
291
|
};
|
|
292
|
+
/** Require a present native decompiler without positively incompatible bytes. */
|
|
293
|
+
const nativeDecompilerCheck = ({ coordinates, platform, architecture, host, }) => {
|
|
294
|
+
const path = coordinates.nativeDecompilerPath;
|
|
295
|
+
const compatibility = path === null
|
|
296
|
+
? undefined
|
|
297
|
+
: assessNativeDecompiler(path, platform, architecture, host.executableHeader?.(path));
|
|
298
|
+
return installationCheck({
|
|
299
|
+
name: "native_decompiler",
|
|
300
|
+
passed: path !== null && compatibility?.status !== "incompatible",
|
|
301
|
+
code: "executable_missing",
|
|
302
|
+
detail: compatibility?.detail ??
|
|
303
|
+
`Matching native decompiler for ${platform}/${architecture} was not found`,
|
|
304
|
+
remediation: compatibility?.status === "incompatible"
|
|
305
|
+
? compatibility.remediation
|
|
306
|
+
: `Provide an executable Ghidra/Features/Decompiler/os/${NATIVE_PLATFORMS[platform]?.[architecture] ?? "<platform>"}/${platform === "win32" ? "decompile.exe" : "decompile"}, or its build/os equivalent. REA does not build or install native tools.`,
|
|
307
|
+
});
|
|
308
|
+
};
|
|
229
309
|
const versionCheck = (properties) => {
|
|
230
310
|
const raw = properties?.providerVersion;
|
|
231
311
|
return installationCheck({
|
|
@@ -280,10 +360,31 @@ const systemGhidraInstallationHost = () => ({
|
|
|
280
360
|
return undefined;
|
|
281
361
|
}
|
|
282
362
|
},
|
|
363
|
+
executableHeader(path) {
|
|
364
|
+
let handle;
|
|
365
|
+
try {
|
|
366
|
+
handle = openSync(path, constants.O_RDONLY | constants.O_NONBLOCK | constants.O_NOCTTY);
|
|
367
|
+
const metadata = fstatSync(handle);
|
|
368
|
+
if (!metadata.isFile())
|
|
369
|
+
return undefined;
|
|
370
|
+
const bytes = Buffer.alloc(EXECUTABLE_HEADER_PROBE_BYTES);
|
|
371
|
+
const read = readSync(handle, bytes, 0, bytes.length, 0);
|
|
372
|
+
return { bytes: bytes.subarray(0, read), size: metadata.size };
|
|
373
|
+
}
|
|
374
|
+
catch (cause) {
|
|
375
|
+
// best-effort cleanup: a header that cannot be read stays unknown.
|
|
376
|
+
void cause;
|
|
377
|
+
return undefined;
|
|
378
|
+
}
|
|
379
|
+
finally {
|
|
380
|
+
if (handle !== undefined)
|
|
381
|
+
closeSync(handle);
|
|
382
|
+
}
|
|
383
|
+
},
|
|
283
384
|
executable(path) {
|
|
284
385
|
try {
|
|
285
386
|
accessSync(path, constants.X_OK);
|
|
286
|
-
return
|
|
387
|
+
return statSync(path).isFile();
|
|
287
388
|
}
|
|
288
389
|
catch (cause) {
|
|
289
390
|
// best-effort cleanup: optional executable probing; failure means missing.
|
|
@@ -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) => {
|