rea-agents 5.0.0 → 6.1.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 +168 -655
- package/bridge/android/ReaJadxBridge.java +14 -5
- package/bridge/ghidra/ReaGhidraBridge.java +173 -47
- package/bridge/hopper_bridge.py +310 -128
- package/bridge/mitmproxy/capture.py +208 -0
- package/bridge/native/rea_lldb_tracer.py +839 -0
- package/bridge/process/ProcessRunTokenReader.swift +297 -0
- package/bridge/process/ProcessRunTokenReaderMain.swift +35 -0
- package/bridge/pwndbg/core_context.py +101 -0
- package/bridge/pwndbg/launch.py +39 -0
- package/bridge/pwndbg/launch_impl.py +34 -0
- package/bridge/pwntools/decoder_runtime.py +59 -0
- package/bridge/pwntools/layout.py +39 -0
- package/bridge/pwntools/layout_impl.py +309 -0
- package/bridge/pwntools/recorded_crash.py +39 -0
- package/bridge/pwntools/recorded_crash_impl.py +147 -0
- package/dist/android/JadxConfiguration.js +196 -33
- package/dist/android/JadxMcpTransport.js +4 -0
- package/dist/android/JadxProtocol.js +6 -0
- package/dist/android/JadxProvider.js +20 -2
- package/dist/android/JadxSession.js +23 -4
- package/dist/application/AnalysisContextQueries.js +8 -35
- package/dist/application/AnalysisDocument.js +32 -0
- package/dist/application/AppBundleExecutable.js +67 -21
- package/dist/application/CallPathTracing.js +19 -3
- package/dist/application/CapabilityInventory.js +27 -3
- package/dist/application/ClientConfigurationDocument.js +871 -6
- package/dist/application/ClientRegistrationIdentity.js +26 -5
- package/dist/application/ClientRegistrationStatus.js +29 -14
- package/dist/application/DirectAnalysis.js +97 -33
- package/dist/application/Doctor.js +4 -2
- package/dist/application/DoctorScope.js +25 -13
- package/dist/application/EnhancedLiteralTracing.js +22 -25
- package/dist/application/EnhancedTools.js +13 -11
- package/dist/application/EvidenceBundleFiles.js +24 -12
- package/dist/application/FunctionAnalysisEvidence.js +2 -3
- package/dist/application/InventoryProjectionEvidence.js +4 -3
- package/dist/application/InvestigationProviders.js +3 -2
- package/dist/application/JsonFiles.js +50 -28
- package/dist/application/ProcedureAddressResolution.js +11 -0
- package/dist/application/ReconstructionCoverageService.js +7 -4
- package/dist/application/ReconstructionObligationCandidates.js +5 -1
- package/dist/application/ReconstructionObligationLedgerService.js +4 -3
- package/dist/application/Setup.js +13 -1
- package/dist/application/SetupClientConfiguration.js +10 -15
- package/dist/application/SetupHost.js +5 -2
- package/dist/application/SetupPlan.js +5 -3
- package/dist/application/SupportedClients.js +34 -1
- package/dist/application/Uninstall.js +4 -3
- package/dist/application/Update.js +18 -3
- package/dist/application/UpdateRuntime.js +46 -25
- package/dist/application/WebModuleTraceService.js +4 -2
- package/dist/application/WebNetworkCapturePort.js +1 -0
- package/dist/application/WebNetworkCaptureService.js +134 -0
- package/dist/application/WebRuntimeService.js +5 -3
- package/dist/application/WebScriptExportService.js +2 -2
- package/dist/application/WebSourceLocationService.js +4 -2
- package/dist/application/WindowsCapabilities.js +1 -1
- package/dist/application/WorkflowEvidence.js +82 -0
- package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
- package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
- package/dist/application/binary/AnalysisSnapshotCache.js +52 -12
- package/dist/application/binary/BinarySession.js +131 -76
- package/dist/application/binary/BinarySessionOpen.js +19 -6
- package/dist/application/binary/BinarySessionRecords.js +45 -3
- package/dist/application/binary/BinarySessionStatus.js +17 -1
- package/dist/application/binary/CompositeProvider.js +13 -0
- package/dist/application/binary/LazyAnalysisProvider.js +3 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +59 -0
- package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +62 -0
- package/dist/application/evm/EvmInterfacePort.js +1 -0
- package/dist/application/evm/EvmInterfaceService.js +64 -0
- package/dist/application/investigation/EvidenceLedger.js +21 -7
- package/dist/application/investigation/InvestigationRecords.js +8 -0
- package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +25 -5
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +34 -14
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +47 -27
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +80 -27
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +33 -12
- package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
- package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +149 -72
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +14 -15
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +41 -1
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +7 -7
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -9
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +118 -12
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +27 -5
- package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
- package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
- package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
- package/dist/application/managed/ManagedReconstructionService.js +4 -3
- package/dist/application/{ProcessCli.js → process/ProcessCli.js} +23 -15
- package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +8 -7
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +42 -5
- package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
- package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
- package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
- package/dist/artifacts/ZipArtifactReader.js +3 -0
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
- package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
- package/dist/artifacts/apple/MachoLoadCommandReader.js +355 -0
- package/dist/artifacts/apple/NibArchive.js +81 -14
- package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
- package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
- package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
- package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +16 -11
- package/dist/{application → artifacts/inventory}/ArtifactInventory.js +4 -4
- package/dist/{application/ArtifactInventory → artifacts/inventory}/classify.js +2 -2
- package/dist/{application/ArtifactInventory → artifacts/inventory}/reader.js +5 -5
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanCanonical.js +14 -17
- package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/artifacts/readStableArtifact.js +20 -4
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +165 -12
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +34 -0
- package/dist/browser/CdpConnection.js +30 -11
- package/dist/browser/CdpOptionalCommand.js +2 -3
- package/dist/browser/CdpPageCapture.js +23 -1
- package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
- package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +130 -122
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/history/CaptureFailures.js +137 -0
- package/dist/browser/history/CaptureFormatError.js +10 -0
- package/dist/browser/history/CaptureRedaction.js +65 -0
- package/dist/browser/history/CaptureRelease.js +17 -0
- package/dist/browser/history/HarCapture.js +165 -0
- package/dist/browser/history/HarCaptureAdapter.js +20 -0
- package/dist/browser/history/HarCaptureProcess.js +57 -0
- package/dist/browser/history/HarJson.js +92 -0
- package/dist/browser/history/HarSchema.js +72 -0
- package/dist/browser/history/HistoricalCaptureDecoder.js +188 -0
- package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
- package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/applicationCommands.js +2 -3
- package/dist/cli/artifactCommands.js +26 -1
- package/dist/cli/binaryDiagnosticsCommands.js +39 -0
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +78 -20
- package/dist/cli/electronCommands.js +21 -13
- package/dist/cli/evmCommands.js +24 -0
- package/dist/cli/firmwareCommands.js +6 -3
- package/dist/cli/javascriptApplicationAnalysis.js +20 -3
- package/dist/cli/jsonOutput.js +38 -0
- package/dist/cli/nativeCallCommands.js +34 -0
- package/dist/cli/processCommands.js +1 -1
- package/dist/cli/streamedJsonOutput.js +56 -0
- package/dist/cli/utilityCommands.js +2 -0
- package/dist/cli/webNetworkCaptureCommands.js +40 -0
- package/dist/cli/webRuntimeCommands.js +8 -8
- package/dist/cli.js +11 -4
- package/dist/cliBrowserScenarioCommands.js +2 -2
- package/dist/cliCommandNames.js +6 -1
- package/dist/cliJsonInput.js +35 -1
- package/dist/cliOutput.js +21 -6
- package/dist/composition/binaryDiagnostics.js +8 -0
- package/dist/composition/evm.js +4 -0
- package/dist/composition/webNetworkCaptures.js +6 -0
- package/dist/config/environment.js +4 -0
- package/dist/config/ghidraStartupTimeout.js +17 -0
- package/dist/config/mcpResponseBudget.js +22 -0
- package/dist/config/parseConfig.js +2 -1
- package/dist/contracts/artifactToolContracts.js +6 -0
- package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
- package/dist/contracts/browserToolContracts.js +4 -3
- package/dist/contracts/enhancedInputs.js +5 -3
- package/dist/contracts/enhancedToolContracts.js +3 -3
- package/dist/contracts/errorSchemas.js +8 -1
- package/dist/contracts/evm/evmToolContracts.js +20 -0
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/investigationExamples.js +2 -2
- package/dist/contracts/javascript/electronToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +8 -6
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
- package/dist/contracts/native/nativeToolContracts.js +21 -3
- package/dist/contracts/officialToolContracts.js +26 -24
- package/dist/contracts/process/processCaptureExample.js +2 -0
- package/dist/contracts/promptContracts.js +3 -3
- package/dist/contracts/sessionLifecycleInputs.js +18 -5
- package/dist/contracts/sessionStatusContract.js +8 -2
- package/dist/contracts/sessionToolContracts.js +8 -3
- package/dist/contracts/sessionToolSchemas.js +8 -4
- package/dist/contracts/toolContractExamples.js +1 -2
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolContracts.js +6 -0
- package/dist/contracts/toolEffects.js +30 -1
- package/dist/contracts/toolOutputSchemaGroups.js +33 -28
- package/dist/contracts/toolOutputSchemaPrimitives.js +19 -1
- package/dist/contracts/toolSchemaMetadata.js +69 -10
- package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
- package/dist/domain/analysisErrorBase.js +22 -2
- package/dist/domain/analysisErrorCore.js +61 -5
- package/dist/domain/analysisErrorPresentation.js +95 -12
- package/dist/domain/analysisErrorProjection.js +148 -19
- package/dist/domain/analysisSnapshot.js +166 -2
- package/dist/domain/android/androidAnalysis.js +2 -4
- package/dist/domain/android/androidApplication.js +17 -9
- package/dist/domain/apple/appleApplication.js +41 -14
- package/dist/domain/apple/dyldEnvironment.js +73 -0
- package/dist/domain/apple/dyldPaths.js +81 -0
- package/dist/domain/apple/dylibResolution.js +478 -0
- package/dist/domain/apple/dylibResolutionFindings.js +77 -0
- package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
- package/dist/domain/apple/keyedArchive.js +9 -1
- package/dist/domain/apple/machoContainer.js +54 -0
- package/dist/domain/apple/plistNumbers.js +76 -0
- package/dist/domain/artifactIdentity.js +29 -0
- package/dist/domain/artifactInventoryEvidence.js +19 -24
- package/dist/domain/artifactPathSyntax.js +1 -1
- package/dist/domain/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserObservation.js +1 -1
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserObservationSchemas.js +13 -0
- package/dist/domain/browserScenarioValues.js +5 -2
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/callPathSchemas.js +1 -1
- package/dist/domain/canonicalDigest.js +13 -1
- package/dist/domain/canonicalJsonDigestSteps.js +133 -0
- package/dist/domain/canonicalOrdering.js +9 -5
- package/dist/domain/changedBehavior.js +9 -9
- package/dist/domain/comparisonSourceEvidence.js +40 -0
- package/dist/domain/comparisonStatus.js +2 -30
- package/dist/domain/configurationErrors.js +1 -1
- package/dist/domain/conformanceTrustGate.js +0 -16
- package/dist/domain/evidence.js +78 -11
- package/dist/domain/evidenceBundle.js +42 -1
- package/dist/domain/evidenceErrors.js +12 -1
- package/dist/domain/evm/evmInterface.js +63 -0
- package/dist/domain/explicitSensitiveFailure.js +108 -0
- package/dist/domain/explicitSensitiveValues.js +10 -0
- package/dist/domain/firmware/firmwareAnalysis.js +10 -4
- package/dist/domain/hopperErrors.js +23 -2
- package/dist/domain/hopperValues.js +51 -8
- package/dist/domain/immutableJson.js +114 -0
- package/dist/domain/inputIssueProjection.js +3 -0
- package/dist/domain/javascript/electronActiveObservation.js +37 -6
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
- package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
- package/dist/domain/javascript/javascriptAstValues.js +20 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
- package/dist/domain/javascript/javascriptRecovery.js +3 -8
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
- package/dist/domain/javascript/javascriptSemanticGraph.js +34 -5
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
- package/dist/domain/javascript/javascriptSourceParser.js +6 -2
- package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
- package/dist/domain/jsonSerialization.js +109 -0
- package/dist/domain/jsonValue.js +91 -3
- package/dist/domain/localPath.js +8 -0
- package/dist/domain/managed/managedApplicationGraph.js +10 -10
- package/dist/domain/managed/managedInspectionEvidence.js +16 -0
- package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
- package/dist/domain/managed/managedNativeVerification.js +3 -9
- package/dist/domain/native/binaryLayout.js +357 -0
- package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeCallObservation.js +186 -0
- package/dist/domain/native/nativeCallPartialObservation.js +33 -0
- package/dist/domain/native/objcSwiftMetadata.js +0 -39
- package/dist/domain/native/recordedCrash.js +266 -0
- package/dist/domain/native/recordedCrashNoteCoverage.js +73 -0
- package/dist/domain/{processCapture.js → process/processCapture.js} +143 -2
- package/dist/domain/{processCaptureExample.js → process/processCaptureExample.js} +5 -0
- package/dist/domain/process/processCaptureParsing.js +54 -0
- package/dist/domain/{processCaptureValidation.js → process/processCaptureValidation.js} +18 -2
- package/dist/domain/{processComparison.js → process/processComparison.js} +39 -5
- package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
- package/dist/domain/{processScenario.js → process/processScenario.js} +11 -10
- package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
- package/dist/domain/propertyListKeys.js +1 -1
- package/dist/domain/propertyListXmlText.js +19 -0
- package/dist/domain/providerAdapterError.js +1 -1
- package/dist/domain/providerOperationHealth.js +54 -0
- package/dist/domain/providerSelectionError.js +4 -2
- package/dist/domain/reconstructionVerification.js +9 -46
- package/dist/domain/reconstructionVerificationSchemas.js +3 -3
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +9 -46
- package/dist/domain/webBundleAnalysis.js +20 -8
- package/dist/domain/webBundleAnalyzerInspection.js +13 -8
- package/dist/domain/webBundleAnalyzerResult.js +41 -2
- package/dist/domain/webCaptureDiff.js +1 -0
- package/dist/domain/webNetworkCapture.js +118 -0
- package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
- package/dist/domain/webRuntime.js +19 -5
- package/dist/domain/webSourceLocation.js +1 -0
- package/dist/dotnet/ManagedExceptionRegionValidation.js +41 -0
- package/dist/dotnet/ManagedMemberInspector.js +4 -2
- package/dist/dotnet/ManagedMemberInspectorCore.js +38 -32
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +23 -7
- package/dist/dotnet/ManagedMemberRows.js +14 -3
- package/dist/dotnet/ManagedMetadataHeaps.js +20 -2
- package/dist/dotnet/ManagedMetadataInventory.js +38 -28
- package/dist/dotnet/ManagedMetadataInventoryRows.js +24 -10
- package/dist/dotnet/ManagedMethodBodyReader.js +7 -1
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +15 -3
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +3 -1
- package/dist/dotnet/ManagedPeReader.js +11 -0
- package/dist/evm/EvmBytecodeCarrier.js +21 -0
- package/dist/evm/EvmWorkerLimits.js +40 -0
- package/dist/evm/EvmoleFailures.js +126 -0
- package/dist/evm/EvmoleInterfaceAdapter.js +53 -0
- package/dist/evm/EvmoleInterfaceProvider.js +273 -0
- package/dist/evm/EvmoleInterfaceWorker.js +87 -0
- package/dist/evm/EvmoleRelease.js +16 -0
- package/dist/firmware/FirmwareCommand.js +1 -0
- package/dist/firmware/FirmwareFiles.js +1 -1
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
- package/dist/ghidra/GhidraClient.js +47 -14
- package/dist/ghidra/GhidraDiagnostics.js +7 -7
- package/dist/ghidra/GhidraFunctionValues.js +10 -7
- package/dist/ghidra/GhidraInstallation.js +18 -21
- package/dist/ghidra/GhidraInventoryValues.js +14 -4
- package/dist/ghidra/GhidraJavaLaunch.js +62 -0
- package/dist/ghidra/GhidraLauncher.js +34 -16
- package/dist/ghidra/GhidraProvider.js +2 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +15 -3
- package/dist/ghidra/GhidraProviderClient.js +23 -12
- package/dist/ghidra/GhidraSessionError.js +11 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
- package/dist/ghidra/GhidraTransport.js +20 -0
- package/dist/hopper/BridgeLauncher.js +33 -11
- package/dist/hopper/HopperAnalysisProfile.js +62 -4
- package/dist/hopper/HopperCleanup.js +15 -3
- package/dist/hopper/HopperClient.js +222 -14
- package/dist/hopper/HopperFileOffset.js +237 -0
- package/dist/hopper/HopperMachOImage.js +196 -0
- package/dist/hopper/HopperOperationStage.js +6 -0
- package/dist/hopper/HopperProvider.js +63 -9
- package/dist/hopper/HopperProviderCapabilities.js +19 -1
- package/dist/hopper/HopperRegexSearch.js +137 -0
- package/dist/hopper/HopperRegexWorker.js +27 -0
- package/dist/hopper/HopperRequestQueue.js +68 -19
- package/dist/hopper/HopperTargetLease.js +3 -2
- package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
- package/dist/inspector/V8InspectorProvider.js +47 -11
- package/dist/javascript/recovery/WakaruCommand.js +3 -0
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +17 -0
- package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
- package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
- package/dist/mcpDoctor.js +62 -2
- package/dist/native/AppleDispatchCoverage.js +47 -6
- package/dist/native/AppleDispatchDecodeFacts.js +6 -0
- package/dist/native/AppleDispatchMetadata.js +6 -3
- package/dist/native/AppleMachoFixups.js +48 -24
- package/dist/native/AppleMachoSelection.js +32 -16
- package/dist/native/AppleObjcCategories.js +6 -2
- package/dist/native/AppleObjcDispatchFacets.js +5 -2
- package/dist/native/AppleObjcProperties.js +2 -1
- package/dist/native/AppleSwiftDispatchFacets.js +27 -21
- package/dist/native/AppleSwiftVtables.js +21 -15
- package/dist/native/CommandRunner.js +82 -84
- package/dist/native/LldbCallTracer.js +541 -0
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +194 -0
- package/dist/native/NativeMacOSProvider.js +117 -20
- package/dist/native/NativeMacOSProviderMetadata.js +8 -3
- package/dist/native/SignatureTargetBinding.js +155 -0
- package/dist/native/parsers/lipo.js +71 -1
- package/dist/native/pwndbg/PwndbgCoreContext.js +180 -0
- package/dist/native/pwntools/PwntoolsDecoder.js +203 -0
- package/dist/native/pwntools/PwntoolsFailures.js +180 -0
- package/dist/native/pwntools/PwntoolsLayoutProvider.js +36 -0
- package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +75 -0
- package/dist/native/pwntools/PwntoolsRelease.js +19 -0
- package/dist/native/pwntools/PwntoolsResourceLimits.js +76 -0
- package/dist/native/pwntools/RecordedCrashSourceBindings.js +46 -0
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +103 -0
- package/dist/process/DarwinProcessRunTokenReader.js +293 -0
- package/dist/process/ExecFileOutput.js +20 -0
- package/dist/process/OwnedCommand.js +118 -0
- package/dist/process/ProcessOwnership.js +431 -51
- package/dist/process/ProcessOwnershipObservation.js +209 -27
- package/dist/process/ProviderProcess.js +68 -10
- package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
- package/dist/{application → process/capture}/ProcessCaptureError.js +18 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +681 -0
- package/dist/{application → process/capture}/ProcessHarness.js +195 -29
- package/dist/{application → process/capture}/ProcessSampling.js +2 -2
- package/dist/server/EvidenceMcpServer.js +146 -0
- package/dist/server/createServer.js +37 -8
- package/dist/server/promptCompletion.js +10 -3
- package/dist/server/registerAndroidTools.js +2 -4
- package/dist/server/registerApplicationTools/helpers.js +2 -4
- package/dist/server/registerArtifactComparisonTool.js +11 -7
- package/dist/server/registerBinaryDiagnosticsTools.js +15 -0
- package/dist/server/registerBrowserScenarioTool.js +2 -4
- package/dist/server/registerBrowserTools.js +2 -4
- package/dist/server/registerBundleComparisonTool.js +2 -3
- package/dist/server/registerCloseLifecycleTool.js +8 -18
- package/dist/server/registerElectronTools.js +2 -4
- package/dist/server/registerEnhancedTools.js +18 -59
- package/dist/server/registerEvidenceTools.js +3 -5
- package/dist/server/registerEvmTools.js +15 -0
- package/dist/server/registerFirmwareTools.js +2 -4
- package/dist/server/registerFunctionComparisonTool.js +10 -6
- package/dist/server/registerInvestigationTools.js +7 -7
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
- package/dist/server/registerOfficialTools.js +2 -4
- package/dist/server/registerProcessComparisonTool.js +72 -46
- package/dist/server/registerRecordedCrashTools.js +15 -0
- package/dist/server/registerSessionRecordTools.js +5 -6
- package/dist/server/registerSessionStatusTool.js +17 -3
- package/dist/server/registerSessionTools.js +13 -5
- package/dist/server/registerWebModuleTool.js +2 -4
- package/dist/server/registerWebNetworkCaptureTool.js +26 -0
- package/dist/server/registerWebRuntimeTools.js +3 -7
- package/dist/server/registerWebScriptTool.js +2 -4
- package/dist/server/registerWebSourceLocationTool.js +2 -4
- package/dist/server/runDerivedOperation.js +15 -3
- package/dist/server/sessionAvailabilityPolicy.js +3 -1
- package/dist/server/sessionToolPolicies.js +1 -1
- package/dist/server/toolRegistrationOptions.js +2 -2
- package/dist/server/toolResult.js +63 -11
- package/dist/server/toolResultEncoding.js +33 -0
- package/install.sh +1 -1
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +42 -9
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/scripts/rea.mjs +11 -3
- package/skills/reverse-engineer-anything/SKILL.md +32 -4
- package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +29 -0
- package/third_party/README.md +60 -0
- package/third_party/evmole/LICENSE +21 -0
- package/third_party/evmole/README.md +22 -0
- package/third_party/pwndbg/LICENSE.md +21 -0
- package/third_party/pwndbg/README.md +23 -0
- package/third_party/pwntools/README.md +40 -0
- package/dist/application/AuthorizedArtifactInventory.js +0 -7
- package/dist/application/ProcessCaptureLifecycle.js +0 -299
- package/dist/application/StoreFileLock.js +0 -124
- package/dist/contracts/processCaptureExample.js +0 -2
- package/dist/domain/bytecodeProvider.js +0 -178
- package/dist/domain/customProtocolCapture.js +0 -137
- package/dist/domain/eventProcessTree.js +0 -225
- package/dist/domain/mobileApplicationInvestigation.js +0 -159
- package/dist/domain/packageAnalysis.js +0 -123
- package/dist/domain/peInspection.js +0 -197
- package/dist/domain/processCaptureParsing.js +0 -21
- package/dist/domain/protocolCapture.js +0 -217
- package/dist/domain/runtimeIdentification.js +0 -212
- package/dist/generatedMcpToolCatalog.js +0 -37
- package/dist/ghidra/GhidraDefaults.js +0 -2
- /package/dist/application/{ArtifactExtractionDestination.js → artifacts/ArtifactExtractionDestination.js} +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/policy.js +0 -0
- /package/dist/{application/ArtifactInventory → artifacts/inventory}/types.js +0 -0
- /package/dist/domain/{processEvidenceProvider.js → process/processEvidenceProvider.js} +0 -0
- /package/dist/domain/{processTraceComparison.js → process/processTraceComparison.js} +0 -0
- /package/dist/domain/{processTraceDimensionProjection.js → process/processTraceDimensionProjection.js} +0 -0
- /package/dist/domain/{processTraceEvaluation.js → process/processTraceEvaluation.js} +0 -0
- /package/dist/{application → process/capture}/FilesystemSnapshot.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureEnvironment.js +0 -0
- /package/dist/{application → process/capture}/ProcessCaptureJournal.js +0 -0
- /package/dist/{application → process/capture}/ProcessFilesystemEffects.js +0 -0
- /package/dist/{application → process/capture}/ProcessNormalization.js +0 -0
- /package/dist/{application → process/capture}/ProcessScenarioRuntimeValidation.js +0 -0
- /package/dist/{application → process/capture}/ProcessTimer.js +0 -0
- /package/dist/{application → process/capture}/TerminalRenderer.js +0 -0
|
@@ -4,6 +4,11 @@ import { accessSync, readFileSync } from "node:fs";
|
|
|
4
4
|
import { posix, win32 } from "node:path";
|
|
5
5
|
import { ghidraApplicationProperties, ghidraJavaMajorAccepted, ghidraJavaRangeLabel, ghidraJavaRequirement, ghidraReleaseAccepted, ghidraReleaseCompatibility, ghidraReleaseLine, ghidraVersionDetail, SUPPORTED_GHIDRA_JAVA_MAJOR, SUPPORTED_GHIDRA_VERSION, } from "./GhidraInstallationPolicy.js";
|
|
6
6
|
export { SUPPORTED_GHIDRA_JAVA_MAJOR, SUPPORTED_GHIDRA_VERSION };
|
|
7
|
+
const NATIVE_PLATFORMS = {
|
|
8
|
+
linux: { x64: "linux_x86_64", arm64: "linux_arm_64" },
|
|
9
|
+
darwin: { x64: "mac_x86_64", arm64: "mac_arm_64" },
|
|
10
|
+
win32: { x64: "win_x86_64" },
|
|
11
|
+
};
|
|
7
12
|
/** Inspect an installation without importing a target or modifying Ghidra. */
|
|
8
13
|
export const inspectGhidraInstallation = (options, host = systemGhidraInstallationHost()) => {
|
|
9
14
|
const platform = options.platform ?? process.platform;
|
|
@@ -67,16 +72,13 @@ const installationCoordinates = (options, platform, architecture, host) => {
|
|
|
67
72
|
const analyzeHeadlessPath = installDir === null
|
|
68
73
|
? null
|
|
69
74
|
: path.join(installDir, "support", platform === "win32" ? "analyzeHeadless.bat" : "analyzeHeadless");
|
|
70
|
-
const decompilerPlatform = platform
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
: "mac_x86_64"
|
|
74
|
-
: null;
|
|
75
|
-
const nativeDecompilerPath = installDir === null || decompilerPlatform === null
|
|
75
|
+
const decompilerPlatform = NATIVE_PLATFORMS[platform]?.[architecture];
|
|
76
|
+
const decompilerExecutable = platform === "win32" ? "decompile.exe" : "decompile";
|
|
77
|
+
const nativeDecompilerPath = installDir === null || decompilerPlatform === undefined
|
|
76
78
|
? null
|
|
77
79
|
: ([
|
|
78
|
-
path.join(installDir, "Ghidra", "Features", "Decompiler", "os", decompilerPlatform,
|
|
79
|
-
path.join(installDir, "Ghidra", "Features", "Decompiler", "build", "os", decompilerPlatform,
|
|
80
|
+
path.join(installDir, "Ghidra", "Features", "Decompiler", "os", decompilerPlatform, decompilerExecutable),
|
|
81
|
+
path.join(installDir, "Ghidra", "Features", "Decompiler", "build", "os", decompilerPlatform, decompilerExecutable),
|
|
80
82
|
].find((candidate) => host.executable(candidate)) ?? null);
|
|
81
83
|
const properties = applicationPropertiesPath === null
|
|
82
84
|
? undefined
|
|
@@ -108,20 +110,17 @@ const installationChecks = ({ coordinates, platform, architecture, javaHome, hos
|
|
|
108
110
|
}),
|
|
109
111
|
installationCheck({
|
|
110
112
|
name: "platform",
|
|
111
|
-
passed: platform
|
|
113
|
+
passed: NATIVE_PLATFORMS[platform] !== undefined,
|
|
112
114
|
code: "unsupported_host",
|
|
113
115
|
detail: platform,
|
|
114
|
-
remediation: "Use Linux or
|
|
116
|
+
remediation: "Use Linux or macOS x64/arm64, or Windows x64 with matching native Ghidra tools.",
|
|
115
117
|
}),
|
|
116
118
|
installationCheck({
|
|
117
119
|
name: "architecture",
|
|
118
|
-
passed:
|
|
119
|
-
architecture === "x64") ||
|
|
120
|
-
(platform === "darwin" &&
|
|
121
|
-
(architecture === "x64" || architecture === "arm64")),
|
|
120
|
+
passed: NATIVE_PLATFORMS[platform]?.[architecture] !== undefined,
|
|
122
121
|
code: "unsupported_host",
|
|
123
122
|
detail: architecture,
|
|
124
|
-
remediation: "Use x64 on Linux or
|
|
123
|
+
remediation: "Use x64/arm64 on Linux or macOS, or x64 on Windows.",
|
|
125
124
|
}),
|
|
126
125
|
installationCheck({
|
|
127
126
|
name: "installation",
|
|
@@ -142,13 +141,11 @@ const installationChecks = ({ coordinates, platform, architecture, javaHome, hos
|
|
|
142
141
|
}),
|
|
143
142
|
installationCheck({
|
|
144
143
|
name: "native_decompiler",
|
|
145
|
-
passed:
|
|
144
|
+
passed: coordinates.nativeDecompilerPath !== null,
|
|
146
145
|
code: "executable_missing",
|
|
147
|
-
detail:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
"matching macOS native decompiler was not found"),
|
|
151
|
-
remediation: "REA does not build native tools. Build Ghidra's native components for this macOS architecture or provide an installation containing Ghidra/Features/Decompiler/os/<platform>/decompile.",
|
|
146
|
+
detail: coordinates.nativeDecompilerPath ??
|
|
147
|
+
`Matching native decompiler for ${platform}/${architecture} was not found`,
|
|
148
|
+
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.`,
|
|
152
149
|
}),
|
|
153
150
|
javaCheck(coordinates.java, coordinates.javaCommand, javaHome, coordinates.properties),
|
|
154
151
|
];
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { nativeLoadImageObservationSchema } from "../domain/native/nativeLoadImage.js";
|
|
3
|
-
import {
|
|
3
|
+
import { AnalysisOutputError, } from "../domain/analysisErrorCore.js";
|
|
4
4
|
import { functionBodySchema, functionBodyEntryAgrees, } from "../domain/hopperValues.js";
|
|
5
5
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
6
6
|
import { err, ok } from "../domain/result.js";
|
|
7
|
+
import { analysisInputErrorFromIssues } from "../domain/inputIssueProjection.js";
|
|
7
8
|
/** Read-only direct inventory operations admitted by the Ghidra adapter. */
|
|
8
9
|
export const GHIDRA_INVENTORY_OPERATIONS = [
|
|
9
10
|
"inspect_native_load_image",
|
|
@@ -26,7 +27,11 @@ export const isGhidraInventoryOperation = (operation) => operationSet.has(operat
|
|
|
26
27
|
export const ghidraIdentifierSchema = z.string().min(1);
|
|
27
28
|
const identifier = ghidraIdentifierSchema;
|
|
28
29
|
const document = identifier.nullable().default(null);
|
|
29
|
-
|
|
30
|
+
/** Caller address spelling; the bridge resolves its space and emits canonical output. */
|
|
31
|
+
export const ghidraInputAddressSchema = z
|
|
32
|
+
.string()
|
|
33
|
+
.regex(/^(?:(?:0[xX])?[0-9a-fA-F]+|(?:[A-Za-z0-9._~-]|%[0-9a-fA-F]{2})+:0[xX][0-9a-fA-F]+)$/u, "Use hexadecimal digits, optionally prefixed with 0x, or an encoded address-space name followed by :0x and hexadecimal digits");
|
|
34
|
+
const explicitAddress = ghidraInputAddressSchema;
|
|
30
35
|
const filteredAddress = explicitAddress.nullable().default(null);
|
|
31
36
|
const searchInput = {
|
|
32
37
|
pattern: z.string().min(1),
|
|
@@ -62,7 +67,9 @@ const inputSchemas = {
|
|
|
62
67
|
export const parseGhidraInventoryInput = (operation, value) => {
|
|
63
68
|
const parsed = inputSchemas[operation].safeParse(value);
|
|
64
69
|
if (!parsed.success)
|
|
65
|
-
return err(
|
|
70
|
+
return err(analysisInputErrorFromIssues(operation, parsed.error.issues, value, {
|
|
71
|
+
cause: parsed.error,
|
|
72
|
+
}));
|
|
66
73
|
return ok(parsed.data);
|
|
67
74
|
};
|
|
68
75
|
export const ghidraCanonicalAddressSchema = z
|
|
@@ -171,7 +178,10 @@ const containingProcedure = z.discriminatedUnion("found", [
|
|
|
171
178
|
.strict()
|
|
172
179
|
.superRefine((value, context) => {
|
|
173
180
|
const body = value.procedure.body;
|
|
174
|
-
|
|
181
|
+
const exactExternalEntry = value.procedure.classification.external &&
|
|
182
|
+
value.query_address === value.procedure.address;
|
|
183
|
+
if (!exactExternalEntry &&
|
|
184
|
+
body.available &&
|
|
175
185
|
!functionBodyEntryAgrees({ ...body, contains_entry: true }, value.query_address))
|
|
176
186
|
context.addIssue({
|
|
177
187
|
code: "custom",
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { dirname, join } from "node:path";
|
|
2
|
+
import { execFileOutput } from "../process/ExecFileOutput.js";
|
|
3
|
+
/** Launch coordinates obtained from Ghidra's own release configuration helper. */
|
|
4
|
+
export const ghidraJavaLaunch = async (options) => {
|
|
5
|
+
const supportRoot = dirname(options.analyzeHeadlessPath);
|
|
6
|
+
const installRoot = dirname(supportRoot);
|
|
7
|
+
const command = join(options.javaHome, "bin", "java");
|
|
8
|
+
const isolatedProperties = [
|
|
9
|
+
`-Duser.home=${options.homeRoot}`,
|
|
10
|
+
`-Djava.io.tmpdir=${options.tempRoot}`,
|
|
11
|
+
];
|
|
12
|
+
const supportArguments = [
|
|
13
|
+
...isolatedProperties,
|
|
14
|
+
"-cp",
|
|
15
|
+
join(supportRoot, "LaunchSupport.jar"),
|
|
16
|
+
"LaunchSupport",
|
|
17
|
+
installRoot,
|
|
18
|
+
];
|
|
19
|
+
const environment = { ...options.environment };
|
|
20
|
+
const configuredEnvironment = await execFileOutput(command, [...supportArguments, "-envvars"], {
|
|
21
|
+
env: environment,
|
|
22
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
23
|
+
});
|
|
24
|
+
for (const line of configuredEnvironment.stdout.split(/\r?\n/u)) {
|
|
25
|
+
if (line === "")
|
|
26
|
+
continue;
|
|
27
|
+
const separator = line.indexOf("=");
|
|
28
|
+
const key = line.slice(0, separator);
|
|
29
|
+
if (separator < 1 || !/^[A-Za-z_][A-Za-z0-9_]*$/u.test(key))
|
|
30
|
+
throw new Error(`Invalid Ghidra LaunchSupport environment entry: ${line}`);
|
|
31
|
+
if ((environment[key] ?? "") === "")
|
|
32
|
+
environment[key] = line.slice(separator + 1);
|
|
33
|
+
}
|
|
34
|
+
const configuredArguments = await execFileOutput(command, [...supportArguments, "-vmargs"], {
|
|
35
|
+
env: environment,
|
|
36
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
37
|
+
});
|
|
38
|
+
const vmArguments = configuredArguments.stdout
|
|
39
|
+
.split(/\r?\n/u)
|
|
40
|
+
.filter((line) => line !== "");
|
|
41
|
+
if (vmArguments.some((argument) => !argument.startsWith("-") || argument.includes("\0")))
|
|
42
|
+
throw new Error("Invalid Ghidra LaunchSupport JVM argument");
|
|
43
|
+
return {
|
|
44
|
+
command,
|
|
45
|
+
environment,
|
|
46
|
+
arguments: [
|
|
47
|
+
...vmArguments,
|
|
48
|
+
...(options.platform === "darwin" ? ["-Xdock:name=Ghidra-Headless"] : []),
|
|
49
|
+
`-Xmx${environment.GHIDRA_HEADLESS_MAXMEM || environment.GHIDRA_MAXMEM || "2G"}`,
|
|
50
|
+
"-XX:ParallelGCThreads=2",
|
|
51
|
+
"-XX:CICompilerCount=2",
|
|
52
|
+
"-Djava.awt.headless=true",
|
|
53
|
+
...isolatedProperties,
|
|
54
|
+
"-showversion",
|
|
55
|
+
"-cp",
|
|
56
|
+
join(installRoot, "Ghidra", "Framework", "Utility", "lib", "Utility.jar"),
|
|
57
|
+
"ghidra.Ghidra",
|
|
58
|
+
"ghidra.app.util.headless.AnalyzeHeadless",
|
|
59
|
+
...options.arguments,
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
};
|
|
@@ -7,6 +7,7 @@ import { err, ok } from "../domain/result.js";
|
|
|
7
7
|
import { cleanupOwnedProcessGroup, cleanupWindowsProcessTree, } from "../process/ProcessOwnership.js";
|
|
8
8
|
import { spawnOwnedProviderProcess, } from "../process/ProviderProcess.js";
|
|
9
9
|
import { ghidraJavaEnvironment } from "./GhidraInstallation.js";
|
|
10
|
+
import { ghidraJavaLaunch } from "./GhidraJavaLaunch.js";
|
|
10
11
|
import { snapshotGhidraExtensions, } from "./extensions/GhidraExtensions.js";
|
|
11
12
|
/** Local launch failure retained as the cause of a provider-neutral error. */
|
|
12
13
|
export class GhidraLaunchError extends Error {
|
|
@@ -58,7 +59,7 @@ export class GhidraHeadlessLauncher {
|
|
|
58
59
|
? {}
|
|
59
60
|
: { dosMz: this.options.dosMz }),
|
|
60
61
|
});
|
|
61
|
-
const
|
|
62
|
+
const scriptCommand = ghidraHeadlessCommand({
|
|
62
63
|
platform,
|
|
63
64
|
analyzeHeadlessPath: this.options.analyzeHeadlessPath,
|
|
64
65
|
arguments: headlessArguments,
|
|
@@ -66,24 +67,45 @@ export class GhidraHeadlessLauncher {
|
|
|
66
67
|
? {}
|
|
67
68
|
: { comSpec: this.options.comSpec }),
|
|
68
69
|
});
|
|
70
|
+
const environment = ghidraLaunchEnvironment(paths, this.options.javaHome, platform, scriptCommand.command);
|
|
71
|
+
if (platform !== "win32" && this.options.javaHome === undefined)
|
|
72
|
+
throw new GhidraLaunchError("POSIX Ghidra requires its inspected JDK home");
|
|
73
|
+
const command = platform !== "win32" && this.options.javaHome !== undefined
|
|
74
|
+
? await ghidraJavaLaunch({
|
|
75
|
+
platform,
|
|
76
|
+
analyzeHeadlessPath: this.options.analyzeHeadlessPath,
|
|
77
|
+
javaHome: this.options.javaHome,
|
|
78
|
+
homeRoot: paths.homeRoot,
|
|
79
|
+
tempRoot: paths.tempRoot,
|
|
80
|
+
arguments: headlessArguments,
|
|
81
|
+
environment,
|
|
82
|
+
...(options.signal === undefined
|
|
83
|
+
? {}
|
|
84
|
+
: { signal: options.signal }),
|
|
85
|
+
})
|
|
86
|
+
: { ...scriptCommand, environment };
|
|
69
87
|
started = await spawnOwnedProviderProcess({
|
|
70
88
|
command: command.command,
|
|
71
89
|
arguments: command.arguments,
|
|
72
90
|
runId: session.runId,
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
expectedCommand: null,
|
|
91
|
+
// POSIX launches the inspected JVM directly; script wrappers cannot
|
|
92
|
+
// preserve JVM property paths containing spaces as single arguments.
|
|
93
|
+
expectedCommand: platform !== "win32" ? command.command : null,
|
|
76
94
|
windowsVerbatimArguments: platform === "win32",
|
|
77
95
|
platform,
|
|
78
|
-
env:
|
|
96
|
+
env: command.environment,
|
|
97
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
79
98
|
});
|
|
80
99
|
await writeGhidraRuntimeFile(paths.ownershipPath, `${JSON.stringify({
|
|
81
100
|
run_id: session.runId,
|
|
101
|
+
transport: session.transport,
|
|
102
|
+
endpoint_path: session.endpointPath,
|
|
82
103
|
pid: started.ownership.leaderPid,
|
|
83
104
|
process_group_id: started.ownership.processGroupId,
|
|
84
105
|
parent_pid: process.pid,
|
|
85
106
|
ownership_kind: platform === "win32" ? "windows-job-object" : "posix-process-group",
|
|
86
|
-
launcher:
|
|
107
|
+
launcher: command.command,
|
|
108
|
+
headless_script: this.options.analyzeHeadlessPath,
|
|
87
109
|
created_at: new Date().toISOString(),
|
|
88
110
|
})}\n`, platform);
|
|
89
111
|
if (isAborted(options.signal)) {
|
|
@@ -266,22 +288,18 @@ const ghidraLaunchEnvironment = (paths, javaHome, platform, executable) => {
|
|
|
266
288
|
XDG_DATA_HOME: paths.dataRoot,
|
|
267
289
|
};
|
|
268
290
|
};
|
|
269
|
-
/** Encode provider-owned JVM paths for the
|
|
291
|
+
/** Encode provider-owned JVM paths for the platform launcher that consumes them. */
|
|
270
292
|
export const ghidraHeadlessJavaOptions = (homeRoot, tempRoot, platform) => {
|
|
271
293
|
const options = [`-Duser.home=${homeRoot}`, `-Djava.io.tmpdir=${tempRoot}`];
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
// JDK_JAVA_OPTIONS is parsed by Java itself, outside that batch expansion.
|
|
275
|
-
return platform === "win32"
|
|
276
|
-
? {
|
|
294
|
+
if (platform === "win32")
|
|
295
|
+
return {
|
|
277
296
|
JDK_JAVA_OPTIONS: [...options, "-XX:-UsePerfData"]
|
|
278
297
|
.map(quoteWindowsBatchToken)
|
|
279
298
|
.join(" "),
|
|
280
299
|
GHIDRA_HEADLESS_JAVA_OPTIONS: "",
|
|
281
|
-
}
|
|
282
|
-
: {
|
|
283
|
-
JDK_JAVA_OPTIONS: "",
|
|
284
|
-
GHIDRA_HEADLESS_JAVA_OPTIONS: options.join(" "),
|
|
285
300
|
};
|
|
301
|
+
// POSIX launches the JVM directly, so these properties travel as separate
|
|
302
|
+
// argv items instead of the shell-split analyzeHeadless option list.
|
|
303
|
+
return { JDK_JAVA_OPTIONS: "", GHIDRA_HEADLESS_JAVA_OPTIONS: "" };
|
|
286
304
|
};
|
|
287
305
|
const isAborted = (signal) => signal?.aborted === true;
|
|
@@ -163,11 +163,11 @@ const inspectWindowsP0TargetSupport = (target, diagnostics) => {
|
|
|
163
163
|
reason: "Windows Ghidra P0 accepts PE targets only.",
|
|
164
164
|
diagnostics,
|
|
165
165
|
};
|
|
166
|
-
if (target.architecture !== "x86_64")
|
|
166
|
+
if (target.architecture !== "x86" && target.architecture !== "x86_64")
|
|
167
167
|
return {
|
|
168
168
|
status: "unsupported",
|
|
169
169
|
code: "architecture_unsupported",
|
|
170
|
-
reason: "Windows Ghidra P0 accepts x86-64 PE targets only.",
|
|
170
|
+
reason: "Windows Ghidra P0 accepts x86 and x86-64 PE targets only.",
|
|
171
171
|
diagnostics,
|
|
172
172
|
};
|
|
173
173
|
if (target.executableRole !== "application")
|
|
@@ -16,10 +16,11 @@ export const GHIDRA_OPERATIONS = Object.freeze([
|
|
|
16
16
|
export const healthLimitations = Object.freeze([
|
|
17
17
|
"The session serves operations only after Ghidra reports default auto-analysis complete; incomplete analysis does not expose partial results.",
|
|
18
18
|
"The imported Program and temporary project are ephemeral and deleted on close. Annotation operations edit session database metadata; original executable bytes are never written.",
|
|
19
|
+
"Cancelling an active Ghidra request terminates its ephemeral database and discards session annotations. The selected target remains open; the next provider query imports the original artifact again.",
|
|
19
20
|
]);
|
|
20
21
|
/** Additional limitations applied to the experimental Windows x64 P0 boundary. */
|
|
21
22
|
export const windowsP0Limitations = Object.freeze([
|
|
22
|
-
"Windows Ghidra P0 accepts approved native x86-64 PE applications only; DLL, managed, hostile, sensitive, and mutable-path targets are unsupported.",
|
|
23
|
+
"Windows Ghidra P0 accepts approved native x86 and x86-64 PE applications only; DLL, managed, hostile, sensitive, and mutable-path targets are unsupported.",
|
|
23
24
|
"The Windows bridge uses authenticated IPv4 loopback because Node path-based IPC does not expose Java AF_UNIX sockets; the endpoint file contains no bearer token.",
|
|
24
25
|
"Windows sessions require the matching packaged Windows x64 native addon, local NTFS targets and runtimes, and Windows 10 or later. Native handles enforce path admission, private DACLs, and Job Object ownership automatically.",
|
|
25
26
|
]);
|
|
@@ -33,7 +34,8 @@ export const limitationsFor = (operation) => {
|
|
|
33
34
|
case "annotate_native_function":
|
|
34
35
|
return [
|
|
35
36
|
...common,
|
|
36
|
-
"Names use Ghidra USER_DEFINED source. Name writes
|
|
37
|
+
"Names use Ghidra USER_DEFINED source. Name writes accept a leaf name or a fully qualified name within the existing namespace; readback uses the fully qualified name and can be reused without adding namespace prefixes. Edits retain the current namespace; other namespace-like text remains literal leaf-name text. Regular comments map to PRE and inline comments to EOL at the exact function entry. Changes commit together after readback and refreshed analysis; failure rolls them all back.",
|
|
38
|
+
"Annotation text rejects NUL and unpaired Unicode surrogates before mutation, with the field and UTF-16 index in the error. Supported Unicode and line endings are preserved.",
|
|
37
39
|
"Metadata edits invalidate immutable analysis snapshots and are discarded on close. CLI returns the updated dossier before session cleanup; this is not a saved Ghidra project.",
|
|
38
40
|
];
|
|
39
41
|
case "inspect_native_load_image":
|
|
@@ -72,6 +74,11 @@ export const limitationsFor = (operation) => {
|
|
|
72
74
|
...common,
|
|
73
75
|
"Only Ghidra-defined string Data is observed; charset is reported, while a non-missing terminator cannot distinguish a present terminator from a fixed or Pascal layout.",
|
|
74
76
|
];
|
|
77
|
+
case "resolve_containing_procedure":
|
|
78
|
+
return [
|
|
79
|
+
...common,
|
|
80
|
+
"An exact external entry resolves to its observed function identity even when its body is empty. This does not establish mapped executable bytes or containment of nearby external addresses.",
|
|
81
|
+
];
|
|
75
82
|
case "list_segments":
|
|
76
83
|
return [
|
|
77
84
|
...common,
|
|
@@ -79,7 +86,10 @@ export const limitationsFor = (operation) => {
|
|
|
79
86
|
];
|
|
80
87
|
case "search_procedures":
|
|
81
88
|
case "search_strings":
|
|
82
|
-
return
|
|
89
|
+
return [
|
|
90
|
+
...common,
|
|
91
|
+
"Regex mode uses Java Pattern semantics. Matcher or compiler stack exhaustion returns a resource constraint without closing the session; literal mode avoids regex recursion and returns complete matching values.",
|
|
92
|
+
];
|
|
83
93
|
case "procedure_pseudo_code":
|
|
84
94
|
return [
|
|
85
95
|
...common,
|
|
@@ -112,12 +122,14 @@ export const limitationsFor = (operation) => {
|
|
|
112
122
|
case "procedure_references":
|
|
113
123
|
return [
|
|
114
124
|
...common,
|
|
125
|
+
"References cover the complete Ghidra function-body AddressSet and exact entry, including instruction-interior destinations and embedded-data sources; an enclosing address span does not establish function ownership.",
|
|
115
126
|
"Reference kinds are direct Ghidra ReferenceManager observations; unresolved computed flows without a target are absent and remain unknown.",
|
|
116
127
|
"Synthetic Ghidra entry-point references without actionable memory sources are omitted.",
|
|
117
128
|
];
|
|
118
129
|
case "analyze_function":
|
|
119
130
|
return [
|
|
120
131
|
...common,
|
|
132
|
+
"References cover the complete Ghidra function-body AddressSet and exact entry. Dossier incoming edges omit sources owned by that function; procedure_references also retains those internal edges.",
|
|
121
133
|
"The dossier combines Ghidra FunctionManager, Listing, ReferenceManager, BasicBlockModel, and decompiler observations; provider-specific pseudocode and assembly are not cross-provider text invariants.",
|
|
122
134
|
"Resolved reference metadata identifies computed, indirect, external, call, jump, and data edges; unresolved targetless flows remain unknown, and function classifications distinguish thunks and externals.",
|
|
123
135
|
"Synthetic Ghidra entry-point references without actionable memory sources are omitted.",
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { fileURLToPath } from "node:url";
|
|
2
2
|
import { createAnalysisExecution, } from "../application/AnalysisProvider.js";
|
|
3
|
-
import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisTimeoutError, } from "../domain/analysisErrorCore.js";
|
|
3
|
+
import { AnalysisCancelledError, AnalysisArtifactChangedError, AnalysisAccessDeniedError, AnalysisCapabilityUnavailableError, AnalysisInputError, AnalysisResourceConstraintError, AnalysisTimeoutError, } from "../domain/analysisErrorCore.js";
|
|
4
4
|
import {} from "../domain/analysisErrorBase.js";
|
|
5
5
|
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
|
|
6
6
|
import { err, ok } from "../domain/result.js";
|
|
7
7
|
import { GhidraClient } from "./GhidraClient.js";
|
|
8
|
-
import { GHIDRA_STARTUP_TIMEOUT_MS } from "./GhidraDefaults.js";
|
|
9
8
|
import { isGhidraFunctionOperation, parseGhidraFunctionInput, parseGhidraFunctionResult, } from "./GhidraFunctionValues.js";
|
|
10
9
|
import { isGhidraInventoryOperation, parseGhidraInventoryInput, parseGhidraInventoryResult, } from "./GhidraInventoryValues.js";
|
|
11
10
|
import { ghidraInstallationDiagnostics, } from "./GhidraInstallation.js";
|
|
@@ -55,12 +54,11 @@ export const createGhidraProviderClient = (input) => {
|
|
|
55
54
|
]
|
|
56
55
|
: [];
|
|
57
56
|
const client = clientFactory({
|
|
57
|
+
startupTimeoutMs: config.ghidraStartupTimeoutMs,
|
|
58
58
|
platform: installation.platform,
|
|
59
59
|
launcher: new GhidraHeadlessLauncher({
|
|
60
60
|
analyzeHeadlessPath: prerequisites.value.analyzeHeadlessPath,
|
|
61
|
-
|
|
62
|
-
? {}
|
|
63
|
-
: { javaHome: config.ghidraJavaHome }),
|
|
61
|
+
javaHome: prerequisites.value.javaHome,
|
|
64
62
|
bridgeScriptPath: fileURLToPath(new URL("../../bridge/ghidra/ReaGhidraBridge.java", import.meta.url)),
|
|
65
63
|
...(target.format === "dos-mz" ? { dosMz: true } : {}),
|
|
66
64
|
...(target.format === "dos-com" ? { dosCom: true } : {}),
|
|
@@ -110,7 +108,7 @@ export const createGhidraProviderClient = (input) => {
|
|
|
110
108
|
if (operation === "health") {
|
|
111
109
|
const started = await client.start(options?.signal);
|
|
112
110
|
if (!started.ok)
|
|
113
|
-
return err(projectSessionError(operation, started.error));
|
|
111
|
+
return err(projectSessionError(operation, started.error, config.ghidraStartupTimeoutMs));
|
|
114
112
|
const failed = await checkExtensions(operation, started.value);
|
|
115
113
|
if (failed !== undefined)
|
|
116
114
|
return err(failed);
|
|
@@ -127,14 +125,14 @@ export const createGhidraProviderClient = (input) => {
|
|
|
127
125
|
if (extensions.length > 0) {
|
|
128
126
|
const started = await client.start(options?.signal);
|
|
129
127
|
if (!started.ok)
|
|
130
|
-
return err(projectSessionError(operation, started.error));
|
|
128
|
+
return err(projectSessionError(operation, started.error, config.ghidraStartupTimeoutMs));
|
|
131
129
|
const failed = await checkExtensions(operation, started.value);
|
|
132
130
|
if (failed !== undefined)
|
|
133
131
|
return err(failed);
|
|
134
132
|
}
|
|
135
133
|
const called = await client.callTool(operation, input.value, options?.signal === undefined ? {} : { signal: options.signal });
|
|
136
134
|
if (!called.ok)
|
|
137
|
-
return err(projectSessionError(operation, called.error));
|
|
135
|
+
return err(projectSessionError(operation, called.error, config.ghidraStartupTimeoutMs));
|
|
138
136
|
const result = isGhidraFunctionOperation(operation)
|
|
139
137
|
? parseGhidraFunctionResult(operation, called.value)
|
|
140
138
|
: parseGhidraInventoryResult(operation, called.value);
|
|
@@ -142,7 +140,7 @@ export const createGhidraProviderClient = (input) => {
|
|
|
142
140
|
return result;
|
|
143
141
|
let normalized = result.value;
|
|
144
142
|
if (operation === "inspect_native_load_image") {
|
|
145
|
-
const attested = await attestGhidraNativeLoadImage(target, operation, result.value, client, (failure) => projectSessionError(operation, failure));
|
|
143
|
+
const attested = await attestGhidraNativeLoadImage(target, operation, result.value, client, (failure) => projectSessionError(operation, failure, config.ghidraStartupTimeoutMs));
|
|
146
144
|
if (!attested.ok)
|
|
147
145
|
return attested;
|
|
148
146
|
normalized = attested.value;
|
|
@@ -176,6 +174,7 @@ const ghidraClientPrerequisites = (target, profile, installation) => {
|
|
|
176
174
|
return err(new ProviderAdapterError("ghidra", "health"));
|
|
177
175
|
return ok({
|
|
178
176
|
analyzeHeadlessPath: installation.analyzeHeadlessPath,
|
|
177
|
+
javaHome: installation.javaHome,
|
|
179
178
|
providerVersion: installation.providerVersion,
|
|
180
179
|
profile,
|
|
181
180
|
});
|
|
@@ -184,7 +183,11 @@ const unavailableClient = (failure) => ({
|
|
|
184
183
|
execute: () => Promise.resolve(err(failure)),
|
|
185
184
|
close: () => Promise.resolve(),
|
|
186
185
|
});
|
|
187
|
-
const projectSessionError = (operation, failure) => {
|
|
186
|
+
const projectSessionError = (operation, failure, startupTimeoutMs) => {
|
|
187
|
+
if (failure.cause instanceof AnalysisAccessDeniedError)
|
|
188
|
+
return new AnalysisAccessDeniedError(operation, failure.cause.path, failure.cause.systemCode, { cause: failure });
|
|
189
|
+
if (failure.cause instanceof AnalysisArtifactChangedError)
|
|
190
|
+
return new AnalysisArtifactChangedError(operation, failure.cause.path, failure.cause.reason, { cause: failure });
|
|
188
191
|
if (operation === "annotate_native_function" &&
|
|
189
192
|
failure.kind === "remote" &&
|
|
190
193
|
failure.remoteCode === "invalid_function_name")
|
|
@@ -194,12 +197,20 @@ const projectSessionError = (operation, failure) => {
|
|
|
194
197
|
if (failure.kind === "cancelled")
|
|
195
198
|
return new AnalysisCancelledError(operation);
|
|
196
199
|
if (failure.kind === "timeout" || failure.kind === "analysis_timeout")
|
|
197
|
-
return new AnalysisTimeoutError(operation, failure.timeoutMs ??
|
|
200
|
+
return new AnalysisTimeoutError(operation, failure.timeoutMs ?? startupTimeoutMs);
|
|
198
201
|
if (failure.kind === "remote" && failure.remoteCode === "decompile_cancelled")
|
|
199
202
|
return new AnalysisCancelledError(operation);
|
|
203
|
+
if (failure.kind === "remote" &&
|
|
204
|
+
failure.remoteCode === "regex_stack_exhausted")
|
|
205
|
+
return new AnalysisResourceConstraintError(operation, "memory", failure.message, null, {
|
|
206
|
+
cause: failure,
|
|
207
|
+
remediationAction: "Retry this search in literal mode or simplify the regex. The active analysis session and annotations remain available.",
|
|
208
|
+
});
|
|
200
209
|
if (failure.kind === "remote" &&
|
|
201
210
|
["invalid_request", "not_found", "ambiguous"].includes(failure.remoteCode ?? ""))
|
|
202
|
-
return new AnalysisInputError(operation, { cause: failure }
|
|
211
|
+
return new AnalysisInputError(operation, { cause: failure }, [
|
|
212
|
+
{ path: [], reason: "invalid_value", message: failure.message },
|
|
213
|
+
]);
|
|
203
214
|
if (failure.kind === "remote" && failure.remoteCode === "method_unavailable")
|
|
204
215
|
return new AnalysisCapabilityUnavailableError("ghidra", operation, failure.message);
|
|
205
216
|
return new ProviderAdapterError("ghidra", operation, {
|
|
@@ -14,13 +14,17 @@ export class GhidraSessionError extends Error {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
/** Build a session failure while preserving bounded remote failure metadata. */
|
|
17
|
-
const createGhidraSessionError = (failure) => new GhidraSessionError(failure.kind, failure.message,
|
|
18
|
-
|
|
19
|
-
:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
const createGhidraSessionError = (failure) => new GhidraSessionError(failure.kind, failure.message, {
|
|
18
|
+
...failure.diagnostics,
|
|
19
|
+
failure_kind: failure.kind,
|
|
20
|
+
failure_message: failure.message,
|
|
21
|
+
...(failure.remoteCode === undefined
|
|
22
|
+
? {}
|
|
23
|
+
: {
|
|
24
|
+
remote_code: failure.redact(failure.remoteCode),
|
|
25
|
+
remote_message: failure.message,
|
|
26
|
+
}),
|
|
27
|
+
}, {
|
|
24
28
|
...(failure.cause === undefined ? {} : { cause: failure.cause }),
|
|
25
29
|
...(failure.timeoutMs === undefined
|
|
26
30
|
? {}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { constants
|
|
3
|
-
import {
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { open, rm } from "node:fs/promises";
|
|
4
4
|
import { extname, join } from "node:path";
|
|
5
|
+
import { Transform } from "node:stream";
|
|
6
|
+
import { pipeline } from "node:stream/promises";
|
|
7
|
+
import { AnalysisArtifactChangedError, AnalysisAccessDeniedError, } from "../domain/analysisErrorCore.js";
|
|
5
8
|
import { windowsPrivateRuntime } from "../windows/WindowsPrivateRuntime.js";
|
|
6
9
|
/** Copy one target and require its bytes to match the parsed target identity. */
|
|
7
10
|
export const createGhidraTargetSnapshot = async (sourcePath, runtimeRoot, expectedSha256, options = {}) => {
|
|
@@ -12,29 +15,61 @@ export const createGhidraTargetSnapshot = async (sourcePath, runtimeRoot, expect
|
|
|
12
15
|
if ((options.platform ?? process.platform) === "win32") {
|
|
13
16
|
const observed = await windowsPrivateRuntime(runtimeRoot).snapshot(sourcePath, `target-${expectedSha256.slice(0, 12)}${suffix}`, options.signal);
|
|
14
17
|
if (observed.sha256 !== expectedSha256)
|
|
15
|
-
throw new
|
|
18
|
+
throw new AnalysisArtifactChangedError("open_binary", sourcePath, `Ghidra target snapshot digest mismatch: expected ${expectedSha256}, observed ${observed.sha256}`);
|
|
16
19
|
return {
|
|
17
20
|
path: snapshotPath,
|
|
18
21
|
sha256: observed.sha256,
|
|
19
22
|
admission: { source: observed.source, snapshot: observed.snapshot },
|
|
20
23
|
};
|
|
21
24
|
}
|
|
25
|
+
let source;
|
|
26
|
+
let destination;
|
|
22
27
|
try {
|
|
23
|
-
await
|
|
24
|
-
await
|
|
28
|
+
source = await openSnapshotSource(sourcePath);
|
|
29
|
+
if (!(await source.stat()).isFile())
|
|
30
|
+
throw new AnalysisArtifactChangedError("open_binary", sourcePath, "The selected Ghidra source is no longer a regular file");
|
|
31
|
+
destination = await open(snapshotPath, "wx", 0o600);
|
|
32
|
+
await destination.chmod(0o600);
|
|
25
33
|
const hash = createHash("sha256");
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
const digest = new Transform({
|
|
35
|
+
transform(chunk, _encoding, done) {
|
|
36
|
+
if (!Buffer.isBuffer(chunk)) {
|
|
37
|
+
done(new TypeError("Ghidra snapshot stream must contain bytes"));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
hash.update(chunk);
|
|
41
|
+
done(null, chunk);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
await pipeline(source.createReadStream(), digest, destination.createWriteStream(), options.signal === undefined ? {} : { signal: options.signal });
|
|
28
45
|
const observedSha256 = hash.digest("hex");
|
|
29
46
|
if (observedSha256 !== expectedSha256)
|
|
30
|
-
throw new
|
|
47
|
+
throw new AnalysisArtifactChangedError("open_binary", sourcePath, `Ghidra target snapshot digest mismatch: expected ${expectedSha256}, observed ${observedSha256}`);
|
|
31
48
|
return { path: snapshotPath, sha256: observedSha256 };
|
|
32
49
|
}
|
|
33
50
|
catch (cause) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
51
|
+
if (destination !== undefined)
|
|
52
|
+
await rm(snapshotPath, { force: true }).catch((cause) => {
|
|
53
|
+
// best-effort cleanup: snapshot removal must not mask the copy failure.
|
|
54
|
+
void cause;
|
|
55
|
+
});
|
|
56
|
+
throw cause;
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
await Promise.all([source?.close(), destination?.close()]);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const openSnapshotSource = async (path) => {
|
|
63
|
+
try {
|
|
64
|
+
// A path replaced by a FIFO must not block startup before its type is checked.
|
|
65
|
+
return await open(path, constants.O_RDONLY | constants.O_NONBLOCK);
|
|
66
|
+
}
|
|
67
|
+
catch (cause) {
|
|
68
|
+
const code = cause instanceof Error && "code" in cause ? cause.code : undefined;
|
|
69
|
+
if (code === "EACCES" || code === "EPERM")
|
|
70
|
+
throw new AnalysisAccessDeniedError("open_binary", path, code, { cause });
|
|
71
|
+
if (code === "ENOENT" || code === "ENOTDIR" || code === "ELOOP")
|
|
72
|
+
throw new AnalysisArtifactChangedError("open_binary", path, `The selected Ghidra source could not be opened (${code})`, { cause });
|
|
38
73
|
throw cause;
|
|
39
74
|
}
|
|
40
75
|
};
|
|
@@ -1,7 +1,27 @@
|
|
|
1
1
|
import { access, open } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { PrivateRuntimeRoot } from "../process/PrivateRuntimeRoot.js";
|
|
2
4
|
import { readWindowsPrivateRuntimeFile } from "../windows/WindowsPrivateRuntime.js";
|
|
3
5
|
import { err, ok } from "../domain/result.js";
|
|
4
6
|
import { GhidraSessionError } from "./GhidraSessionError.js";
|
|
7
|
+
/** Allocate an endpoint that fits the host's Unix sockaddr without moving the project. */
|
|
8
|
+
export const createGhidraEndpoint = async (runtimeRoot, transport, platform) => {
|
|
9
|
+
const path = join(runtimeRoot, transport === "unix-socket" ? "bridge.sock" : "bridge-endpoint.json");
|
|
10
|
+
// sockaddr_un includes a terminating NUL: macOS has 104 bytes, Linux 108.
|
|
11
|
+
const maximumPathBytes = platform === "darwin" ? 103 : 107;
|
|
12
|
+
if (transport !== "unix-socket" ||
|
|
13
|
+
Buffer.byteLength(path, "utf8") <= maximumPathBytes)
|
|
14
|
+
return { endpoint: { transport, path } };
|
|
15
|
+
const socketRoot = await PrivateRuntimeRoot.create({
|
|
16
|
+
parent: "/tmp",
|
|
17
|
+
prefix: "rea-ghidra-socket-",
|
|
18
|
+
platform,
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
endpoint: { transport, path: join(socketRoot.path, "s") },
|
|
22
|
+
socketRoot,
|
|
23
|
+
};
|
|
24
|
+
};
|
|
5
25
|
/** Observe a ready endpoint, returning null while its bridge is not listening. */
|
|
6
26
|
export const observeGhidraEndpoint = async (endpoint) => {
|
|
7
27
|
if (endpoint.transport === "unix-socket") {
|