rea-agents 4.0.0 → 4.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 +93 -30
- package/bridge/ghidra/ReaGhidraBridge.java +358 -15
- package/bridge/ghidra/ReaGhidraExtensions.java +113 -0
- package/bridge/ghidra/ReaGhidraPrepareCom.java +32 -0
- package/dist/android/AndroidTargetSnapshot.js +34 -0
- package/dist/android/JadxAnalysis.js +191 -0
- package/dist/android/JadxConfiguration.js +41 -0
- package/dist/android/JadxMcpTransport.js +145 -0
- package/dist/android/JadxProtocol.js +101 -0
- package/dist/android/JadxProvider.js +170 -0
- package/dist/android/JadxRelease.js +19 -0
- package/dist/android/JadxSession.js +97 -0
- package/dist/application/AnalysisContextQueries.js +2 -1
- package/dist/application/AnalysisProviderEvaluation.js +5 -3
- package/dist/application/AnalysisProviderRegistry.js +2 -1
- package/dist/application/AnalysisSnapshotCache.js +4 -1
- package/dist/application/AnalysisSnapshotFiles.js +1 -1
- package/dist/application/AndroidAnalysisPort.js +1 -0
- package/dist/application/AndroidAnalysisService.js +37 -0
- package/dist/application/ArtifactExtraction.js +7 -4
- package/dist/application/ArtifactGraphConstruction.js +10 -17
- package/dist/application/ArtifactInventory/scanCanonical.js +8 -7
- package/dist/application/BinarySession.js +16 -3
- package/dist/application/BinarySessionExecution.js +4 -1
- package/dist/application/BinarySessionOpen.js +3 -2
- package/dist/application/BinarySessionRecords.js +9 -3
- package/dist/application/BinaryTargetResolver.js +25 -6
- package/dist/application/BrowserObservationService.js +2 -1
- package/dist/application/BrowserScenarioCaptureService.js +2 -1
- package/dist/application/BrowserScenarioEvidence.js +2 -2
- package/dist/application/CallPathTracing.js +2 -1
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/ClientConfigPath.js +3 -1
- package/dist/application/ClientConfigurationDocument.js +11 -1
- package/dist/application/ClientRegistrationStatus.js +8 -1
- package/dist/application/CompositeProvider.js +1 -1
- package/dist/application/DirectAnalysis.js +23 -7
- package/dist/application/DirectAnalysisStatus.js +3 -3
- package/dist/application/Doctor.js +48 -8
- package/dist/application/DoctorDiagnostics.js +7 -5
- package/dist/application/DoctorScope.js +1 -1
- package/dist/application/ElectronActiveEvidence.js +2 -2
- package/dist/application/ElectronActiveObservationService.js +2 -1
- package/dist/application/ElectronBoundaryAnalysis.js +1 -1
- package/dist/application/ElectronObservationService.js +2 -1
- package/dist/application/EnhancedLiteralTracing.js +2 -1
- package/dist/application/EnhancedToolTypes.js +2 -1
- package/dist/application/EnhancedTools.js +3 -1
- package/dist/application/EvidenceBundleCommands.js +2 -1
- package/dist/application/EvidenceBundleFiles.js +1 -1
- package/dist/application/EvidenceInputResolver.js +30 -0
- package/dist/application/EvidenceLedger.js +2 -1
- package/dist/application/FirmwareAnalysisPort.js +1 -0
- package/dist/application/FirmwareAnalysisService.js +35 -0
- package/dist/application/FunctionAnalysisEvidence.js +32 -0
- package/dist/application/InventoryProjectionEvidence.js +2 -1
- package/dist/application/JavaScriptApplicationService.js +50 -3
- package/dist/application/JavaScriptApplicationWorkflowService.js +2 -1
- package/dist/application/JavaScriptArtifactAnalysis.js +4 -2
- package/dist/application/JavaScriptArtifactFiles.js +4 -2
- package/dist/application/JavaScriptArtifactPathResolution.js +6 -2
- package/dist/application/JavaScriptJsonModules.js +3 -2
- package/dist/application/JavaScriptModuleRelationships.js +4 -2
- package/dist/application/JavaScriptRuntimeObservationService.js +2 -1
- package/dist/application/JavaScriptRuntimeReconciliationService.js +2 -1
- package/dist/application/JavaScriptSemanticGraphProjection.js +1 -1
- package/dist/application/JavaScriptSemanticTraceService.js +2 -1
- package/dist/application/JsonFiles.js +1 -1
- package/dist/application/LazyAnalysisProvider.js +3 -1
- package/dist/application/LinuxHopper.js +12 -4
- package/dist/application/MacHopper.js +20 -7
- package/dist/application/ManagedApplicationGraphService.js +2 -1
- package/dist/application/ManagedMemberComparisonService.js +3 -1
- package/dist/application/ManagedNativeVerificationService.js +2 -1
- package/dist/application/ManagedReconstructionService.js +2 -1
- package/dist/application/NativeCallRoutes.js +1 -1
- package/dist/application/NativeDispatchMetadataInspection.js +1 -1
- package/dist/application/NativeUiActionTrace.js +2 -1
- package/dist/application/NativeValueTrace.js +1 -1
- package/dist/application/ProcessCaptureError.js +1 -1
- package/dist/application/ProcessCaptureJournal.js +3 -1
- package/dist/application/ProcessCaptureLifecycle.js +6 -3
- package/dist/application/ProcessCli.js +9 -5
- package/dist/application/ProcessEvidence.js +2 -6
- package/dist/application/ProcessHarness.js +3 -2
- package/dist/application/ProcessNormalization.js +12 -5
- package/dist/application/ProcessSampling.js +3 -1
- package/dist/application/ReconstructionCoverageService.js +2 -1
- package/dist/application/ReconstructionObligationLedgerService.js +2 -1
- package/dist/application/ReferenceSourceImportEntries.js +2 -0
- package/dist/application/ReferenceSourceImportPolicy.js +4 -2
- package/dist/application/ReferenceSourceVcsAdapter.js +35 -4
- package/dist/application/SessionProviderRouter.js +4 -1
- package/dist/application/Setup.js +1 -128
- package/dist/application/SetupClientConfiguration.js +17 -6
- package/dist/application/SetupHost.js +111 -0
- package/dist/application/SetupRegistrationEnvironment.js +1 -2
- package/dist/application/SetupSkill.js +9 -3
- package/dist/application/SetupTypes.js +17 -0
- package/dist/application/StoreFileLock.js +7 -2
- package/dist/application/SupportedClients.js +8 -0
- package/dist/application/Uninstall.js +9 -4
- package/dist/application/UpdateRuntime.js +5 -2
- package/dist/application/WindowsCapabilities.js +7 -7
- package/dist/application/runtime.js +3 -1
- package/dist/artifacts/ArtifactProvider.js +3 -1
- package/dist/artifacts/DirectoryArtifactReader.js +2 -0
- package/dist/artifacts/NativeDmgArtifactReader.js +10 -3
- package/dist/artifacts/NibArchive.js +4 -2
- package/dist/artifacts/SafeOutputTree.js +26 -10
- package/dist/artifacts/ZipArtifactReader.js +1 -0
- package/dist/browser/BrowserProcessStartup.js +3 -1
- package/dist/browser/CdpAuthorizedMainFrame.js +1 -1
- package/dist/browser/CdpBrowserProvider.js +4 -1
- package/dist/browser/CdpCaptureDocuments.js +3 -1
- package/dist/browser/CdpCaptureEventHandlers.js +6 -2
- package/dist/browser/CdpCaptureStorageFingerprints.js +1 -1
- package/dist/browser/CdpCaptureValues.js +6 -2
- package/dist/browser/CdpConnection.js +8 -6
- package/dist/browser/CdpElectronInspection.js +3 -3
- package/dist/browser/CdpElectronProvider.js +4 -1
- package/dist/browser/CdpElectronScripts.js +2 -2
- package/dist/browser/CdpEndpoint.js +22 -10
- package/dist/browser/CdpObservationSession.js +2 -1
- package/dist/browser/CdpOptionalCommand.js +1 -1
- package/dist/browser/CdpPageCapture.js +2 -1
- package/dist/browser/CdpSafeMetadata.js +53 -8
- package/dist/browser/CdpScreenshot.js +1 -1
- package/dist/browser/CdpTargetSession.js +8 -5
- package/dist/browser/CdpWebMcpDiscovery.js +1 -1
- package/dist/browser/ElectronFileScope.js +9 -3
- package/dist/browser/JavaScriptRuntimeScope.js +3 -1
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +3 -1
- package/dist/browser/PlaywrightElectronActiveActions.js +1 -1
- package/dist/browser/PlaywrightElectronActiveProvider.js +6 -2
- package/dist/browser/PlaywrightExecutionBoundary.js +1 -1
- package/dist/browser/PlaywrightScenarioArtifacts.js +10 -5
- package/dist/browser/PlaywrightScenarioBrowser.js +3 -1
- package/dist/browser/PlaywrightScenarioEvents.js +6 -2
- package/dist/browser/PlaywrightScenarioSession.js +5 -2
- package/dist/browser/V8InspectorEndpoint.js +2 -1
- package/dist/browser/V8InspectorProvider.js +6 -1
- package/dist/browser/WebSourceMapFetcher.js +24 -11
- package/dist/cli/androidCommands.js +81 -0
- package/dist/{cliApplicationCommands.js → cli/applicationCommands.js} +18 -16
- package/dist/{cliBrowserAdvancedCommands.js → cli/browserAdvancedCommands.js} +13 -16
- package/dist/{cliBrowserCommands.js → cli/browserCommands.js} +9 -9
- package/dist/cli/commandCancellation.js +24 -0
- package/dist/cli/coreAnalysisCommands.js +110 -17
- package/dist/{cliElectronCommands.js → cli/electronCommands.js} +14 -13
- package/dist/cli/firmwareCommands.js +75 -0
- package/dist/{cliSetup.js → cli/interactiveSetup.js} +1 -1
- package/dist/cli/javascriptApplicationAnalysis.js +1 -1
- package/dist/cli/managedCommands.js +1 -1
- package/dist/cli/managedProjectGraphCommand.js +1 -1
- package/dist/cli/options.js +7 -1
- package/dist/{cliProcessCommands.js → cli/processCommands.js} +3 -3
- package/dist/cli/referenceSourceImportStatus.js +10 -0
- package/dist/cli/setupCommands.js +4 -2
- package/dist/cli/utilityCommands.js +3 -2
- package/dist/cli.js +10 -15
- package/dist/cliBrowserContext.js +1 -1
- package/dist/cliBrowserScenarioCommands.js +2 -1
- package/dist/cliCommandNames.js +11 -2
- package/dist/cliEvidenceCommands.js +2 -1
- package/dist/cliJavaScriptRuntimeCommands.js +2 -1
- package/dist/cliJsonInput.js +26 -11
- package/dist/cliLogging.js +2 -1
- package/dist/cliOutput.js +15 -16
- package/dist/config/environment.js +11 -1
- package/dist/config/parseConfig.js +7 -1
- package/dist/config/parsers.js +1 -1
- package/dist/contracts/androidToolContracts.js +77 -0
- package/dist/contracts/applicationToolContracts.js +32 -5
- package/dist/contracts/applicationWorkflowInputContracts.js +13 -13
- package/dist/contracts/artifactComparisonExample.js +7 -14
- package/dist/contracts/enhancedToolContracts.js +31 -0
- package/dist/contracts/errorSchemas.js +4 -2
- package/dist/contracts/evidenceInputContracts.js +13 -0
- package/dist/contracts/firmwareToolContracts.js +38 -0
- package/dist/contracts/officialToolContracts.js +66 -0
- package/dist/contracts/promptContracts.js +1 -1
- package/dist/contracts/sessionLifecycleInputs.js +4 -0
- package/dist/contracts/sessionToolContracts.js +43 -0
- package/dist/contracts/sessionToolSchemas.js +1 -1
- package/dist/contracts/toolContractExamples.js +5 -0
- package/dist/contracts/toolContractTypes.js +2 -0
- package/dist/contracts/toolContracts.js +7 -130
- package/dist/contracts/toolEffects.js +43 -0
- package/dist/contracts/toolOutputSchemaGroups.js +4 -0
- package/dist/contracts/toolOutputSchemaPrimitives.js +1 -0
- package/dist/doctorRuntime.js +5 -1
- package/dist/domain/analysisErrorBase.js +33 -0
- package/dist/domain/analysisErrorCore.js +60 -0
- package/dist/domain/analysisErrorPresentation.js +22 -2
- package/dist/domain/analysisErrorProjection.js +24 -3
- package/dist/domain/analysisSnapshot.js +1 -0
- package/dist/domain/androidAnalysis.js +141 -0
- package/dist/domain/appleAssetCatalog.js +1 -1
- package/dist/domain/artifactGraph.js +1 -0
- package/dist/domain/artifactInspection.js +19 -17
- package/dist/domain/artifactInventoryEvidence.js +20 -25
- package/dist/domain/artifactOperationError.js +16 -0
- package/dist/domain/browserObservation.js +12 -4
- package/dist/domain/browserObservationError.js +23 -0
- package/dist/domain/browserScenario.js +1 -1
- package/dist/domain/browserScenarioCapture.js +1 -1
- package/dist/domain/browserScenarioDiff.js +1 -1
- package/dist/domain/browserScenarioNormalization.js +6 -11
- package/dist/domain/browserScenarioValues.js +3 -1
- package/dist/domain/callPath.js +47 -7
- package/dist/domain/canonicalDigest.js +65 -0
- package/dist/domain/canonicalOrdering.js +11 -0
- package/dist/domain/changedBehavior.js +8 -7
- package/dist/domain/comparisonSemantics.js +2 -4
- package/dist/domain/configurationErrors.js +25 -0
- package/dist/domain/dosCom.js +8 -0
- package/dist/domain/electronActiveObservation.js +3 -1
- package/dist/domain/electronStaticAnalysisBrowser.js +13 -23
- package/dist/domain/electronStaticAnalysisNative.js +2 -1
- package/dist/domain/electronStaticAnalysisValues.js +23 -3
- package/dist/domain/evidence.js +3 -11
- package/dist/domain/evidenceErrors.js +30 -0
- package/dist/domain/firmwareAnalysis.js +121 -0
- package/dist/domain/functionComparison.js +4 -2
- package/dist/domain/functionComparisonDimensions.js +6 -4
- package/dist/domain/functionComparisonNormalization.js +8 -1
- package/dist/domain/functionComparisonResults.js +1 -4
- package/dist/domain/hopperErrors.js +78 -0
- package/dist/domain/hopperValues.js +2 -1
- package/dist/domain/interfaceBuilderGraph.js +3 -1
- package/dist/domain/javascriptApplicationChangeGraph.js +2 -2
- package/dist/domain/javascriptApplicationGraph.js +13 -22
- package/dist/domain/javascriptApplicationVersionComparison.js +3 -11
- package/dist/domain/javascriptApplicationVersionItems.js +3 -3
- package/dist/domain/javascriptApplicationVersionKeys.js +1 -1
- package/dist/domain/javascriptAstFingerprint.js +1 -1
- package/dist/domain/javascriptExportShapeComparison.js +1 -2
- package/dist/domain/javascriptExportShapeSelection.js +1 -1
- package/dist/domain/javascriptExportShapeVariants.js +7 -3
- package/dist/domain/javascriptFeatureSeed.js +29 -9
- package/dist/domain/javascriptFeatureTrace.js +9 -13
- package/dist/domain/javascriptFeatureTraversal.js +2 -1
- package/dist/domain/javascriptNativeHandoff.js +2 -1
- package/dist/domain/javascriptRuntimeLoadState.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationActive.js +3 -10
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +4 -3
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +8 -14
- package/dist/domain/javascriptRuntimeReconciliationResult.js +4 -4
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +5 -2
- package/dist/domain/javascriptRuntimeStaticCandidates.js +8 -4
- package/dist/domain/javascriptSemanticAnalysis.js +40 -3
- package/dist/domain/javascriptSemanticCallResolution.js +2 -1
- package/dist/domain/javascriptSemanticChildProcesses.js +2 -1
- package/dist/domain/javascriptSemanticDataEffects.js +2 -1
- package/dist/domain/javascriptSemanticFingerprints.js +1 -1
- package/dist/domain/javascriptSemanticGraph.js +23 -28
- package/dist/domain/javascriptSemanticPrimitives.js +9 -2
- package/dist/domain/javascriptSemanticProjection.js +2 -1
- package/dist/domain/javascriptSemanticPromises.js +2 -1
- package/dist/domain/javascriptSemanticProvenance.js +1 -1
- package/dist/domain/javascriptSemanticQuery.js +7 -8
- package/dist/domain/javascriptSemanticQueryAssessment.js +1 -2
- package/dist/domain/javascriptSemanticQueryIdentity.js +1 -2
- package/dist/domain/javascriptSemanticReturns.js +2 -1
- package/dist/domain/javascriptSemanticValues.js +50 -16
- package/dist/domain/javascriptSourceParser.js +4 -2
- package/dist/domain/javascriptStaticAnalysis.js +1 -1
- package/dist/domain/javascriptStaticAnalysisBundler.js +2 -1
- package/dist/domain/javascriptStaticAnalysisCalls.js +14 -6
- package/dist/domain/javascriptStaticAnalysisHelpers.js +31 -4
- package/dist/domain/jsonShape.js +6 -2
- package/dist/domain/managedMemberComparison.js +1 -0
- package/dist/domain/managedMemberComparisonItems.js +2 -0
- package/dist/domain/managedNativeVerificationMatch.js +5 -3
- package/dist/domain/nativeDataType.js +2 -0
- package/dist/domain/nativeFunctionAnnotations.js +43 -0
- package/dist/domain/nativeLoadImage.js +95 -0
- package/dist/domain/nativeMetadataRecovery.js +55 -0
- package/dist/domain/processCapture.js +0 -1
- package/dist/domain/processEvidenceProvider.js +11 -0
- package/dist/domain/processTraceComparison.js +1 -1
- package/dist/domain/providerAdapterError.js +17 -0
- package/dist/domain/providerCleanupError.js +1 -1
- package/dist/domain/providerSelectionError.js +44 -0
- package/dist/domain/reconstructionUnknowns.js +1 -1
- package/dist/domain/reconstructionVerification.js +22 -8
- package/dist/domain/referenceSourceClassification.js +5 -6
- package/dist/domain/referenceSourceGraph.js +9 -17
- package/dist/domain/referenceSourceImportParsing.js +38 -23
- package/dist/domain/runtimeIdentification.js +1 -1
- package/dist/domain/runtimeVersion.js +4 -7
- package/dist/domain/safeJson.js +13 -0
- package/dist/domain/sourceToBundleComparison.js +5 -7
- package/dist/domain/sourceToBundleSignals.js +6 -6
- package/dist/domain/staticRuntimeCorrelation.js +9 -7
- package/dist/domain/unknownRegistryError.js +10 -0
- package/dist/domain/webBundleAnalyzerAst.js +22 -5
- package/dist/domain/webBundleAnalyzerInspection.js +20 -14
- package/dist/dotnet/ManagedMemberRows.js +1 -1
- package/dist/dotnet/ManagedMetadataHeaps.js +3 -2
- package/dist/dotnet/ManagedMetadataInventoryRows.js +4 -2
- package/dist/dotnet/ManagedMethodBodyReader.js +8 -1
- package/dist/dotnet/ManagedStaticProvider.js +3 -1
- package/dist/firmware/FirmwareCommand.js +163 -0
- package/dist/firmware/FirmwareFiles.js +190 -0
- package/dist/firmware/FirmwareProvider.js +258 -0
- package/dist/firmware/FirmwarePublication.js +84 -0
- package/dist/firmware/FirmwareRelease.js +32 -0
- package/dist/firmware/FirmwareReports.js +223 -0
- package/dist/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +5 -5
- package/dist/ghidra/GhidraAnalysisProfile.js +37 -8
- package/dist/ghidra/GhidraClient.js +52 -6
- package/dist/ghidra/GhidraDiagnostics.js +3 -0
- package/dist/ghidra/GhidraDoctor.js +38 -14
- package/dist/ghidra/GhidraFunctionValues.js +10 -4
- package/dist/ghidra/GhidraInstallation.js +10 -4
- package/dist/ghidra/GhidraInventoryValues.js +39 -2
- package/dist/ghidra/GhidraLauncher.js +91 -26
- package/dist/ghidra/GhidraLoadImageValues.js +199 -0
- package/dist/ghidra/GhidraProvider.js +129 -13
- package/dist/ghidra/GhidraProviderCapabilities.js +52 -15
- package/dist/ghidra/GhidraRequestQueue.js +2 -2
- package/dist/ghidra/GhidraSessionError.js +31 -4
- package/dist/ghidra/GhidraSessionValues.js +10 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +16 -2
- package/dist/ghidra/GhidraTransport.js +12 -0
- package/dist/ghidra/extensions/GhidraExtensionFailures.js +20 -0
- package/dist/ghidra/extensions/GhidraExtensions.js +170 -0
- package/dist/ghidra/extensions/nativeaot/NativeAotAdapter.js +21 -0
- package/dist/ghidra/extensions/nativeaot/NativeAotReport.js +84 -0
- package/dist/hopper/BridgeLauncher.js +4 -2
- package/dist/hopper/HopperAnalysisProfile.js +7 -2
- package/dist/hopper/HopperCleanup.js +55 -9
- package/dist/hopper/HopperClient.js +14 -4
- package/dist/hopper/HopperProcessDiagnostic.js +1 -1
- package/dist/hopper/HopperProvider.js +8 -4
- package/dist/hopper/HopperRequestQueue.js +7 -3
- package/dist/hopper/HopperSessionValues.js +1 -1
- package/dist/hopper/HopperSocketConnection.js +1 -1
- package/dist/hopper/HopperTargetLease.js +23 -15
- package/dist/hopper/LinuxPrivateDisplayDiagnostic.js +7 -8
- package/dist/hopper/LinuxPrivateDisplayProbe.js +6 -2
- package/dist/hopper/protocol.js +8 -8
- package/dist/ida/IdaConfiguration.js +56 -0
- package/dist/ida/IdaDoctor.js +53 -0
- package/dist/ida/IdaInput.js +62 -0
- package/dist/ida/IdaMcpConnection.js +111 -0
- package/dist/ida/IdaOperationRunner.js +299 -0
- package/dist/ida/IdaProtocolValues.js +178 -0
- package/dist/ida/IdaProvider.js +126 -0
- package/dist/ida/IdaProviderCapabilities.js +60 -0
- package/dist/ida/IdaSessionClient.js +306 -0
- package/dist/ida/IdaWorkspace.js +54 -0
- package/dist/main/shutdown.js +21 -1
- package/dist/main/startup.js +1 -1
- package/dist/main/transport.js +8 -4
- package/dist/main.js +5 -2
- package/dist/native/AppleDispatchMetadata.js +31 -10
- package/dist/native/NativeMacOSProvider.js +87 -15
- package/dist/native/NativeMachoInspection.js +42 -12
- package/dist/native/NativeUiHelperRuntime.js +7 -1
- package/dist/native/NativeUiObservation.js +6 -2
- package/dist/native/parsers/demangle.js +1 -1
- package/dist/native/parsers/dyldInfo.js +3 -3
- package/dist/native/parsers/otool.js +4 -1
- package/dist/native/parsers/plist.js +11 -3
- package/dist/process/PrivateRuntimeRoot.js +13 -3
- package/dist/process/ProcessOwnership.js +5 -73
- package/dist/process/ProcessOwnershipObservation.js +62 -2
- package/dist/process/ProcessOwnershipProcessTree.js +13 -0
- package/dist/process/ProviderProcess.js +24 -7
- package/dist/process/ProviderRunLineage.js +1 -1
- package/dist/process/WindowsAuthority.js +20 -1
- package/dist/reference/ReferenceSourceReaderEntries.js +5 -1
- package/dist/reference/ReferenceSourceReaderFile.js +1 -0
- package/dist/server/createServer.js +25 -2
- package/dist/server/mcpProgress.js +2 -1
- package/dist/server/promptCompletion.js +3 -3
- package/dist/server/registerAndroidTools.js +30 -0
- package/dist/server/registerApplicationTools/compareExportShapes.js +5 -1
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +7 -2
- package/dist/server/registerApplicationTools/compareVersions.js +5 -1
- package/dist/server/registerApplicationTools/traceFeature.js +7 -2
- package/dist/server/registerApplicationTools/traceSemantics.js +7 -2
- package/dist/server/registerEnhancedTools.js +28 -1
- package/dist/server/registerFirmwareTools.js +22 -0
- package/dist/server/registerFunctionComparisonTool.js +1 -1
- package/dist/server/registerInvestigationTools/helpers.js +2 -1
- package/dist/server/registerManagedTools.js +1 -1
- package/dist/server/registerManagedWorkflowTools/evidence.js +1 -1
- package/dist/server/registerOfficialTools.js +4 -1
- package/dist/server/registerProcessComparisonTool.js +5 -2
- package/dist/server/registerSessionTools.js +3 -1
- package/dist/server/runDerivedOperation.js +1 -1
- package/dist/server/sessionAvailabilityPolicy.js +3 -0
- package/dist/server/sessionEvidence.js +1 -1
- package/dist/server/toolResult.js +2 -1
- package/dist/windows/WindowsNativeLoader.js +108 -0
- package/dist/windows/WindowsOwnedProcess.js +168 -0
- package/dist/windows/WindowsPrivateRuntime.js +137 -0
- package/install.sh +4 -6
- package/native/windows/README.md +102 -0
- package/native/windows/build/manifest.json +9 -0
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +38 -24
- package/scripts/rea.mjs +1 -1
- package/scripts/verify-windows-native-artifact.mjs +39 -0
- package/skills/reverse-engineer-anything/SKILL.md +92 -24
- package/skills/reverse-engineer-anything/references/android-applications.md +31 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +19 -2
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +52 -4
- package/dist/browser/CdpCanonicalJsonDigest.js +0 -9
- package/dist/domain/errors.js +0 -324
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
3
|
+
import { AnalysisProtocolError } from "../domain/analysisErrorCore.js";
|
|
4
|
+
/** Normalize an IDA hexadecimal coordinate without passing through a JavaScript number. */
|
|
5
|
+
export const idaAddressSchema = z
|
|
6
|
+
.string()
|
|
7
|
+
.regex(/^(?:0x)?[0-9a-f]+$/iu)
|
|
8
|
+
.transform((value) => `0x${BigInt(value.startsWith("0x") || value.startsWith("0X") ? value : `0x${value}`).toString(16)}`);
|
|
9
|
+
/** A function observation; size is an enclosing span, never a complete body. */
|
|
10
|
+
export const idaFunctionSchema = z.union([
|
|
11
|
+
z.object({
|
|
12
|
+
address: idaAddressSchema,
|
|
13
|
+
name: z.string().min(1),
|
|
14
|
+
size: z.string(),
|
|
15
|
+
}),
|
|
16
|
+
z
|
|
17
|
+
.object({
|
|
18
|
+
addr: idaAddressSchema,
|
|
19
|
+
name: z.string().min(1),
|
|
20
|
+
size: z.string(),
|
|
21
|
+
})
|
|
22
|
+
.transform(({ addr, ...rest }) => ({ address: addr, ...rest })),
|
|
23
|
+
]);
|
|
24
|
+
/** Legacy metadata describes the recorded input, whereas modern health names live paths. */
|
|
25
|
+
export const legacyMetadataSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
path: z.string().min(1),
|
|
28
|
+
module: z.string(),
|
|
29
|
+
sha256: z.string().regex(/^[0-9a-f]{64}$/iu),
|
|
30
|
+
base: idaAddressSchema,
|
|
31
|
+
})
|
|
32
|
+
.passthrough();
|
|
33
|
+
export const modernHealthSchema = z
|
|
34
|
+
.object({
|
|
35
|
+
status: z.literal("ok"),
|
|
36
|
+
input_path: z.string().min(1),
|
|
37
|
+
idb_path: z.string().nullable(),
|
|
38
|
+
imagebase: idaAddressSchema,
|
|
39
|
+
auto_analysis_ready: z.boolean().nullable(),
|
|
40
|
+
module: z.string(),
|
|
41
|
+
})
|
|
42
|
+
.passthrough();
|
|
43
|
+
/** An upstream cursor must either finish or advance strictly to avoid replay loops. */
|
|
44
|
+
export const cursorSchema = z.union([
|
|
45
|
+
z.object({ next: z.number().int().nonnegative() }),
|
|
46
|
+
z.object({ done: z.literal(true) }),
|
|
47
|
+
]);
|
|
48
|
+
export const nextOffset = (cursor, current) => {
|
|
49
|
+
if ("done" in cursor)
|
|
50
|
+
return null;
|
|
51
|
+
if (cursor.next <= current)
|
|
52
|
+
throw new AnalysisProtocolError("IDA MCP pagination did not advance its offset.");
|
|
53
|
+
return cursor.next;
|
|
54
|
+
};
|
|
55
|
+
export const legacyPageSchema = z.object({
|
|
56
|
+
data: z.array(jsonValueSchema),
|
|
57
|
+
next_offset: z.number().int().nonnegative().nullable(),
|
|
58
|
+
});
|
|
59
|
+
export const modernPageSchema = z
|
|
60
|
+
.array(z.object({
|
|
61
|
+
data: z.array(jsonValueSchema),
|
|
62
|
+
next_offset: z.number().int().nonnegative().nullable(),
|
|
63
|
+
}))
|
|
64
|
+
.length(1);
|
|
65
|
+
export const modernLookupSchema = z
|
|
66
|
+
.array(z.object({
|
|
67
|
+
query: z.string(),
|
|
68
|
+
fn: idaFunctionSchema.nullable(),
|
|
69
|
+
error: z.string().nullable(),
|
|
70
|
+
}))
|
|
71
|
+
.length(1);
|
|
72
|
+
const instructionSchema = z.union([
|
|
73
|
+
z.object({
|
|
74
|
+
address: idaAddressSchema,
|
|
75
|
+
instruction: z.string(),
|
|
76
|
+
comments: z.array(z.string()).nullish(),
|
|
77
|
+
}),
|
|
78
|
+
z
|
|
79
|
+
.object({
|
|
80
|
+
addr: idaAddressSchema,
|
|
81
|
+
instruction: z.string(),
|
|
82
|
+
comments: z.array(z.string()).nullish(),
|
|
83
|
+
})
|
|
84
|
+
.transform(({ addr, ...rest }) => ({ address: addr, ...rest })),
|
|
85
|
+
]);
|
|
86
|
+
export const disassemblySchema = z.object({
|
|
87
|
+
name: z.string(),
|
|
88
|
+
start_ea: idaAddressSchema,
|
|
89
|
+
lines: z.array(instructionSchema),
|
|
90
|
+
return_type: z.string().nullish(),
|
|
91
|
+
arguments: z
|
|
92
|
+
.array(z.object({ name: z.string(), type: z.string() }))
|
|
93
|
+
.nullish(),
|
|
94
|
+
});
|
|
95
|
+
export const modernDisassemblySchema = z.object({
|
|
96
|
+
asm: disassemblySchema.nullable(),
|
|
97
|
+
error: z.string().optional(),
|
|
98
|
+
cursor: cursorSchema,
|
|
99
|
+
});
|
|
100
|
+
export const modernDecompileSchema = z.object({
|
|
101
|
+
code: z.string().nullable(),
|
|
102
|
+
error: z.string().optional(),
|
|
103
|
+
cursor: cursorSchema,
|
|
104
|
+
line_count: z.number().int().nonnegative().optional(),
|
|
105
|
+
total_lines: z.number().int().nonnegative().optional(),
|
|
106
|
+
});
|
|
107
|
+
export const legacyStringSchema = z.object({
|
|
108
|
+
address: idaAddressSchema,
|
|
109
|
+
string: z.string(),
|
|
110
|
+
length: z.number().int().nonnegative(),
|
|
111
|
+
});
|
|
112
|
+
export const modernStringsSchema = z.object({
|
|
113
|
+
matches: z.array(z.object({ addr: idaAddressSchema, string: z.string() })),
|
|
114
|
+
cursor: cursorSchema,
|
|
115
|
+
});
|
|
116
|
+
export const legacyXrefsSchema = z.array(z.object({
|
|
117
|
+
address: idaAddressSchema,
|
|
118
|
+
type: z.string(),
|
|
119
|
+
function: idaFunctionSchema.nullable(),
|
|
120
|
+
}));
|
|
121
|
+
export const modernXrefsSchema = z
|
|
122
|
+
.array(z.object({
|
|
123
|
+
xrefs: z
|
|
124
|
+
.array(z.object({
|
|
125
|
+
addr: idaAddressSchema,
|
|
126
|
+
type: z.string(),
|
|
127
|
+
fn: idaFunctionSchema.nullable(),
|
|
128
|
+
}))
|
|
129
|
+
.nullable(),
|
|
130
|
+
error: z.string().optional(),
|
|
131
|
+
more: z.boolean().optional(),
|
|
132
|
+
}))
|
|
133
|
+
.length(1);
|
|
134
|
+
export const modernCalleesSchema = z
|
|
135
|
+
.array(z.object({
|
|
136
|
+
callees: z
|
|
137
|
+
.array(z.object({
|
|
138
|
+
addr: idaAddressSchema,
|
|
139
|
+
name: z.string(),
|
|
140
|
+
type: z.enum(["internal", "external"]),
|
|
141
|
+
}))
|
|
142
|
+
.nullable(),
|
|
143
|
+
error: z.string().optional(),
|
|
144
|
+
more: z.boolean().optional(),
|
|
145
|
+
}))
|
|
146
|
+
.length(1);
|
|
147
|
+
export const legacyCalleesSchema = z.array(z.object({ address: idaAddressSchema, name: z.string() }).passthrough());
|
|
148
|
+
/** Parsed database lifecycle observations retain explicit ownership information. */
|
|
149
|
+
export const openDatabaseSchema = z
|
|
150
|
+
.object({
|
|
151
|
+
success: z.literal(true),
|
|
152
|
+
session: z
|
|
153
|
+
.object({ session_id: z.string().min(1), input_path: z.string().min(1) })
|
|
154
|
+
.passthrough(),
|
|
155
|
+
})
|
|
156
|
+
.passthrough();
|
|
157
|
+
export const databaseListSchema = z
|
|
158
|
+
.object({
|
|
159
|
+
sessions: z.array(z
|
|
160
|
+
.object({
|
|
161
|
+
session_id: z.string(),
|
|
162
|
+
input_path: z.string(),
|
|
163
|
+
owned: z.boolean(),
|
|
164
|
+
backend: z.enum(["worker", "gui"]),
|
|
165
|
+
is_active: z.boolean(),
|
|
166
|
+
})
|
|
167
|
+
.passthrough()),
|
|
168
|
+
})
|
|
169
|
+
.passthrough();
|
|
170
|
+
export const closeDatabaseSchema = z
|
|
171
|
+
.object({
|
|
172
|
+
success: z.literal(true),
|
|
173
|
+
session_id: z.string(),
|
|
174
|
+
saved: z.boolean().nullable().optional(),
|
|
175
|
+
owned: z.boolean(),
|
|
176
|
+
backend: z.enum(["worker", "gui"]),
|
|
177
|
+
})
|
|
178
|
+
.passthrough();
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { createAnalysisProfile } from "../domain/analysisProfile.js";
|
|
2
|
+
import { err, ok } from "../domain/result.js";
|
|
3
|
+
import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
|
|
4
|
+
import { ConfigurationError } from "../domain/configurationErrors.js";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import canonicalize from "canonicalize";
|
|
7
|
+
import { readIdaConfiguration, } from "./IdaConfiguration.js";
|
|
8
|
+
import { createIdaMcpConnection, } from "./IdaMcpConnection.js";
|
|
9
|
+
import { idaCapabilities, IDA_PROVIDER_IDENTITY, } from "./IdaProviderCapabilities.js";
|
|
10
|
+
import { IdaSessionClient } from "./IdaSessionClient.js";
|
|
11
|
+
import { privateRuntimeRootCapability } from "../process/PrivateRuntimeRoot.js";
|
|
12
|
+
export { IDA_PROVIDER_IDENTITY } from "./IdaProviderCapabilities.js";
|
|
13
|
+
/** Bring-your-own IDA MCP candidate; discovery performs no provider startup. */
|
|
14
|
+
export class IdaProvider {
|
|
15
|
+
config;
|
|
16
|
+
connectionFactory;
|
|
17
|
+
#registration;
|
|
18
|
+
constructor(config, connectionFactory = createIdaMcpConnection) {
|
|
19
|
+
this.config = config;
|
|
20
|
+
this.connectionFactory = connectionFactory;
|
|
21
|
+
}
|
|
22
|
+
identity() {
|
|
23
|
+
return IDA_PROVIDER_IDENTITY;
|
|
24
|
+
}
|
|
25
|
+
capabilities() {
|
|
26
|
+
const config = this.#configuration();
|
|
27
|
+
return idaCapabilities(config.ok ? config.value.mode : "attached", config.ok && "command" in config.value);
|
|
28
|
+
}
|
|
29
|
+
inspectAvailability() {
|
|
30
|
+
const config = this.#configuration();
|
|
31
|
+
if (config.ok && config.value.mode === "headless") {
|
|
32
|
+
const privacy = privateRuntimeRootCapability();
|
|
33
|
+
if (!privacy.available)
|
|
34
|
+
return {
|
|
35
|
+
status: "unavailable",
|
|
36
|
+
code: "unsupported_host",
|
|
37
|
+
reason: privacy.reason,
|
|
38
|
+
diagnostics: {
|
|
39
|
+
configured: true,
|
|
40
|
+
mode: "headless",
|
|
41
|
+
live_connection_probed: false,
|
|
42
|
+
private_workspace_available: false,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return config.ok
|
|
47
|
+
? {
|
|
48
|
+
status: "available",
|
|
49
|
+
code: null,
|
|
50
|
+
reason: null,
|
|
51
|
+
diagnostics: {
|
|
52
|
+
configured: true,
|
|
53
|
+
mode: config.value.mode,
|
|
54
|
+
transport: "command" in config.value ? "stdio" : "http",
|
|
55
|
+
live_connection_probed: false,
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
: {
|
|
59
|
+
status: "unavailable",
|
|
60
|
+
code: this.config.idaMcpConfigPath === undefined
|
|
61
|
+
? "not_configured"
|
|
62
|
+
: "open_options_invalid",
|
|
63
|
+
reason: config.error.message,
|
|
64
|
+
diagnostics: { configured: false, live_connection_probed: false },
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
inspectTargetSupport(target) {
|
|
68
|
+
const diagnostics = {
|
|
69
|
+
target_kind: target.kind,
|
|
70
|
+
target_format: target.format,
|
|
71
|
+
};
|
|
72
|
+
return target.kind === "executable"
|
|
73
|
+
? { status: "supported", code: null, reason: null, diagnostics }
|
|
74
|
+
: {
|
|
75
|
+
status: "unsupported",
|
|
76
|
+
code: "target_kind_unsupported",
|
|
77
|
+
reason: "IDA MCP integration admits executable inputs, not analysis databases. Select the original input binary.",
|
|
78
|
+
diagnostics,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async resolveAnalysisProfile(_target, options) {
|
|
82
|
+
if (options?.signal?.aborted === true)
|
|
83
|
+
return err(new AnalysisCancelledError("ida:profile"));
|
|
84
|
+
const config = this.#configuration();
|
|
85
|
+
if (!config.ok)
|
|
86
|
+
return config;
|
|
87
|
+
return ok({
|
|
88
|
+
profile: createAnalysisProfile(IDA_PROVIDER_IDENTITY, {
|
|
89
|
+
version_scope: "rea-ida-adapter",
|
|
90
|
+
engine_version: null,
|
|
91
|
+
upstream_distribution_version: null,
|
|
92
|
+
mode: config.value.mode,
|
|
93
|
+
compatibility_profile: config.value.mode === "attached"
|
|
94
|
+
? "legacy-1.4"
|
|
95
|
+
: "database-supervisor",
|
|
96
|
+
database_revision: null,
|
|
97
|
+
cache_policy: "live",
|
|
98
|
+
registration_digest: createHash("sha256")
|
|
99
|
+
.update(canonicalize(config.value) ?? "")
|
|
100
|
+
.digest("hex"),
|
|
101
|
+
}),
|
|
102
|
+
compatibility: {
|
|
103
|
+
mode: config.value.mode,
|
|
104
|
+
engine_version: null,
|
|
105
|
+
upstream_distribution_version: null,
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
createClient(target, profile) {
|
|
110
|
+
const config = this.#configuration();
|
|
111
|
+
if (!config.ok)
|
|
112
|
+
return {
|
|
113
|
+
execute: async () => err(config.error),
|
|
114
|
+
close: async () => undefined,
|
|
115
|
+
};
|
|
116
|
+
return new IdaSessionClient(config.value, target, this.connectionFactory(config.value), profile);
|
|
117
|
+
}
|
|
118
|
+
#configuration() {
|
|
119
|
+
this.#registration ??=
|
|
120
|
+
this.config.idaMcpConfigPath === undefined
|
|
121
|
+
? readIdaConfigurationNotConfigured()
|
|
122
|
+
: readIdaConfiguration(this.config.idaMcpConfigPath);
|
|
123
|
+
return this.#registration;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const readIdaConfigurationNotConfigured = () => err(new ConfigurationError("Set REA_IDA_MCP_CONFIG to an upstream IDA MCP JSON registration; see docs/ida-provider.md."));
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { GENERATED_MCP_TOOL_CATALOG } from "../generatedMcpToolCatalog.js";
|
|
2
|
+
/** This version identifies REA's adapter, not IDA or the upstream Python package. */
|
|
3
|
+
export const IDA_PROVIDER_IDENTITY = Object.freeze({
|
|
4
|
+
id: "ida",
|
|
5
|
+
name: "IDA Pro MCP adapter",
|
|
6
|
+
version: "1",
|
|
7
|
+
});
|
|
8
|
+
/** Read-only analyst outcomes supported by both upstream compatibility profiles. */
|
|
9
|
+
export const IDA_OPERATIONS = [
|
|
10
|
+
"list_procedures",
|
|
11
|
+
"search_procedures",
|
|
12
|
+
"list_strings",
|
|
13
|
+
"search_strings",
|
|
14
|
+
"procedure_address",
|
|
15
|
+
"procedure_pseudo_code",
|
|
16
|
+
"procedure_assembly",
|
|
17
|
+
"procedure_callers",
|
|
18
|
+
"procedure_callees",
|
|
19
|
+
"read_function_instructions",
|
|
20
|
+
"xrefs",
|
|
21
|
+
"analyze_function",
|
|
22
|
+
];
|
|
23
|
+
/** Shared limitations of observations from an externally mutable analysis database. */
|
|
24
|
+
export const IDA_LIMITATIONS = Object.freeze([
|
|
25
|
+
"Provider version identifies the REA IDA adapter. IDA engine and upstream distribution versions are unknown unless separately observed; MCP serverInfo is reported independently.",
|
|
26
|
+
"Results describe the current IDA analysis database. Input identity does not prove an unmodified database; patches, annotations, analysis completeness, and database revision remain unknown.",
|
|
27
|
+
"Live results are never replayed from analysis snapshots. Target checks before and after a request do not provide an atomic lock against external GUI changes.",
|
|
28
|
+
"Caller cancellation drains the in-flight MCP request before cleanup; it does not prove that IDA engine work was interrupted.",
|
|
29
|
+
"Headless workers are released through the upstream database lifecycle. Abrupt termination of REA, its proxy, or the supervisor cannot prove worker cleanup; inspect upstream inventory after an interrupted process.",
|
|
30
|
+
"Complete function body ranges, typed references, unresolved indirect calls, referenced data, and basic blocks are unavailable in this adapter. Empty unsupported dossier facets are unknown, not observed absence.",
|
|
31
|
+
]);
|
|
32
|
+
/** Existing REA contracts implemented by the adapter; no upstream tools are exposed directly. */
|
|
33
|
+
export const IDA_PROVIDER_TOOL_CONTRACTS = Object.freeze(IDA_OPERATIONS.map((operation) => {
|
|
34
|
+
const contract = GENERATED_MCP_TOOL_CATALOG.find(({ name }) => name === operation);
|
|
35
|
+
if (contract === undefined)
|
|
36
|
+
throw new TypeError(`Missing contract for ${operation}`);
|
|
37
|
+
return { ...contract, name: operation };
|
|
38
|
+
}));
|
|
39
|
+
/** Advertise live observations and configured lifecycle effects truthfully. */
|
|
40
|
+
export const idaCapabilities = (mode, stdio) => IDA_PROVIDER_TOOL_CONTRACTS.map(({ name: operation }) => ({
|
|
41
|
+
provider: IDA_PROVIDER_IDENTITY,
|
|
42
|
+
operation,
|
|
43
|
+
...(mode === "headless" && operation === "procedure_callers"
|
|
44
|
+
? {
|
|
45
|
+
available: false,
|
|
46
|
+
reason: "The modern upstream profile reports code references without proving direct call edges.",
|
|
47
|
+
}
|
|
48
|
+
: { available: true, reason: null }),
|
|
49
|
+
cachePolicy: "live",
|
|
50
|
+
effects: {
|
|
51
|
+
mutatesArtifact: false,
|
|
52
|
+
launchesProcess: stdio || mode === "headless",
|
|
53
|
+
mayShowUi: false,
|
|
54
|
+
mayAccessNetwork: true,
|
|
55
|
+
mayWriteFilesystem: stdio || mode === "headless",
|
|
56
|
+
changesPermissions: false,
|
|
57
|
+
requiresRoot: false,
|
|
58
|
+
},
|
|
59
|
+
limitations: IDA_LIMITATIONS,
|
|
60
|
+
}));
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { createAnalysisExecution, } from "../application/AnalysisProvider.js";
|
|
3
|
+
import { AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisProtocolError, AnalysisOutputError, AnalysisInputError, } from "../domain/analysisErrorCore.js";
|
|
4
|
+
import { AnalysisError } from "../domain/analysisErrorBase.js";
|
|
5
|
+
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
|
|
6
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
7
|
+
import { err, ok } from "../domain/result.js";
|
|
8
|
+
import { IdaOperationRunner } from "./IdaOperationRunner.js";
|
|
9
|
+
import { IDA_LIMITATIONS, IDA_OPERATIONS, IDA_PROVIDER_IDENTITY, } from "./IdaProviderCapabilities.js";
|
|
10
|
+
import { closeDatabaseSchema, databaseListSchema, legacyMetadataSchema, modernHealthSchema, openDatabaseSchema, } from "./IdaProtocolValues.js";
|
|
11
|
+
import { idaFileDigest, IdaWorkspace, sameIdaHostPath, } from "./IdaWorkspace.js";
|
|
12
|
+
import { parseIdaInput } from "./IdaInput.js";
|
|
13
|
+
const legacyTools = [
|
|
14
|
+
"get_metadata",
|
|
15
|
+
"list_functions",
|
|
16
|
+
"list_strings",
|
|
17
|
+
"get_function_by_name",
|
|
18
|
+
"get_function_by_address",
|
|
19
|
+
"decompile_function",
|
|
20
|
+
"disassemble_function",
|
|
21
|
+
"get_callers",
|
|
22
|
+
"get_callees",
|
|
23
|
+
"get_xrefs_to",
|
|
24
|
+
];
|
|
25
|
+
const modernTools = [
|
|
26
|
+
"idb_open",
|
|
27
|
+
"idb_list",
|
|
28
|
+
"idb_close",
|
|
29
|
+
"server_health",
|
|
30
|
+
"list_funcs",
|
|
31
|
+
"lookup_funcs",
|
|
32
|
+
"find_regex",
|
|
33
|
+
"decompile",
|
|
34
|
+
"disasm",
|
|
35
|
+
"callees",
|
|
36
|
+
"xrefs_to",
|
|
37
|
+
];
|
|
38
|
+
const operationSet = new Set(IDA_OPERATIONS);
|
|
39
|
+
const isIdaOperation = (operation) => operationSet.has(operation);
|
|
40
|
+
const wasCancelled = (options) => options?.signal?.aborted === true;
|
|
41
|
+
/** A failed cleanup retains its private workspace and reports the remaining resource. */
|
|
42
|
+
class IdaCleanupError extends ProviderAdapterError {
|
|
43
|
+
cleanupIncomplete = true;
|
|
44
|
+
cleanupResources;
|
|
45
|
+
constructor(path, cause) {
|
|
46
|
+
super("ida", "close", {
|
|
47
|
+
cause,
|
|
48
|
+
diagnostics: {
|
|
49
|
+
reason: "IDA worker release could not be verified. The private workspace was retained.",
|
|
50
|
+
workspace: path,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
this.cleanupResources = [path];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Serial read-only session whose lifecycle authority excludes an attached GUI. */
|
|
57
|
+
export class IdaSessionClient {
|
|
58
|
+
config;
|
|
59
|
+
target;
|
|
60
|
+
connection;
|
|
61
|
+
profile;
|
|
62
|
+
#tail = Promise.resolve();
|
|
63
|
+
#startup;
|
|
64
|
+
#closed = false;
|
|
65
|
+
#closing = false;
|
|
66
|
+
#workspace;
|
|
67
|
+
#database;
|
|
68
|
+
#openAttempted = false;
|
|
69
|
+
#openCompleted = false;
|
|
70
|
+
#initialIdentity;
|
|
71
|
+
#metadata = null;
|
|
72
|
+
#lifecycle = [];
|
|
73
|
+
constructor(config, target, connection, profile) {
|
|
74
|
+
this.config = config;
|
|
75
|
+
this.target = target;
|
|
76
|
+
this.connection = connection;
|
|
77
|
+
this.profile = profile;
|
|
78
|
+
}
|
|
79
|
+
execute(operation, parameters, options) {
|
|
80
|
+
const call = this.#tail.then(() => this.#execute(operation, parameters, options));
|
|
81
|
+
this.#tail = call.then(() => undefined, () => undefined);
|
|
82
|
+
return call;
|
|
83
|
+
}
|
|
84
|
+
async #execute(operation, parameters, options) {
|
|
85
|
+
if (this.#closed || this.#closing)
|
|
86
|
+
return err(new AnalysisProtocolError("IDA session is closing or closed; reopen the target."));
|
|
87
|
+
if (wasCancelled(options))
|
|
88
|
+
return err(new AnalysisCancelledError(operation));
|
|
89
|
+
if (operation !== "health" && !isIdaOperation(operation))
|
|
90
|
+
return err(new AnalysisCapabilityUnavailableError("ida", operation, "This integration admits read-only analysis operations only."));
|
|
91
|
+
if (operation === "procedure_callers" && this.config.mode === "headless")
|
|
92
|
+
return err(new AnalysisCapabilityUnavailableError("ida", operation, "The modern upstream profile does not prove direct callers."));
|
|
93
|
+
if (operation !== "health") {
|
|
94
|
+
const parsed = parseIdaInput(operation, parameters);
|
|
95
|
+
if (!parsed.ok)
|
|
96
|
+
return parsed;
|
|
97
|
+
parameters = parsed.value;
|
|
98
|
+
}
|
|
99
|
+
const document = parameters.document;
|
|
100
|
+
if (document !== undefined &&
|
|
101
|
+
document !== this.target.path &&
|
|
102
|
+
document !== this.target.sourcePath)
|
|
103
|
+
return err(new AnalysisInputError(operation, undefined, [
|
|
104
|
+
{
|
|
105
|
+
path: ["document"],
|
|
106
|
+
reason: "invalid_value",
|
|
107
|
+
expected: this.target.path,
|
|
108
|
+
message: "IDA document must be the REA-bound target; omit document or use its admitted path.",
|
|
109
|
+
},
|
|
110
|
+
]));
|
|
111
|
+
try {
|
|
112
|
+
await this.#start();
|
|
113
|
+
const before = await this.#observe();
|
|
114
|
+
if (wasCancelled(options))
|
|
115
|
+
return err(new AnalysisCancelledError(operation));
|
|
116
|
+
if (operation === "health")
|
|
117
|
+
return this.#health(before);
|
|
118
|
+
if (!isIdaOperation(operation))
|
|
119
|
+
throw new AnalysisProtocolError("IDA operation changed after validation.");
|
|
120
|
+
const runner = new IdaOperationRunner(this.connection, this.config.mode === "attached" ? "legacy" : "modern", this.#database);
|
|
121
|
+
const result = await runner.run(operation, parameters);
|
|
122
|
+
const after = await this.#observe();
|
|
123
|
+
if (wasCancelled(options))
|
|
124
|
+
return err(new AnalysisCancelledError(operation));
|
|
125
|
+
return ok(createAnalysisExecution(result, IDA_PROVIDER_IDENTITY, {
|
|
126
|
+
rawResult: {
|
|
127
|
+
upstream: this.connection.serverInfo(),
|
|
128
|
+
metadata_before: before,
|
|
129
|
+
metadata_after: after,
|
|
130
|
+
observations: jsonValueSchema.parse(runner.raw),
|
|
131
|
+
},
|
|
132
|
+
limitations: [...IDA_LIMITATIONS, ...runner.limitations],
|
|
133
|
+
locations: [
|
|
134
|
+
{ kind: "artifact-path", path: this.target.path },
|
|
135
|
+
...runner.locations,
|
|
136
|
+
],
|
|
137
|
+
...(this.profile === undefined
|
|
138
|
+
? {}
|
|
139
|
+
: { analysisProfile: this.profile }),
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
catch (cause) {
|
|
143
|
+
return this.#failure(operation, cause, options);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
#health(metadata) {
|
|
147
|
+
return ok(createAnalysisExecution({
|
|
148
|
+
ready: true,
|
|
149
|
+
mode: this.config.mode,
|
|
150
|
+
database: this.#database ?? null,
|
|
151
|
+
upstream: this.connection.serverInfo(),
|
|
152
|
+
metadata,
|
|
153
|
+
lifecycle: this.#lifecycle,
|
|
154
|
+
}, IDA_PROVIDER_IDENTITY, {
|
|
155
|
+
limitations: IDA_LIMITATIONS,
|
|
156
|
+
...(this.profile === undefined
|
|
157
|
+
? {}
|
|
158
|
+
: { analysisProfile: this.profile }),
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
#failure(operation, cause, options) {
|
|
162
|
+
if (wasCancelled(options))
|
|
163
|
+
return err(new AnalysisCancelledError(operation));
|
|
164
|
+
if (cause instanceof AnalysisError)
|
|
165
|
+
return err(cause);
|
|
166
|
+
if (cause instanceof z.ZodError)
|
|
167
|
+
return err(new AnalysisOutputError(operation, `IDA MCP returned malformed or unsupported producer data: ${cause.issues.map((issue) => `${issue.path.join(".") || "$"}: ${issue.message}`).join("; ")}`, { cause }));
|
|
168
|
+
return err(new ProviderAdapterError("ida", operation, {
|
|
169
|
+
cause,
|
|
170
|
+
diagnostics: {
|
|
171
|
+
reason: cause instanceof Error ? cause.message : "Unknown upstream failure",
|
|
172
|
+
recovery: "Check the configured upstream MCP registration and selected target; see docs/ida-provider.md.",
|
|
173
|
+
},
|
|
174
|
+
}));
|
|
175
|
+
}
|
|
176
|
+
#start() {
|
|
177
|
+
this.#startup ??= this.#initialize();
|
|
178
|
+
return this.#startup;
|
|
179
|
+
}
|
|
180
|
+
async #initialize() {
|
|
181
|
+
const tools = new Set(await this.connection.connect());
|
|
182
|
+
const expected = this.config.mode === "attached" ? legacyTools : modernTools;
|
|
183
|
+
const missing = expected.filter((name) => !tools.has(name));
|
|
184
|
+
if (missing.length > 0)
|
|
185
|
+
throw new AnalysisProtocolError(`IDA MCP ${this.config.mode} compatibility profile is missing tools: ${missing.join(", ")}. Attached mode requires the legacy 1.4 profile; headless mode requires the database supervisor profile. See docs/ida-provider.md.`);
|
|
186
|
+
if (this.config.mode === "headless") {
|
|
187
|
+
this.#workspace = await IdaWorkspace.create(this.target, this.config.workspaceRoot);
|
|
188
|
+
this.#openAttempted = true;
|
|
189
|
+
const raw = await this.connection.call("idb_open", {
|
|
190
|
+
input_path: this.#workspace.inputPath,
|
|
191
|
+
mode: "force_headless",
|
|
192
|
+
run_auto_analysis: true,
|
|
193
|
+
build_caches: true,
|
|
194
|
+
init_hexrays: true,
|
|
195
|
+
preferred_session_id: this.#workspace.sessionId,
|
|
196
|
+
});
|
|
197
|
+
this.#openCompleted = true;
|
|
198
|
+
this.#lifecycle.push(raw);
|
|
199
|
+
const opened = openDatabaseSchema.parse(raw);
|
|
200
|
+
if (!sameIdaHostPath(opened.session.input_path, this.#workspace.inputPath))
|
|
201
|
+
throw new AnalysisProtocolError("IDA opened a different input than the private admitted target copy.");
|
|
202
|
+
if (opened.session.session_id !== this.#workspace.sessionId)
|
|
203
|
+
throw new AnalysisProtocolError("IDA returned an adopted or unexpected session instead of the requested private worker.");
|
|
204
|
+
const inventory = databaseListSchema.parse(await this.connection.call("idb_list", {}));
|
|
205
|
+
this.#lifecycle.push(jsonValueSchema.parse(inventory));
|
|
206
|
+
const entry = inventory.sessions.find(({ session_id }) => session_id === opened.session.session_id);
|
|
207
|
+
if (entry?.owned !== true ||
|
|
208
|
+
entry.backend !== "worker" ||
|
|
209
|
+
entry.is_active !== true ||
|
|
210
|
+
!sameIdaHostPath(entry.input_path, this.#workspace.inputPath))
|
|
211
|
+
throw new AnalysisProtocolError("IDA did not return an active owned headless worker for the private input copy.");
|
|
212
|
+
this.#database = opened.session.session_id;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async #observe() {
|
|
216
|
+
let identity;
|
|
217
|
+
if (this.config.mode === "attached") {
|
|
218
|
+
const raw = await this.connection.call("get_metadata", {});
|
|
219
|
+
const metadata = legacyMetadataSchema.parse(raw);
|
|
220
|
+
if (metadata.sha256.toLowerCase() !== this.target.sha256.toLowerCase())
|
|
221
|
+
throw new AnalysisProtocolError(`The attached IDA input SHA-256 does not match the selected target ${this.target.path}; open that target in IDA or use headless mode.`);
|
|
222
|
+
identity = JSON.stringify([
|
|
223
|
+
metadata.path,
|
|
224
|
+
metadata.sha256.toLowerCase(),
|
|
225
|
+
metadata.base,
|
|
226
|
+
]);
|
|
227
|
+
this.#metadata = raw;
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
if (this.#database === undefined || this.#workspace === undefined)
|
|
231
|
+
throw new AnalysisProtocolError("IDA headless session has no database binding.");
|
|
232
|
+
const raw = await this.connection.call("server_health", {
|
|
233
|
+
database: this.#database,
|
|
234
|
+
});
|
|
235
|
+
const metadata = modernHealthSchema.parse(raw);
|
|
236
|
+
if (!sameIdaHostPath(metadata.input_path, this.#workspace.inputPath) ||
|
|
237
|
+
(await idaFileDigest(this.#workspace.inputPath)) !== this.target.sha256)
|
|
238
|
+
throw new AnalysisProtocolError("IDA headless input identity changed after target admission.");
|
|
239
|
+
if (metadata.auto_analysis_ready !== true)
|
|
240
|
+
throw new AnalysisProtocolError("IDA auto-analysis is incomplete or readiness is unknown; retry after analysis completes.");
|
|
241
|
+
identity = JSON.stringify([
|
|
242
|
+
this.#database,
|
|
243
|
+
metadata.input_path,
|
|
244
|
+
metadata.idb_path,
|
|
245
|
+
metadata.imagebase,
|
|
246
|
+
]);
|
|
247
|
+
this.#metadata = raw;
|
|
248
|
+
}
|
|
249
|
+
if (this.#initialIdentity !== undefined &&
|
|
250
|
+
identity !== this.#initialIdentity)
|
|
251
|
+
throw new AnalysisProtocolError("The attached IDA target or image base changed during the REA session; reopen the target.");
|
|
252
|
+
this.#initialIdentity = identity;
|
|
253
|
+
return this.#metadata;
|
|
254
|
+
}
|
|
255
|
+
async closeWithOutcome() {
|
|
256
|
+
this.#closing = true;
|
|
257
|
+
await this.#tail;
|
|
258
|
+
if (this.#closed)
|
|
259
|
+
return ok(null);
|
|
260
|
+
try {
|
|
261
|
+
if (this.#workspace !== undefined && this.#openAttempted) {
|
|
262
|
+
if (this.#database === undefined) {
|
|
263
|
+
const inventory = databaseListSchema.parse(await this.connection.call("idb_list", {}));
|
|
264
|
+
const workspace = this.#workspace;
|
|
265
|
+
this.#database = inventory.sessions.find((entry) => entry.owned &&
|
|
266
|
+
entry.backend === "worker" &&
|
|
267
|
+
entry.session_id === workspace.sessionId &&
|
|
268
|
+
sameIdaHostPath(entry.input_path, workspace.inputPath))?.session_id;
|
|
269
|
+
if (this.#database === undefined &&
|
|
270
|
+
inventory.sessions.some((entry) => sameIdaHostPath(entry.input_path, workspace.inputPath)))
|
|
271
|
+
throw new AnalysisProtocolError("An unowned worker still uses the private workspace; it was retained.");
|
|
272
|
+
}
|
|
273
|
+
if (this.#database !== undefined) {
|
|
274
|
+
const closed = closeDatabaseSchema.parse(await this.connection.call("idb_close", {
|
|
275
|
+
database: this.#database,
|
|
276
|
+
save: false,
|
|
277
|
+
}));
|
|
278
|
+
if (closed.session_id !== this.#database ||
|
|
279
|
+
closed.saved === true ||
|
|
280
|
+
closed.owned !== true ||
|
|
281
|
+
closed.backend !== "worker")
|
|
282
|
+
throw new AnalysisProtocolError("IDA database close did not confirm the requested owned, unsaved session release.");
|
|
283
|
+
const inventory = databaseListSchema.parse(await this.connection.call("idb_list", {}));
|
|
284
|
+
if (inventory.sessions.some((entry) => entry.session_id === this.#database ||
|
|
285
|
+
sameIdaHostPath(entry.input_path, this.#workspace?.inputPath ?? "")))
|
|
286
|
+
throw new AnalysisProtocolError("IDA worker remains registered after close.");
|
|
287
|
+
}
|
|
288
|
+
if (!this.#openCompleted)
|
|
289
|
+
throw new AnalysisProtocolError("IDA database open did not return a completed response. Worker inventory cannot prove that the request has stopped; the private workspace was retained.");
|
|
290
|
+
}
|
|
291
|
+
await this.connection.close();
|
|
292
|
+
await this.#workspace?.remove();
|
|
293
|
+
this.#closed = true;
|
|
294
|
+
return ok(null);
|
|
295
|
+
}
|
|
296
|
+
catch (cause) {
|
|
297
|
+
await this.connection.close().catch(() => undefined);
|
|
298
|
+
return err(new IdaCleanupError(this.#workspace?.directory ?? "IDA MCP connection", cause));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
async close() {
|
|
302
|
+
const result = await this.closeWithOutcome();
|
|
303
|
+
if (!result.ok)
|
|
304
|
+
throw result.error;
|
|
305
|
+
}
|
|
306
|
+
}
|