rea-agents 6.4.0 → 6.7.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/DISCLAIMER.md +136 -0
- package/README.md +76 -16
- package/THIRD_PARTY_NOTICES.md +135 -0
- package/bridge/android/ReaJadxBridge.java +281 -25
- package/bridge/cutter/rea_bridge.py +825 -0
- package/bridge/ghidra/ReaGhidraAnalysisOptions.java +38 -0
- package/bridge/ghidra/ReaGhidraBridge.java +1232 -142
- package/bridge/ghidra/ReaGhidraBundleActivator.java +14 -0
- package/bridge/ghidra/ReaGhidraMipsSoftFloat.java +176 -0
- package/bridge/ghidra/ReaGhidraPrepareRaw.java +49 -0
- package/bridge/hopper_bridge.py +111 -69
- package/bridge/mitmproxy/capture.py +189 -13
- package/bridge/native/rea_lldb_tracer.py +88 -10
- package/bridge/process/ProcessRunTokenReader.swift +76 -34
- package/bridge/pwndbg/core_context.py +15 -2
- package/bridge/pwntools/layout_impl.py +5 -0
- package/bridge/pwntools/recorded_crash_impl.py +31 -10
- package/dist/adb/AdbCommand.js +148 -0
- package/dist/adb/AdbConfiguration.js +41 -7
- package/dist/adb/AdbDeviceOutput.js +59 -37
- package/dist/adb/AdbDirectoryListing.js +80 -0
- package/dist/adb/AdbHostFileName.js +34 -0
- package/dist/adb/AdbInputSnapshot.js +126 -0
- package/dist/adb/AdbProvider.js +1106 -346
- package/dist/adb/AdbShellOutput.js +146 -77
- package/dist/android/AndroidTargetSnapshot.js +7 -7
- package/dist/android/JadxAnalysis.js +53 -33
- package/dist/android/JadxConfiguration.js +283 -145
- package/dist/android/JadxDoctor.js +123 -0
- package/dist/android/JadxFailure.js +154 -0
- package/dist/android/JadxInterruption.js +13 -0
- package/dist/android/JadxJavaProbe.js +246 -0
- package/dist/android/JadxMcpTransport.js +53 -18
- package/dist/android/JadxProtocol.js +43 -2
- package/dist/android/JadxProvider.js +183 -102
- package/dist/android/JadxRelease.js +17 -2
- package/dist/android/JadxSession.js +35 -14
- package/dist/android/JadxWorkspaceRoot.js +157 -0
- package/dist/apktool/ApktoolCommandCleanup.js +134 -0
- package/dist/apktool/ApktoolCommandOutput.js +22 -0
- package/dist/apktool/ApktoolConfiguration.js +306 -45
- package/dist/apktool/ApktoolDecodeOutput.js +131 -42
- package/dist/apktool/ApktoolDecodedInventory.js +52 -0
- package/dist/apktool/ApktoolProvider.js +296 -340
- package/dist/apktool/ApktoolStringTables.js +178 -0
- package/dist/apktool/ApktoolWorkspace.js +162 -0
- package/dist/application/AnalysisContextQueries.js +5 -8
- package/dist/application/AnalysisDocument.js +19 -4
- package/dist/application/AnalysisProvider.js +36 -18
- package/dist/application/AppBundleExecutable.js +16 -9
- package/dist/application/BinaryTargetResolver.js +204 -40
- package/dist/application/BrowserEvidence.js +1 -1
- package/dist/application/BrowserObservationService.js +54 -9
- package/dist/application/BrowserScenarioCaptureService.js +26 -7
- package/dist/application/CallPathTracing.js +52 -13
- package/dist/application/CapabilityInventory.js +182 -36
- package/dist/application/ClaudeDesktopConfigLocation.js +152 -0
- package/dist/application/ClientConfigurationCleanup.js +73 -0
- package/dist/application/ClientConfigurationDocument.js +270 -151
- package/dist/application/ClientConfigurationFiles.js +51 -14
- package/dist/application/ClientConfigurationPublication.js +167 -0
- package/dist/application/ClientRegistrationEnvironment.js +40 -4
- package/dist/application/ClientRegistrationIdentity.js +112 -32
- package/dist/application/ClientRegistrationStatus.js +280 -84
- package/dist/application/DirectAnalysis.js +98 -30
- package/dist/application/DirectAnalysisCleanup.js +5 -1
- package/dist/application/DirectAnalysisStatus.js +13 -1
- package/dist/application/Doctor.js +192 -37
- package/dist/application/DoctorDiagnostics.js +59 -16
- package/dist/application/DoctorProviderIds.js +8 -0
- package/dist/application/DoctorScope.js +11 -2
- package/dist/application/DshCordisPatch.js +355 -0
- package/dist/application/DshCordisYaml.js +155 -0
- package/dist/application/EnhancedLiteralTracing.js +30 -16
- package/dist/application/EnhancedToolTypes.js +0 -1
- package/dist/application/EnhancedTools.js +154 -56
- package/dist/application/EvidenceBundleCommands.js +30 -7
- package/dist/application/EvidenceBundleFiles.js +29 -7
- package/dist/application/FunctionAnalysisEvidence.js +3 -0
- package/dist/application/GeminiClientSettings.js +25 -13
- package/dist/application/HermesClientHome.js +20 -0
- package/dist/application/HermesConfigurationYaml.js +312 -0
- package/dist/application/HopperDownload.js +11 -3
- package/dist/application/HopperReleaseFeed.js +71 -0
- package/dist/application/InventoryProjectionEvidence.js +0 -1
- package/dist/application/InvestigationProviders.js +14 -3
- package/dist/application/JsonFiles.js +110 -20
- package/dist/application/JsonInputFile.js +220 -62
- package/dist/application/LinuxHopper.js +218 -115
- package/dist/application/LinuxHopperPublisher.js +656 -0
- package/dist/application/MacHopper.js +203 -83
- package/dist/application/MacHopperPaths.js +40 -0
- package/dist/application/{MipsElfAbiFlags.js → MipsElfMetadata.js} +71 -10
- package/dist/application/MipsElfSharedLoad.js +164 -0
- package/dist/application/MipsGnuAttributes.js +90 -0
- package/dist/application/MsixPackageStorage.js +140 -0
- package/dist/application/ProgressReporter.js +1 -1
- package/dist/application/ProviderOperationExecution.js +15 -14
- package/dist/application/ReconstructionCoverageService.js +0 -1
- package/dist/application/ReconstructionObligationCandidates.js +20 -4
- package/dist/application/ReconstructionObligationLedgerDiagnostics.js +2 -2
- package/dist/application/ReconstructionObligationLedgerEvaluation.js +19 -33
- package/dist/application/ReconstructionObligationLedgerProjection.js +3 -72
- package/dist/application/ReconstructionObligationLedgerService.js +6 -2
- package/dist/application/ReconstructionObligationOriginalCases.js +10 -1
- package/dist/application/ReferenceSourceImport.js +24 -8
- package/dist/application/ReferenceSourceImportEntries.js +180 -37
- package/dist/application/ReferenceSourceImportPolicy.js +5 -3
- package/dist/application/ReferenceSourceImportTypes.js +0 -1
- package/dist/application/ReferenceSourceVcsAdapter.js +36 -17
- package/dist/application/RegularFileRead.js +117 -70
- package/dist/application/Setup.js +59 -21
- package/dist/application/SetupClientConfiguration.js +301 -66
- package/dist/application/SetupClients.js +25 -10
- package/dist/application/SetupHost.js +149 -51
- package/dist/application/SetupInstallFailure.js +58 -3
- package/dist/application/SetupPlan.js +94 -55
- package/dist/application/SetupRecoveryBackup.js +93 -0
- package/dist/application/SetupRegistrationEnvironment.js +14 -1
- package/dist/application/SetupSkill.js +303 -76
- package/dist/application/SourceLimitations.js +35 -0
- package/dist/application/SupportedClients.js +166 -32
- package/dist/application/TypeScriptEmittedSourceCandidates.js +26 -0
- package/dist/application/Uninstall.js +356 -110
- package/dist/application/UninstallFailure.js +14 -0
- package/dist/application/Update.js +54 -25
- package/dist/application/UpdateCommandProgress.js +66 -0
- package/dist/application/UpdateFailure.js +17 -0
- package/dist/application/UpdateMaintenance.js +18 -31
- package/dist/application/UpdateRuntime.js +198 -54
- package/dist/application/WebModuleTraceService.js +42 -22
- package/dist/application/WebNetworkCaptureService.js +24 -12
- package/dist/application/WebRuntimeService.js +41 -8
- package/dist/application/WebScriptExportService.js +6 -4
- package/dist/application/WebSourceLocationService.js +23 -8
- package/dist/application/WindowsCapabilities.js +18 -15
- package/dist/application/WorkflowEvidence.js +31 -1
- package/dist/application/analysisView/AnalysisViewService.js +46 -11
- package/dist/application/android/AndroidAnalysisService.js +5 -4
- package/dist/application/android/AndroidPackageInspection.js +25 -0
- package/dist/application/android/AndroidSearchEvidenceSummary.js +98 -0
- package/dist/application/artifacts/ArtifactComparisonEvidence.js +32 -0
- package/dist/application/binary/AnalysisProviderEvaluation.js +14 -11
- package/dist/application/binary/AnalysisProviderRegistry.js +365 -60
- package/dist/application/binary/AnalysisSnapshotCache.js +41 -20
- package/dist/application/binary/AnalysisSnapshotFiles.js +75 -9
- package/dist/application/binary/BinarySession.js +308 -117
- package/dist/application/binary/BinarySessionExecution.js +5 -4
- package/dist/application/binary/BinarySessionOpen.js +13 -6
- package/dist/application/binary/BinarySessionRecords.js +36 -7
- package/dist/application/binary/BinarySessionStatus.js +96 -27
- package/dist/application/binary/BinaryTargetSummary.js +9 -0
- package/dist/application/binary/CompositeProvider.js +116 -28
- package/dist/application/binary/LazyAnalysisProvider.js +6 -66
- package/dist/application/binary/SessionProviderRouter.js +16 -4
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +14 -5
- package/dist/application/binaryDiagnostics/PeResourcesService.js +25 -5
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +17 -7
- package/dist/application/captures/PacketCaptureService.js +84 -0
- package/dist/application/closeOwnedWebResources.js +37 -0
- package/dist/application/electron/ElectronFusePort.js +1 -0
- package/dist/application/electron/ElectronFuseService.js +45 -0
- package/dist/application/evm/EvmInterfaceEvidence.js +11 -0
- package/dist/application/evm/EvmInterfaceService.js +5 -15
- package/dist/application/firmware/FirmwareAnalysisService.js +4 -3
- package/dist/application/flutter/DartAotInspection.js +26 -0
- package/dist/application/flutter/FlutterBuildAnalysisPort.js +1 -0
- package/dist/application/flutter/FlutterBuildAnalysisService.js +13 -0
- package/dist/application/frida/FridaInstrumentationPort.js +8 -0
- package/dist/application/frida/FridaInstrumentationService.js +310 -0
- package/dist/application/frida/fridaInputErrors.js +17 -0
- package/dist/application/go/GoBinaryPort.js +1 -0
- package/dist/application/go/GoBinaryService.js +79 -0
- package/dist/application/harmony/HarmonyApplicationService.js +17 -0
- package/dist/application/investigation/EvidenceLedger.js +43 -18
- package/dist/application/investigation/InvestigationRecords.js +12 -21
- package/dist/application/investigation/UnknownEvidence.js +22 -18
- package/dist/application/javascript/ElectronActiveObservationService.js +55 -25
- package/dist/application/javascript/ElectronBoundaryAnalysis.js +17 -3
- package/dist/application/javascript/ElectronBoundaryGraph.js +2 -0
- package/dist/application/javascript/ElectronBoundaryGraphCallPaths.js +144 -0
- package/dist/application/javascript/ElectronBoundaryGraphIpc.js +26 -7
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +1 -1
- package/dist/application/javascript/ElectronBoundaryGraphWindows.js +61 -11
- package/dist/application/javascript/ElectronEvidence.js +1 -2
- package/dist/application/javascript/ElectronObservationService.js +41 -8
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +21 -0
- package/dist/application/javascript/JavaScriptApplicationService.js +29 -14
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +0 -1
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +119 -49
- package/dist/application/javascript/JavaScriptArtifactAnalysisTypes.js +30 -1
- package/dist/application/javascript/JavaScriptArtifactGraphAccumulator.js +51 -21
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +31 -7
- package/dist/application/javascript/JavaScriptArtifactGraphContext.js +28 -6
- package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +25 -14
- package/dist/application/javascript/JavaScriptArtifactGraphEvidence.js +3 -3
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +186 -50
- package/dist/application/javascript/JavaScriptArtifactGraphStructure.js +173 -14
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +959 -188
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +57 -32
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +2 -0
- package/dist/application/javascript/JavaScriptModuleRelationships.js +34 -12
- package/dist/application/javascript/JavaScriptRecoveryService.js +29 -9
- package/dist/application/javascript/JavaScriptRuntimeObservationEvidence.js +1 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +33 -9
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +0 -1
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +4 -5
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +138 -43
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +13 -4
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +23 -3
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +18 -5
- package/dist/application/javascript/JavaScriptSemanticGraphElectronProjection.js +67 -0
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +4 -6
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +2 -3
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +5 -8
- package/dist/application/javascript/JavaScriptSemanticTraceService.js +0 -1
- package/dist/application/managed/ManagedApplicationGraphService.js +0 -1
- package/dist/application/managed/ManagedMemberComparisonService.js +72 -54
- package/dist/application/managed/ManagedNativeVerificationService.js +0 -1
- package/dist/application/managed/ManagedReconstructionService.js +0 -1
- package/dist/application/native/NativeCallRoutes.js +78 -41
- package/dist/application/native/NativeDispatchMetadataInspection.js +6 -2
- package/dist/application/native/NativeUiActionTrace.js +43 -22
- package/dist/application/native/NativeValueTrace.js +65 -23
- package/dist/application/pcap/PcapAnalysisPort.js +1 -0
- package/dist/application/pcap/PcapAnalysisService.js +24 -0
- package/dist/application/process/ProcessCli.js +33 -13
- package/dist/application/reverse/ReverseEngineeringCommandPort.js +1 -0
- package/dist/application/reverse/ReverseEngineeringService.js +688 -0
- package/dist/application/rust/RustBinaryPort.js +1 -0
- package/dist/application/rust/RustBinaryService.js +82 -0
- package/dist/application/signals/SignalRecordingService.js +84 -0
- package/dist/application/sqlite/SqliteDatabaseCapability.js +30 -0
- package/dist/application/sqlite/SqliteDatabasePort.js +1 -0
- package/dist/application/sqlite/SqliteDatabaseService.js +76 -0
- package/dist/application/wasm/WasmArtifactPort.js +1 -0
- package/dist/application/wasm/WasmArtifactService.js +76 -0
- package/dist/application/wasm/WasmInterfaceComparisonService.js +188 -0
- package/dist/artifacts/AnalysisCleanupLease.js +119 -0
- package/dist/artifacts/ArtifactFileOperation.js +150 -0
- package/dist/artifacts/ArtifactHash.js +15 -3
- package/dist/artifacts/ArtifactPaths.js +4 -7
- package/dist/artifacts/ArtifactProvider.js +24 -9
- package/dist/artifacts/ArtifactReader.js +63 -5
- package/dist/artifacts/ArtifactResourceScope.js +92 -9
- package/dist/artifacts/AsarArtifactReader.js +186 -120
- package/dist/artifacts/AsarEntryStream.js +49 -17
- package/dist/artifacts/AsarListing.js +78 -0
- package/dist/artifacts/DirectoryArtifactReader.js +119 -28
- package/dist/artifacts/MachOSliceArtifactReader.js +153 -23
- package/dist/artifacts/NativeDmgArtifactReader.js +264 -62
- package/dist/artifacts/OrderedReads.js +57 -0
- package/dist/artifacts/SafeOutputTree.js +24 -7
- package/dist/artifacts/SafeOutputTreeCreationFailure.js +1 -0
- package/dist/artifacts/SafeOutputTreeReadback.js +10 -16
- package/dist/artifacts/ZipArtifactReader.js +150 -25
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +79 -68
- package/dist/artifacts/apple/DylibFileAccess.js +106 -0
- package/dist/artifacts/apple/DylibResolutionReader.js +72 -157
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +108 -29
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +81 -28
- package/dist/artifacts/apple/KeyedArchiveReader.js +23 -13
- package/dist/artifacts/apple/MachoLoadCommandReader.js +77 -61
- package/dist/artifacts/apple/NibArchive.js +11 -4
- package/dist/artifacts/apple/PlistNumberLiterals.js +106 -118
- package/dist/artifacts/extraction/ArtifactExtraction.js +21 -19
- package/dist/artifacts/hostExecutableMarking.js +16 -0
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +139 -41
- package/dist/artifacts/inventory/classify.js +36 -17
- package/dist/artifacts/inventory/hashStableRootArtifact.js +14 -7
- package/dist/artifacts/inventory/reader.js +36 -21
- package/dist/artifacts/inventory/scanCanonical.js +27 -21
- package/dist/artifacts/inventory/scanReader.js +36 -10
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +166 -8
- package/dist/artifacts/readArtifactFileChunks.js +9 -0
- package/dist/artifacts/readStableArtifact.js +13 -11
- package/dist/browser/BrowserProcessStartup.js +20 -9
- package/dist/browser/BrowserScenarioPartialObservation.js +74 -92
- package/dist/browser/BrowserScenarioSecrets.js +176 -46
- package/dist/browser/CdpBrowserProvider.js +124 -102
- package/dist/browser/CdpCaptureDocuments.js +232 -102
- package/dist/browser/CdpCaptureDomSvg.js +80 -76
- package/dist/browser/CdpCaptureEventBodyShapes.js +9 -5
- package/dist/browser/CdpCaptureEventHandlers.js +23 -12
- package/dist/browser/CdpCaptureEvents.js +49 -10
- package/dist/browser/CdpCaptureStorage.js +22 -5
- package/dist/browser/CdpCaptureStorageFingerprints.js +54 -11
- package/dist/browser/CdpCaptureValues.js +12 -1
- package/dist/browser/CdpConnection.js +135 -30
- package/dist/browser/CdpElectronInspection.js +74 -64
- package/dist/browser/CdpElectronProvider.js +63 -6
- package/dist/browser/CdpElectronScriptEvents.js +4 -1
- package/dist/browser/CdpElectronScripts.js +4 -6
- package/dist/browser/CdpElectronWorkers.js +20 -4
- package/dist/browser/CdpEndpoint.js +143 -17
- package/dist/browser/CdpObservationSession.js +24 -8
- package/dist/browser/CdpPageCapture.js +68 -17
- package/dist/browser/CdpPageCaptureScripts.js +18 -13
- package/dist/browser/CdpPageCaptureWorkers.js +46 -11
- package/dist/browser/CdpSafeMetadata.js +32 -24
- package/dist/browser/CdpScreenshot.js +5 -14
- package/dist/browser/CdpSnapshotNodes.js +103 -0
- package/dist/browser/CdpSnapshotStrings.js +15 -0
- package/dist/browser/CdpTargetSession.js +76 -7
- package/dist/browser/CdpTargetSessionOwner.js +198 -0
- package/dist/browser/CdpWebMcpDiscovery.js +23 -6
- package/dist/browser/ElectronCaptureCleanup.js +82 -0
- package/dist/browser/ElectronProcessCleanup.js +91 -0
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +75 -20
- package/dist/browser/PlaywrightElectronActiveActions.js +57 -9
- package/dist/browser/PlaywrightElectronActiveFuses.js +86 -0
- package/dist/browser/PlaywrightElectronActiveProjection.js +21 -4
- package/dist/browser/PlaywrightElectronActiveProvider.js +237 -175
- package/dist/browser/PlaywrightExecutionBoundary.js +6 -4
- package/dist/browser/PlaywrightScenarioBrowser.js +240 -91
- package/dist/browser/PlaywrightScenarioEvents.js +287 -38
- package/dist/browser/PlaywrightScenarioServiceWorkers.js +336 -0
- package/dist/browser/PlaywrightScenarioSession.js +151 -46
- package/dist/browser/PlaywrightScenarioStorage.js +15 -7
- package/dist/browser/StructuredFieldToken.js +53 -0
- package/dist/browser/WebArtifactCleanup.js +53 -0
- package/dist/browser/WebSourceMapFetcher.js +181 -89
- package/dist/browser/assets/LocalWebScriptArtifacts.js +24 -3
- package/dist/browser/assets/PublishWebScripts.js +13 -2
- package/dist/browser/assets/ScenarioScriptCapture.js +2 -1
- package/dist/browser/assets/WebArtifactReads.js +15 -3
- package/dist/browser/assets/WebSourceLocationArtifacts.js +47 -3
- package/dist/browser/execution/CdpRuntimeSession.js +36 -7
- package/dist/browser/execution/CdpWebRuntimeProvider.js +22 -4
- package/dist/browser/history/CaptureFailures.js +29 -10
- package/dist/browser/history/CaptureFormatError.js +2 -2
- package/dist/browser/history/{HarJson.js → CaptureJson.js} +14 -4
- package/dist/browser/history/CaptureRedaction.js +16 -3
- package/dist/browser/history/CaptureRelease.js +20 -2
- package/dist/browser/history/HarCapture.js +54 -30
- package/dist/browser/history/HarSchema.js +36 -36
- package/dist/browser/history/HistoricalCaptureDecoder.js +93 -25
- package/dist/browser/history/NodeCaptureAdapter.js +48 -0
- package/dist/browser/history/{HarCaptureProcess.js → NodeCaptureProcess.js} +18 -9
- package/dist/browser/history/QlogCapture.js +385 -0
- package/dist/browser/history/SazCapture.js +130 -0
- package/dist/browser/history/SazHttp.js +61 -0
- package/dist/browser/history/SazMetadata.js +55 -0
- package/dist/browser/history/SazProjection.js +90 -0
- package/dist/browser/modules/NativeModuleResolver.js +248 -131
- package/dist/browser/modules/WebModuleArtifacts.js +49 -3
- package/dist/browser/network/PlaywrightNetworkContent.js +67 -9
- package/dist/browser/network/PlaywrightScenarioNetwork.js +249 -26
- package/dist/captures/TsharkCaptureProvider.js +377 -0
- package/dist/captures/parseFieldDiscovery.js +66 -0
- package/dist/captures/parsePacketOutput.js +21 -0
- package/dist/catalogIdentity.js +58 -42
- package/dist/cli/adbCommands.js +20 -21
- package/dist/cli/analysisViewCommands.js +1 -1
- package/dist/cli/androidCommands.js +13 -16
- package/dist/cli/apktoolCommands.js +14 -25
- package/dist/cli/applicationCommands.js +44 -17
- package/dist/cli/artifactCommands.js +1 -1
- package/dist/cli/binaryDiagnosticsCommands.js +17 -13
- package/dist/cli/browserAdvancedCommands.js +46 -26
- package/dist/cli/browserCommands.js +59 -33
- package/dist/cli/captureCommands.js +72 -0
- package/dist/cli/cliResultOutput.js +274 -0
- package/dist/cli/coreBinaryCommands.js +77 -30
- package/dist/cli/coreNativeCommands.js +53 -31
- package/dist/cli/cutterCommands.js +88 -0
- package/dist/cli/electronCommands.js +76 -13
- package/dist/cli/evmCommands.js +9 -19
- package/dist/cli/finishAnalysisCommand.js +52 -0
- package/dist/cli/firmwareCommands.js +20 -50
- package/dist/cli/flutterCommands.js +53 -0
- package/dist/cli/fridaCommands.js +219 -0
- package/dist/cli/goCommands.js +20 -0
- package/dist/cli/interactiveSetup.js +11 -1
- package/dist/cli/javascriptApplicationAnalysis.js +1 -1
- package/dist/cli/javascriptRecoveryCommands.js +18 -23
- package/dist/cli/jebCommands.js +2 -14
- package/dist/cli/jsonOutput.js +2 -2
- package/dist/cli/managedCommands.js +31 -3
- package/dist/cli/options.js +26 -2
- package/dist/cli/pcapCommands.js +29 -0
- package/dist/cli/processCommands.js +1 -1
- package/dist/cli/reverseEngineeringCommands.js +268 -0
- package/dist/cli/rustCommands.js +20 -0
- package/dist/cli/setupCommands.js +41 -12
- package/dist/cli/signalCommands.js +72 -0
- package/dist/cli/sqliteCommands.js +52 -0
- package/dist/cli/utilityCommands.js +116 -74
- package/dist/cli/wasmCommands.js +50 -0
- package/dist/cli/webModuleCommands.js +27 -38
- package/dist/cli/webNetworkCaptureCommands.js +10 -9
- package/dist/cli/webRuntimeCommands.js +15 -6
- package/dist/cli/webSourceLocationCommands.js +14 -33
- package/dist/cli-runtime/AnalysisCleanupLease-CWfTGYKd.js +103 -0
- package/dist/cli-runtime/AnalysisProvider-BGrYaMVo.js +38 -0
- package/dist/cli-runtime/AnalysisSnapshotCache-BjRlXeUS.js +711 -0
- package/dist/cli-runtime/ArtifactFileOperation-Dg4BcoEM.js +122 -0
- package/dist/cli-runtime/ArtifactReader-DMwm42bk.js +78 -0
- package/dist/cli-runtime/ArtifactResourceScope-CokZGcII.js +175 -0
- package/dist/cli-runtime/AsarHeader-BxwU17DJ.js +31 -0
- package/dist/cli-runtime/BinarySessionStatus-DRhjr7Vb.js +212 -0
- package/dist/cli-runtime/BinaryTargetResolver-tuCTjBlQ.js +1238 -0
- package/dist/cli-runtime/BoundedFileBytes-DRtiQNAQ.js +43 -0
- package/dist/cli-runtime/CdpTargetSession-CQ08KHbh.js +925 -0
- package/dist/cli-runtime/ClientConfigPath-Dn-V_GUf.js +255 -0
- package/dist/cli-runtime/ClientConfigurationDocument-C9T8MNGc.js +2021 -0
- package/dist/cli-runtime/ClientRegistrationStatus-PnD29RTX.js +585 -0
- package/dist/cli-runtime/CurrentEntrypointPath-m7QCIVN0.js +14 -0
- package/dist/cli-runtime/DirectAnalysis-C5NyUryV.js +581 -0
- package/dist/cli-runtime/DirectoryArtifactReader-CokAJ8vo.js +448 -0
- package/dist/cli-runtime/Doctor-DrkWsav4.js +668 -0
- package/dist/cli-runtime/ElectronFileScope-AP7VoVr7.js +1109 -0
- package/dist/cli-runtime/ElectronFuseFailures-DsjXR7Xp.js +609 -0
- package/dist/cli-runtime/ExecFileOutput-D6KLYTve.js +119 -0
- package/dist/cli-runtime/InterfaceBuilderDecodeBudget-CW1IO3dG.js +298 -0
- package/dist/cli-runtime/InventoryProjectionEvidence-DTH5QAqL.js +49 -0
- package/dist/cli-runtime/InvestigationProviders-CFh4a64d.js +118 -0
- package/dist/cli-runtime/JavaScriptApplicationEvidenceGraph-gOmPB2L6.js +160 -0
- package/dist/cli-runtime/JavaScriptApplicationWorkflowEvidence-WZgtK_Ok.js +75 -0
- package/dist/cli-runtime/JavaScriptWorkerMemoryLimit-B1bwMM1a.js +86 -0
- package/dist/cli-runtime/JebMcpEndpoint-BEalGZh9.js +710 -0
- package/dist/cli-runtime/JsonFiles-uvd6ZyQi.js +600 -0
- package/dist/cli-runtime/KunaInstallation-P0j3x851.js +1781 -0
- package/dist/cli-runtime/MacCodeSignature-MgYbRK_H.js +24 -0
- package/dist/cli-runtime/MacHopperPaths-bGzqjF1Z.js +34 -0
- package/dist/cli-runtime/MachoLoadCommandReader-CZm6N5vF.js +330 -0
- package/dist/cli-runtime/ManagedSnapshot-CPE9C3OD.js +4481 -0
- package/dist/cli-runtime/OwnedCommandCleanup-BN_V6Erc.js +187 -0
- package/dist/cli-runtime/OwnedRegularFile-D1f5nUCx.js +256 -0
- package/dist/cli-runtime/OwnedStagedOutput-D31dOozz.js +126 -0
- package/dist/cli-runtime/PrivateRuntimeRoot-Cd23u6jd.js +296 -0
- package/dist/cli-runtime/ProcessOwnership-CtrNr6ee.js +545 -0
- package/dist/cli-runtime/ProcessOwnershipObservation-C006iCtZ.js +920 -0
- package/dist/cli-runtime/ProviderDeadline-rSuH4Pm8.js +148 -0
- package/dist/cli-runtime/ProviderOperationExecution-CmU-XrQr.js +38 -0
- package/dist/cli-runtime/ProviderProcess-D87A7ctp.js +770 -0
- package/dist/cli-runtime/RegularFileRead-mbgGYtxe.js +125 -0
- package/dist/cli-runtime/SafeOutputTree-i904hd_2.js +525 -0
- package/dist/cli-runtime/SetupHost-CMPmPraB.js +1268 -0
- package/dist/cli-runtime/SharedStartupAttempt-BxKyf3Uv.js +1424 -0
- package/dist/cli-runtime/StableFileHash-Ame_h3lY.js +61 -0
- package/dist/cli-runtime/SupportedClients-DMafjitv.js +1066 -0
- package/dist/cli-runtime/UninstallFailure-1blyKXHE.js +22 -0
- package/dist/cli-runtime/Update-DAsASWlE.js +143 -0
- package/dist/cli-runtime/UpdateFailure-BcFNxEZZ.js +24 -0
- package/dist/cli-runtime/WindowsBatchCommand-Cx9kaVNf.js +97 -0
- package/dist/cli-runtime/WindowsNativeLoader-BqyZO0ZD.js +142 -0
- package/dist/cli-runtime/ZipArtifactReader-Jed69LEL.js +252 -0
- package/dist/cli-runtime/analysisErrorCleanup-COdAmDsb.js +33 -0
- package/dist/cli-runtime/appleArchiveFormat-Bb3G5CCI.js +269 -0
- package/dist/cli-runtime/application__DirectAnalysisStatus-F74bu9oy.js +150 -0
- package/dist/cli-runtime/application__EnhancedTools-Bg51b0Yp.js +1820 -0
- package/dist/cli-runtime/application__FunctionAnalysisEvidence-DBWIaYCh.js +41 -0
- package/dist/cli-runtime/application__ReconstructionCoverageService-AEPNpZqJ.js +32 -0
- package/dist/cli-runtime/application__ReconstructionObligationLedgerService-Cl9cPEZf.js +828 -0
- package/dist/cli-runtime/application__Setup-DwQzEewK.js +526 -0
- package/dist/cli-runtime/application__Uninstall-BOf9oyvQ.js +468 -0
- package/dist/cli-runtime/application__UpdateRuntime-CzWkRJHa.js +435 -0
- package/dist/cli-runtime/application__android__AndroidApplicationService-shW_aKlj.js +31 -0
- package/dist/cli-runtime/application__apple__AppleApplicationService-DIv6d3wB.js +31 -0
- package/dist/cli-runtime/application__harmony__HarmonyApplicationService-OIUFVQFV.js +31 -0
- package/dist/cli-runtime/application__javascript__ElectronActiveObservationService-wvCh72hK.js +118 -0
- package/dist/cli-runtime/application__javascript__ElectronObservationService-SydXPCwM.js +88 -0
- package/dist/cli-runtime/application__javascript__JavaScriptApplicationService-o0uEsjEc.js +12254 -0
- package/dist/cli-runtime/application__javascript__JavaScriptApplicationWorkflowService-BAheG_71.js +2336 -0
- package/dist/cli-runtime/application__javascript__JavaScriptRuntimeReconciliationService-Cnn4GP8q.js +88 -0
- package/dist/cli-runtime/application__javascript__JavaScriptSemanticTraceService-CmvLfV1A.js +299 -0
- package/dist/cli-runtime/artifacts__ArtifactProvider-wx2K0F2I.js +2205 -0
- package/dist/cli-runtime/binary-CWVNJhAC.js +19608 -0
- package/dist/cli-runtime/catalogIdentity-DAEEsOdX.js +1112 -0
- package/dist/cli-runtime/cli.js +44469 -0
- package/dist/cli-runtime/cliOutput-CgSuw782.js +163 -0
- package/dist/cli-runtime/cliOutput.js +5 -0
- package/dist/cli-runtime/cliResultOutput-10sd6xGx.js +1453 -0
- package/dist/cli-runtime/cliResultOutput.js +6 -0
- package/dist/cli-runtime/composition__browserScenario-BtPb1c1y.js +3414 -0
- package/dist/cli-runtime/composition__electronObservation-Bk8R6DJo.js +614 -0
- package/dist/cli-runtime/composition__electronScenario-BVF0qStH.js +916 -0
- package/dist/cli-runtime/cutterToolContracts-BQtG_Nzo.js +5267 -0
- package/dist/cli-runtime/doctorRuntime-B__SIpm-.js +478 -0
- package/dist/cli-runtime/dotnet__ManagedStaticProvider-DO5Yzcp4.js +5 -0
- package/dist/cli-runtime/errorSchemas-Ixz_q7qt.js +655 -0
- package/dist/cli-runtime/homeDirectory-DC_DeJIg.js +18 -0
- package/dist/cli-runtime/javascriptApplicationAnalysis-Dk6yBV8g.js +2088 -0
- package/dist/cli-runtime/javascriptExportReturnShapeProjection-CObOIiQ6.js +78 -0
- package/dist/cli-runtime/javascriptExportShapeComparisonSchemas-DpwuBenh.js +1244 -0
- package/dist/cli-runtime/javascriptRuntimeReconciliation-C6ZgWMys.js +1509 -0
- package/dist/cli-runtime/javascriptRuntimeReconciliationSchemas-D6tZKUQs.js +247 -0
- package/dist/cli-runtime/javascriptSemanticTraceSchemas-C7m0b6_w.js +126 -0
- package/dist/cli-runtime/lipo-DPQ6qurH.js +394 -0
- package/dist/cli-runtime/logger-BuDJ9xxO.js +48 -0
- package/dist/cli-runtime/machoContainer-Cy98bkFm.js +352 -0
- package/dist/cli-runtime/managedApplicationGraph-BazVqpJv.js +1136 -0
- package/dist/cli-runtime/managedToolContracts-BuFkMBH5.js +99 -0
- package/dist/cli-runtime/mcpDoctor.js +361 -0
- package/dist/cli-runtime/mcpStartupPolicy-imCbM3qo.js +28 -0
- package/dist/cli-runtime/native__NativeMacOSProvider-DTcRhuGA.js +5502 -0
- package/dist/cli-runtime/officialToolContracts-CzzVLx8I.js +1522 -0
- package/dist/cli-runtime/peMachine-B9ggfSJJ.js +95 -0
- package/dist/cli-runtime/propertyListKeys-D5dSASEy.js +355 -0
- package/dist/cli-runtime/providerCleanupError-BhsJyAhk.js +25 -0
- package/dist/cli-runtime/providerIdentities-Ao1XTvwx.js +31 -0
- package/dist/cli-runtime/providerStartupTimeout-B2tF2LtZ.js +17 -0
- package/dist/cli-runtime/readArtifactFileChunks-BbTL_PtB.js +129 -0
- package/dist/cli-runtime/reconstructionObligationLedgerSchemas-Bi6sect1.js +22156 -0
- package/dist/cli-runtime/rolldown-runtime-DXoylpqc.js +121 -0
- package/dist/cli-runtime/runtimeVersion-CMGd0bDu.js +23 -0
- package/dist/cli-runtime/safeJson-DKKACtdy.js +25 -0
- package/dist/cli-runtime/scanCanonical-CcDFUr-w.js +2594 -0
- package/dist/cli-runtime/snapshotEnvironment-Yvx5qwsl.js +196 -0
- package/dist/cli-runtime/toolContracts-CJzEyZ38.js +3795 -0
- package/dist/cli-runtime/toolOutputSchemaGroups-BqdSzySu.js +12249 -0
- package/dist/cli-runtime/workflowInputError-BP8z9Wxl.js +26 -0
- package/dist/cli.js +48 -5
- package/dist/cliBrowserScenarioCommands.js +41 -7
- package/dist/cliCommandNames.js +48 -0
- package/dist/cliEvidenceCommands.js +0 -1
- package/dist/cliJavaScriptRuntimeCommands.js +16 -14
- package/dist/cliJsonInput.js +12 -4
- package/dist/cliLogging.js +66 -15
- package/dist/cliObservationOptions.js +9 -0
- package/dist/cliOutput.js +105 -7
- package/dist/composition/binary.js +19 -2
- package/dist/composition/captures.js +3 -0
- package/dist/composition/directAnalysis.js +36 -11
- package/dist/composition/electronFuses.js +4 -0
- package/dist/composition/evm.js +12 -0
- package/dist/composition/flutter.js +3 -0
- package/dist/composition/go.js +4 -0
- package/dist/composition/javascriptAnalysisWorkerProcess.js +8 -8
- package/dist/composition/jeb.js +45 -5
- package/dist/composition/pcap.js +3 -0
- package/dist/composition/resolveWindowsProviderExecutable.js +61 -0
- package/dist/composition/reverseEngineering.js +29 -0
- package/dist/composition/rust.js +4 -0
- package/dist/composition/signals.js +3 -0
- package/dist/composition/sqlite.js +4 -0
- package/dist/composition/wasm.js +22 -0
- package/dist/composition/webNetworkCaptures.js +7 -2
- package/dist/config/environment.js +79 -4
- package/dist/config/ghidraDisabledAnalyzers.js +25 -0
- package/dist/config/homeDirectory.js +9 -6
- package/dist/config/mcpInputSchemaProfile.js +5 -1
- package/dist/config/mcpOutputSchemaProfile.js +22 -0
- package/dist/config/parseConfig.js +28 -34
- package/dist/config/parsers.js +4 -3
- package/dist/config/{ghidraStartupTimeout.js → providerStartupTimeout.js} +7 -3
- package/dist/contracts/adb/adbToolContracts.js +8 -8
- package/dist/contracts/analysisDetail.js +6 -3
- package/dist/contracts/analysisViewApiSurfaceExample.js +68 -0
- package/dist/contracts/analysisViewToolContracts.js +65 -3
- package/dist/contracts/android/androidToolContracts.js +17 -8
- package/dist/contracts/apktool/apktoolToolContracts.js +5 -1
- package/dist/contracts/applicationToolContracts.js +17 -2
- package/dist/contracts/artifactComparisonExample.js +18 -14
- package/dist/contracts/artifactToolContracts.js +16 -3
- package/dist/contracts/browserScenarioToolContracts.js +1 -1
- package/dist/contracts/browserToolContracts.js +13 -1
- package/dist/contracts/captures/captureToolContracts.js +42 -0
- package/dist/contracts/compactInputSchema.js +39 -12
- package/dist/contracts/cutterToolContracts.js +84 -0
- package/dist/contracts/enhancedToolContracts.js +2 -2
- package/dist/contracts/evm/evmToolContracts.js +30 -15
- package/dist/contracts/firmware/firmwareToolContracts.js +1 -1
- package/dist/contracts/flutter/flutterToolContracts.js +47 -0
- package/dist/contracts/fridaRemoteAddress.js +23 -0
- package/dist/contracts/fridaToolContracts.js +274 -0
- package/dist/contracts/functionComparisonExample.js +12 -1
- package/dist/contracts/gdbToolContracts.js +102 -0
- package/dist/contracts/go/goToolContracts.js +20 -0
- package/dist/contracts/hopperMemoryContracts.js +15 -0
- package/dist/contracts/inputSchemaPresentation.js +199 -38
- package/dist/contracts/investigationExamples.js +1 -0
- package/dist/contracts/javascript/electronToolContracts.js +27 -2
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +1 -0
- package/dist/contracts/javascript/javascriptRecoveryToolContracts.js +13 -1
- package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +1 -0
- package/dist/contracts/jsonSchemaKeywords.js +29 -0
- package/dist/contracts/managed/managedToolContracts.js +43 -4
- package/dist/contracts/managed/managedWorkflowExamples.js +10 -1
- package/dist/contracts/managed/managedWorkflowToolContracts.js +4 -30
- package/dist/contracts/mobileApplicationGraphExamples.js +27 -12
- package/dist/contracts/native/binaryDiagnosticsToolContracts.js +3 -2
- package/dist/contracts/native/nativeToolContracts.js +10 -6
- package/dist/contracts/officialToolContracts.js +7 -7
- package/dist/contracts/pcap/pcapToolContracts.js +33 -0
- package/dist/contracts/providerSelection.js +1 -0
- package/dist/contracts/reconstructionReadinessExample.js +126 -119
- package/dist/contracts/reverseEngineeringToolContracts.js +52 -0
- package/dist/contracts/rizinDebugToolContracts.js +97 -0
- package/dist/contracts/rust/rustToolContracts.js +20 -0
- package/dist/contracts/sessionLifecycleInputs.js +34 -2
- package/dist/contracts/sessionToolContracts.js +4 -4
- package/dist/contracts/sessionToolSchemas.js +14 -0
- package/dist/contracts/signals/signalToolContracts.js +40 -0
- package/dist/contracts/sqlite/sqliteToolContracts.js +36 -0
- package/dist/contracts/toolContractExamples.js +29 -0
- package/dist/contracts/toolContractTypes.js +2 -0
- package/dist/contracts/toolContracts.js +26 -0
- package/dist/contracts/toolEffects.js +252 -9
- package/dist/contracts/toolOutputSchemaGroups.js +78 -32
- package/dist/contracts/toolOutputSchemaPrimitives.js +118 -10
- package/dist/contracts/toolSchemaMetadata.js +102 -16
- package/dist/contracts/unknownContractExamples.js +1 -1
- package/dist/contracts/wasm/wasmComparisonContracts.js +52 -0
- package/dist/contracts/wasm/wasmToolContracts.js +33 -0
- package/dist/contracts/webNetworkCaptureToolContracts.js +15 -4
- package/dist/cutter/CutterBridgeClient.js +760 -0
- package/dist/cutter/CutterBridgeService.js +187 -0
- package/dist/doctorRuntime.js +41 -8
- package/dist/domain/adb/adbDeviceAnalysis.js +45 -5
- package/dist/domain/analysisErrorBase.js +79 -2
- package/dist/domain/analysisErrorCleanup.js +4 -2
- package/dist/domain/analysisErrorCore.js +32 -0
- package/dist/domain/analysisErrorPresentation.js +80 -20
- package/dist/domain/analysisErrorProjection.js +72 -37
- package/dist/domain/analysisProfile.js +7 -3
- package/dist/domain/analysisSearch.js +26 -0
- package/dist/domain/analysisSnapshot.js +312 -185
- package/dist/domain/analysisView/WebNetworkApiSurfaceAccumulator.js +353 -0
- package/dist/domain/analysisView/analysisView.js +391 -44
- package/dist/domain/analysisView/analysisViewCoverage.js +32 -0
- package/dist/domain/analysisView/analysisViewDataAdmission.js +86 -0
- package/dist/domain/analysisView/analysisViewErrors.js +4 -0
- package/dist/domain/analysisView/analysisViewParent.js +12 -0
- package/dist/domain/analysisView/analysisViewText.js +29 -0
- package/dist/domain/analysisView/androidPackageView.js +102 -0
- package/dist/domain/analysisView/artifactInventoryView.js +126 -0
- package/dist/domain/analysisView/binaryLayoutView.js +11 -4
- package/dist/domain/analysisView/dartAotView.js +93 -0
- package/dist/domain/analysisView/evmInterfaceView.js +105 -0
- package/dist/domain/analysisView/interfaceBuilderView.js +182 -0
- package/dist/domain/analysisView/javascriptApplicationCoverage.js +27 -0
- package/dist/domain/analysisView/javascriptApplicationView.js +123 -49
- package/dist/domain/analysisView/javascriptFactsView.js +92 -0
- package/dist/domain/analysisView/javascriptModuleReferences.js +37 -0
- package/dist/domain/analysisView/machoView.js +186 -0
- package/dist/domain/analysisView/managedArtifactView.js +108 -0
- package/dist/domain/analysisView/managedMemberView.js +215 -0
- package/dist/domain/analysisView/nativeFunctionView.js +20 -25
- package/dist/domain/analysisView/pcapCaptureView.js +264 -0
- package/dist/domain/analysisView/qlogCaptureView.js +198 -0
- package/dist/domain/analysisView/wasmArtifactView.js +162 -0
- package/dist/domain/analysisView/webNetworkApiSurfaceView.js +123 -0
- package/dist/domain/analysisView/webNetworkCaptureView.js +388 -0
- package/dist/domain/android/androidAnalysis.js +36 -2
- package/dist/domain/android/androidApplication.js +37 -64
- package/dist/domain/apktool/apktoolResourceAnalysis.js +70 -8
- package/dist/domain/apple/appleApplication.js +70 -87
- package/dist/domain/apple/appleArchiveFormat.js +184 -0
- package/dist/domain/apple/appleAssetCatalog.js +15 -0
- package/dist/domain/apple/appleBundleAnatomy.js +57 -69
- package/dist/domain/apple/dyldPaths.js +9 -2
- package/dist/domain/apple/dylibResolution.js +24 -10
- package/dist/domain/apple/dylibResolutionFindings.js +8 -9
- package/dist/domain/apple/interfaceBuilderGraph.js +78 -33
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +39 -12
- package/dist/domain/apple/jvmClassFile.js +226 -0
- package/dist/domain/apple/keyedArchive.js +39 -17
- package/dist/domain/apple/machoContainer.js +123 -8
- package/dist/domain/apple/machoCpuIdentity.js +4 -0
- package/dist/domain/apple/plistNumbers.js +67 -5
- package/dist/domain/apple/plistValue.js +95 -19
- package/dist/domain/artifactComparison.js +116 -37
- package/dist/domain/artifactDecompressionBudget.js +26 -0
- package/dist/domain/artifactGraph.js +18 -9
- package/dist/domain/artifactIdentity.js +4 -1
- package/dist/domain/artifactInspection.js +34 -3
- package/dist/domain/artifactInventoryEvidence.js +146 -40
- package/dist/domain/binaryTarget.js +251 -109
- package/dist/domain/binaryTargetTypes.js +24 -1
- package/dist/domain/browserNetworkEvidence.js +24 -3
- package/dist/domain/browserObservation.js +92 -56
- package/dist/domain/browserObservationError.js +4 -4
- package/dist/domain/browserObservationSchemas.js +4 -1
- package/dist/domain/browserScenarioCapture.js +11 -1
- package/dist/domain/browserScenarioCaptureLimits.js +34 -0
- package/dist/domain/browserScenarioCaptureValues.js +76 -2
- package/dist/domain/browserScenarioDiff.js +120 -11
- package/dist/domain/browserScenarioDiffEvidence.js +44 -13
- package/dist/domain/browserScenarioDiffValues.js +10 -3
- package/dist/domain/browserScenarioNetworkComparison.js +158 -0
- package/dist/domain/browserScenarioNormalization.js +10 -13
- package/dist/domain/browserScenarioValues.js +7 -13
- package/dist/domain/browserSession.js +2 -2
- package/dist/domain/bundleComparison.js +1 -5
- package/dist/domain/callPath.js +40 -3
- package/dist/domain/captures/packetCapture.js +139 -0
- package/dist/domain/captures/packetFields.js +81 -0
- package/dist/domain/changedBehavior.js +43 -41
- package/dist/domain/comparisonSourceEvidence.js +6 -0
- package/dist/domain/dosCom.js +2 -2
- package/dist/domain/dosMz.js +66 -19
- package/dist/domain/electron/electronFuseEvidence.js +42 -0
- package/dist/domain/electron/electronFuses.js +360 -0
- package/dist/domain/elfFixedHeader.js +66 -0
- package/dist/domain/evidence.js +105 -39
- package/dist/domain/evidenceBundle.js +67 -22
- package/dist/domain/evidenceErrors.js +5 -0
- package/dist/domain/evm/evmInterface.js +18 -4
- package/dist/domain/evm/solidityMetadata.js +70 -0
- package/dist/domain/explicitSensitiveFailure.js +44 -23
- package/dist/domain/fileSnapshotObservation.js +25 -0
- package/dist/domain/firmware/firmwareAnalysis.js +29 -0
- package/dist/domain/fixedTupleSchema.js +9 -0
- package/dist/domain/flutter/flutterBuildAnalysis.js +141 -0
- package/dist/domain/functionCallCoverage.js +60 -0
- package/dist/domain/functionComparisonDimensions.js +136 -18
- package/dist/domain/functionComparisonNormalization.js +83 -19
- package/dist/domain/functionComparisonResults.js +7 -6
- package/dist/domain/functionComparisonSchemas.js +14 -3
- package/dist/domain/functionDossierEvidence.js +4 -0
- package/dist/domain/go/goBinary.js +96 -0
- package/dist/domain/harmony/harmonyApplication.js +156 -0
- package/dist/domain/hopperErrors.js +19 -18
- package/dist/domain/hopperPublisher.js +12 -0
- package/dist/domain/hopperValues.js +135 -34
- package/dist/domain/javascript/electronActiveObservation.js +1 -0
- package/dist/domain/javascript/electronObservation.js +4 -1
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +94 -33
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +3 -1
- package/dist/domain/javascript/electronStaticAnalysisNative.js +19 -5
- package/dist/domain/javascript/electronStaticAnalysisValues.js +14 -28
- package/dist/domain/javascript/electronStaticOptionObjects.js +45 -0
- package/dist/domain/javascript/electronWrappedCallPaths.js +551 -0
- package/dist/domain/javascript/htmlArtifactReferences.js +94 -4
- package/dist/domain/javascript/javascriptAnalysisResourceControls.js +37 -1
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +7 -0
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +10 -2
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +1 -1
- package/dist/domain/javascript/javascriptApplicationGraph.js +17 -1
- package/dist/domain/javascript/javascriptApplicationGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptApplicationProjectionResources.js +8 -0
- package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +3 -1
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +49 -21
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +31 -18
- package/dist/domain/javascript/javascriptArtifactFiles.js +2 -1
- package/dist/domain/javascript/javascriptAstFingerprint.js +89 -24
- package/dist/domain/javascript/javascriptAstValues.js +132 -5
- package/dist/domain/javascript/javascriptBootstrap.js +94 -0
- package/dist/domain/javascript/javascriptBootstrapIntegrity.js +372 -0
- package/dist/domain/javascript/javascriptBuiltinResourceMethods.js +8 -0
- package/dist/domain/javascript/javascriptBundledRequireOrigin.js +278 -0
- package/dist/domain/javascript/javascriptCommonJsExportReceivers.js +231 -0
- package/dist/domain/javascript/javascriptContextBridgeExposure.js +23 -0
- package/dist/domain/javascript/javascriptElectronMemberWrites.js +96 -22
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +6 -5
- package/dist/domain/javascript/javascriptExportShapeVariants.js +1 -1
- package/dist/domain/javascript/javascriptFeatureSeed.js +34 -17
- package/dist/domain/javascript/javascriptFeatureTrace.js +9 -3
- package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +42 -11
- package/dist/domain/javascript/javascriptGraphqlOperations.js +382 -0
- package/dist/domain/javascript/javascriptIntrinsicInvocation.js +132 -0
- package/dist/domain/javascript/javascriptModuleDeclaration.js +48 -0
- package/dist/domain/javascript/javascriptModuleInterop.js +618 -0
- package/dist/domain/javascript/javascriptModuleResolutionMode.js +18 -0
- package/dist/domain/javascript/javascriptModuleSpecifier.js +5 -0
- package/dist/domain/javascript/javascriptNativeHandoff.js +7 -12
- package/dist/domain/javascript/javascriptPackageImportAliases.js +58 -0
- package/dist/domain/javascript/javascriptRecovery.js +12 -5
- package/dist/domain/javascript/javascriptRpcEndpoints.js +7 -93
- package/dist/domain/javascript/javascriptRuntimeLoadState.js +16 -0
- package/dist/domain/javascript/javascriptRuntimeObservation.js +4 -1
- package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +45 -16
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +65 -47
- package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +0 -1
- package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +5 -4
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +113 -11
- package/dist/domain/javascript/javascriptSemanticAmbientWrites.js +511 -0
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +706 -204
- package/dist/domain/javascript/javascriptSemanticAsyncEffects.js +54 -54
- package/dist/domain/javascript/javascriptSemanticCallResolution.js +59 -30
- package/dist/domain/javascript/javascriptSemanticCallableStack.js +52 -0
- package/dist/domain/javascript/javascriptSemanticCalls.js +10 -15
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +163 -92
- package/dist/domain/javascript/javascriptSemanticCoverage.js +5 -1
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +435 -45
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +46 -29
- package/dist/domain/javascript/javascriptSemanticDependencies.js +69 -0
- package/dist/domain/javascript/javascriptSemanticDerivedAnalysis.js +1 -1
- package/dist/domain/javascript/javascriptSemanticEvaluationOrder.js +126 -0
- package/dist/domain/javascript/javascriptSemanticExpressionShapes.js +111 -0
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +11 -14
- package/dist/domain/javascript/javascriptSemanticGetterQueries.js +147 -0
- package/dist/domain/javascript/javascriptSemanticGetterResults.js +264 -0
- package/dist/domain/javascript/javascriptSemanticGraph.js +22 -1
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +13 -1
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +5 -4
- package/dist/domain/javascript/javascriptSemanticMapOperations.js +51 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +421 -154
- package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +500 -27
- package/dist/domain/javascript/javascriptSemanticObjectReferences.js +377 -174
- package/dist/domain/javascript/javascriptSemanticObjects.js +53 -43
- package/dist/domain/javascript/javascriptSemanticOpaqueEffects.js +163 -0
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +11 -1
- package/dist/domain/javascript/javascriptSemanticProjection.js +180 -95
- package/dist/domain/javascript/javascriptSemanticPromises.js +6 -9
- package/dist/domain/javascript/javascriptSemanticProvenance.js +5 -1
- package/dist/domain/javascript/javascriptSemanticQuery.js +7 -2
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +2 -1
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +1 -1
- package/dist/domain/javascript/javascriptSemanticReferenceSources.js +25 -0
- package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +369 -8
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +3 -19
- package/dist/domain/javascript/javascriptSemanticResources.js +33 -44
- package/dist/domain/javascript/javascriptSemanticReturnedReferences.js +81 -26
- package/dist/domain/javascript/javascriptSemanticReturns.js +37 -30
- package/dist/domain/javascript/javascriptSemanticState.js +225 -39
- package/dist/domain/javascript/javascriptSemanticTraversal.js +6 -4
- package/dist/domain/javascript/javascriptSemanticValues.js +379 -56
- package/dist/domain/javascript/javascriptSourceMapPaths.js +44 -17
- package/dist/domain/javascript/javascriptSourceParser.js +121 -7
- package/dist/domain/javascript/javascriptSourceSelection.js +11 -0
- package/dist/domain/javascript/javascriptStaticAnalysis.js +69 -24
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +97 -23
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +488 -48
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +196 -78
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +4 -0
- package/dist/domain/javascript/javascriptStaticAnalysisTypes.js +2 -1
- package/dist/domain/javascript/javascriptSymbolicBindings.js +1118 -0
- package/dist/domain/javascript/javascriptSymbolicControlFlow.js +44 -0
- package/dist/domain/javascript/javascriptSymbolicValues.js +45 -0
- package/dist/domain/javascript/sourceToBundleComparison.js +3 -1
- package/dist/domain/javascript/sourceToBundleComparisonSchemas.js +2 -0
- package/dist/domain/javascript/sourceToBundleSignals.js +50 -13
- package/dist/domain/jsonValue.js +37 -12
- package/dist/domain/localPath.js +6 -3
- package/dist/domain/managed/managedApplicationGraph.js +5 -0
- package/dist/domain/managed/managedApplicationGraphCoverage.js +6 -2
- package/dist/domain/managed/managedApplicationGraphNodes.js +14 -10
- package/dist/domain/managed/managedArtifact.js +77 -1
- package/dist/domain/managed/managedInspectionEvidence.js +5 -6
- package/dist/domain/managed/managedMemberComparison.js +6 -0
- package/dist/domain/managed/managedMemberComparisonCoverage.js +36 -3
- package/dist/domain/managed/managedMemberComparisonItems.js +135 -59
- package/dist/domain/managed/managedMemberComparisonMatch.js +237 -42
- package/dist/domain/managed/managedMemberSignatureIdentity.js +40 -0
- package/dist/domain/managed/managedNativeVerificationMatch.js +54 -31
- package/dist/domain/managed/managedNativeVerificationSchemas.js +15 -4
- package/dist/domain/managed/managedReconstruction.js +5 -8
- package/dist/domain/mobileApplicationGraphProjection.js +95 -0
- package/dist/domain/native/addressCoordinate.js +11 -0
- package/dist/domain/native/binaryLayout.js +2 -4
- package/dist/domain/native/bytePattern.js +121 -0
- package/dist/domain/native/nativeAotPe.js +31 -4
- package/dist/domain/native/nativeAotSnapshotObservation.js +18 -0
- package/dist/domain/native/nativeCallPartialObservation.js +14 -12
- package/dist/domain/native/nativeInspection.js +38 -4
- package/dist/domain/native/nativeInstruction.js +17 -2
- package/dist/domain/native/nativeInvestigationGraph.js +9 -5
- package/dist/domain/native/nativeLoadImage.js +32 -1
- package/dist/domain/native/nativeUiObservation.js +5 -6
- package/dist/domain/native/objcSwiftMetadata.js +19 -9
- package/dist/domain/native/peResources.js +14 -4
- package/dist/domain/native/recordedCrash.js +79 -10
- package/dist/domain/offsetDateTime.js +60 -0
- package/dist/domain/pcap/pcapAnalysis.js +91 -0
- package/dist/domain/pcap/pcapEvidence.js +15 -0
- package/dist/domain/peMachine.js +38 -0
- package/dist/domain/pngHeader.js +18 -0
- package/dist/domain/process/processCaptureCoverage.js +26 -3
- package/dist/domain/process/processCaptureExample.js +2 -0
- package/dist/domain/process/processCaptureValidation.js +33 -8
- package/dist/domain/process/processComparison.js +41 -13
- package/dist/domain/process/processScenario.js +7 -0
- package/dist/domain/process/processTraceDimensionProjection.js +1 -1
- package/dist/domain/process/processTraceEvaluation.js +119 -74
- package/dist/domain/process/processTraceSpecification.js +243 -89
- package/dist/domain/propertyListKeys.js +238 -23
- package/dist/domain/propertyListXml.js +149 -0
- package/dist/domain/propertyListXmlText.js +20 -4
- package/dist/domain/providerAdapterError.js +2 -5
- package/dist/domain/providerCleanupError.js +2 -4
- package/dist/domain/providerConfigurationRefusal.js +12 -0
- package/dist/domain/providerSelectionError.js +2 -1
- package/dist/domain/qlogCapture.js +62 -0
- package/dist/domain/rawBinary.js +105 -0
- package/dist/domain/reconstructionCoverage.js +40 -24
- package/dist/domain/reconstructionCoverageEvaluation.js +50 -47
- package/dist/domain/reconstructionCoverageEvidence.js +26 -0
- package/dist/domain/reconstructionCoverageVerifierResults.js +35 -0
- package/dist/domain/reconstructionObligationLedgerIntegrity.js +114 -0
- package/dist/domain/reconstructionObligationLedgerSchemas.js +104 -1
- package/dist/domain/reconstructionReadiness.js +4 -8
- package/dist/domain/reconstructionReadinessJourneyFindings.js +4 -1
- package/dist/domain/reconstructionUnknowns.js +9 -1
- package/dist/domain/reconstructionVerification.js +86 -43
- package/dist/domain/recordedTransportUrl.js +59 -0
- package/dist/domain/referenceSourceClassification.js +27 -23
- package/dist/domain/referenceSourceGraph.js +51 -13
- package/dist/domain/referenceSourceImportParsing.js +27 -13
- package/dist/domain/referenceSourcePathIdentity.js +13 -1
- package/dist/domain/referenceSourceRequireBindings.js +40 -108
- package/dist/domain/referenceSourceSummary.js +92 -0
- package/dist/domain/relationshipCoverage.js +43 -0
- package/dist/domain/residualUnknown.js +93 -26
- package/dist/domain/reverseEngineering.js +31 -0
- package/dist/domain/runtimeVersion.js +8 -0
- package/dist/domain/rust/rustBinary.js +200 -0
- package/dist/domain/signals/annotationTextWindow.js +31 -0
- package/dist/domain/signals/signalDecoders.js +69 -0
- package/dist/domain/signals/signalRecording.js +115 -0
- package/dist/domain/sourceMapContents.js +10 -3
- package/dist/domain/sourceMapEnvelope.js +17 -11
- package/dist/domain/sqlite/sqliteDatabase.js +189 -0
- package/dist/domain/staticRuntimeCorrelation.js +7 -9
- package/dist/domain/swiftSymbolClassification.js +17 -0
- package/dist/domain/symbolAnalysis.js +20 -7
- package/dist/domain/urlComponents.js +6 -0
- package/dist/domain/wasm/wasmArtifact.js +119 -0
- package/dist/domain/wasm/wasmInterface.js +89 -0
- package/dist/domain/webBundleAnalysis.js +14 -3
- package/dist/domain/webBundleAnalyzerAst.js +7 -2
- package/dist/domain/webBundleAnalyzerInspection.js +113 -57
- package/dist/domain/webBundleAnalyzerResult.js +18 -6
- package/dist/domain/webCaptureDiff.js +235 -51
- package/dist/domain/webCaptureFrameComparison.js +49 -0
- package/dist/domain/webInventory.js +28 -14
- package/dist/domain/webMcpDiscovery.js +5 -2
- package/dist/domain/webModuleImports.js +22 -27
- package/dist/domain/webModuleTrace.js +25 -8
- package/dist/domain/webNetworkCapture.js +101 -39
- package/dist/domain/webNetworkCaptureCoordinates.js +21 -0
- package/dist/domain/webRuntime.js +0 -1
- package/dist/domain/webScreenshot.js +2 -2
- package/dist/domain/webScriptArtifacts.js +2 -4
- package/dist/domain/webScriptExport.js +6 -8
- package/dist/domain/webScriptExportError.js +2 -3
- package/dist/domain/webScriptExportPlan.js +2 -2
- package/dist/domain/webSourceLocation.js +20 -9
- package/dist/domain/xmlDocument.js +41 -0
- package/dist/domain/zipPackageFormat.js +25 -3
- package/dist/dotnet/ManagedArtifactInspector.js +25 -12
- package/dist/dotnet/ManagedDecodeBudget.js +87 -9
- package/dist/dotnet/ManagedMemberInspector.js +127 -22
- package/dist/dotnet/ManagedMemberInspectorCore.js +408 -141
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +109 -37
- package/dist/dotnet/ManagedMemberOwnership.js +65 -0
- package/dist/dotnet/ManagedMemberPointers.js +69 -0
- package/dist/dotnet/ManagedMemberRows.js +181 -48
- package/dist/dotnet/ManagedMetadataHeaps.js +110 -25
- package/dist/dotnet/ManagedMetadataInventory.js +5 -5
- package/dist/dotnet/ManagedMetadataInventoryRows.js +36 -52
- package/dist/dotnet/ManagedMetadataLayout.js +26 -16
- package/dist/dotnet/ManagedMetadataRowSizes.js +1 -1
- package/dist/dotnet/ManagedMethodBodyReader.js +29 -11
- package/dist/dotnet/ManagedMethodSpecs.js +78 -0
- package/dist/dotnet/ManagedNativeBoundaryHelpers.js +20 -19
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +13 -21
- package/dist/dotnet/ManagedPeReader.js +60 -27
- package/dist/dotnet/ManagedReaderFailure.js +9 -0
- package/dist/dotnet/ManagedSnapshot.js +93 -0
- package/dist/dotnet/ManagedStaticProvider.js +55 -64
- package/dist/dotnet/ManagedTypeMemberLists.js +105 -0
- package/dist/dotnet/ManagedTypeNameDigests.js +177 -0
- package/dist/dotnet/ManagedTypeNames.js +58 -0
- package/dist/dotnet/ManagedTypeNesting.js +25 -0
- package/dist/dotnet/ManagedTypeReferences.js +94 -0
- package/dist/dotnet/ManagedUserStrings.js +75 -0
- package/dist/electron/ElectronFuseFailures.js +105 -0
- package/dist/electron/ElectronFusePath.js +248 -0
- package/dist/electron/ElectronFuseProvider.js +88 -0
- package/dist/electron/ElectronFuseReader.js +333 -0
- package/dist/evaluation/AgentEvaluationFixtures.js +194 -11
- package/dist/evaluation/CodexAgentEval.js +19 -40
- package/dist/evaluation/KnownAnswerEvaluation.js +126 -57
- package/dist/evm/EvmoleFailures.js +20 -14
- package/dist/evm/EvmoleInterfaceAdapter.js +5 -1
- package/dist/evm/EvmoleInterfaceProvider.js +142 -35
- package/dist/evm/EvmoleInterfaceWorker.js +2 -0
- package/dist/evm/SolidityMetadata.js +139 -0
- package/dist/filesystem/OwnedRegularFile.js +116 -0
- package/dist/filesystem/OwnedStagedOutput.js +155 -0
- package/dist/filesystem/RegularFile.js +65 -9
- package/dist/filesystem/StableFileHash.js +56 -38
- package/dist/filesystem/callerPath.js +26 -0
- package/dist/filesystem/readFileHandleChunks.js +72 -13
- package/dist/filesystem/readStableFileBytes.js +85 -0
- package/dist/firmware/FirmwareCommand.js +15 -9
- package/dist/firmware/FirmwareFailures.js +56 -0
- package/dist/firmware/FirmwareFiles.js +136 -110
- package/dist/firmware/FirmwareProvider.js +122 -65
- package/dist/firmware/FirmwarePublication.js +244 -12
- package/dist/firmware/FirmwareReports.js +202 -12
- package/dist/flutter/DartElf.js +445 -0
- package/dist/flutter/ElfBuildId.js +137 -0
- package/dist/flutter/ElfLoadMap.js +91 -0
- package/dist/flutter/FlutterBuildProvider.js +866 -0
- package/dist/flutter/FlutterPayloadScan.js +180 -0
- package/dist/frida/FridaInstrumentationManager.js +1104 -0
- package/dist/gdb/GdbSessionManager.js +1639 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +146 -14
- package/dist/ghidra/GhidraAnalysisSeeds.js +39 -55
- package/dist/ghidra/GhidraBridgeSources.js +12 -0
- package/dist/ghidra/GhidraClient.js +501 -180
- package/dist/ghidra/GhidraClientStartup.js +5 -3
- package/dist/ghidra/GhidraClientWire.js +5 -2
- package/dist/ghidra/GhidraDiagnostics.js +23 -5
- package/dist/ghidra/GhidraDoctor.js +60 -26
- package/dist/ghidra/GhidraDosSnapshot.js +83 -0
- package/dist/ghidra/GhidraExecutableHeader.js +54 -0
- package/dist/ghidra/GhidraFileArtifacts.js +93 -0
- package/dist/ghidra/GhidraFunctionValues.js +50 -2
- package/dist/ghidra/GhidraInstallation.js +305 -108
- package/dist/ghidra/GhidraInstallationPolicy.js +94 -103
- package/dist/ghidra/GhidraInstallationProperties.js +57 -0
- package/dist/ghidra/GhidraInventoryValues.js +52 -6
- package/dist/ghidra/GhidraJavaLaunch.js +99 -11
- package/dist/ghidra/GhidraJavaProbe.js +267 -0
- package/dist/ghidra/GhidraJavaProperties.js +119 -0
- package/dist/ghidra/GhidraLanguageCatalog.js +83 -8
- package/dist/ghidra/GhidraLauncher.js +325 -85
- package/dist/ghidra/GhidraLoadImageAttest.js +82 -65
- package/dist/ghidra/GhidraLoadImageValues.js +109 -27
- package/dist/ghidra/GhidraMipsProfile.js +258 -14
- package/dist/ghidra/GhidraNativeAotSnapshotOwner.js +221 -0
- package/dist/ghidra/GhidraPeProfile.js +91 -0
- package/dist/ghidra/GhidraPowerPcProfile.js +51 -0
- package/dist/ghidra/GhidraProvider.js +267 -42
- package/dist/ghidra/GhidraProviderCapabilities.js +29 -15
- package/dist/ghidra/GhidraProviderClient.js +439 -276
- package/dist/ghidra/GhidraPspExtension.js +210 -0
- package/dist/ghidra/GhidraPspProfile.js +62 -0
- package/dist/ghidra/GhidraRawBinaryLanguage.js +49 -0
- package/dist/ghidra/GhidraReleasePolicy.js +93 -0
- package/dist/ghidra/GhidraRequestQueue.js +64 -40
- package/dist/ghidra/GhidraRiscvProfile.js +100 -0
- package/dist/ghidra/GhidraSessionError.js +301 -24
- package/dist/ghidra/GhidraSessionValues.js +76 -0
- package/dist/ghidra/GhidraSocketConnection.js +25 -11
- package/dist/ghidra/GhidraTargetSnapshot.js +67 -50
- package/dist/ghidra/GhidraTransport.js +86 -62
- package/dist/ghidra/extensions/GhidraExtensions.js +30 -45
- package/dist/go/GoBinaryContainer.js +140 -0
- package/dist/go/GoBinaryImage.js +210 -0
- package/dist/go/GoBinaryProvider.js +180 -0
- package/dist/go/GoElfImage.js +211 -0
- package/dist/go/GoMachoImage.js +164 -0
- package/dist/go/GoModuleText.js +217 -0
- package/dist/go/GoPeImage.js +124 -0
- package/dist/hopper/BridgeLauncher.js +78 -6
- package/dist/hopper/HopperAnalysisProfile.js +23 -11
- package/dist/hopper/HopperCleanup.js +29 -4
- package/dist/hopper/HopperClient.js +317 -93
- package/dist/hopper/HopperMacPublisher.js +29 -0
- package/dist/hopper/HopperMachOImage.js +61 -29
- package/dist/hopper/HopperProcessDiagnostic.js +27 -0
- package/dist/hopper/HopperProvider.js +57 -29
- package/dist/hopper/HopperProviderCapabilities.js +9 -4
- package/dist/hopper/HopperRegexSearch.js +21 -60
- package/dist/hopper/HopperRequestQueue.js +17 -5
- package/dist/hopper/HopperSessionValues.js +10 -1
- package/dist/ida/IdaBusyHealth.js +78 -0
- package/dist/ida/IdaCallGraph.js +134 -0
- package/dist/ida/IdaConfiguration.js +7 -2
- package/dist/ida/IdaDiagnosticRedactor.js +199 -0
- package/dist/ida/IdaDiagnosticWriter.js +62 -0
- package/dist/ida/IdaDoctor.js +7 -5
- package/dist/ida/IdaJsonDiagnostic.js +138 -0
- package/dist/ida/IdaMcpConnection.js +308 -32
- package/dist/ida/IdaNativeProtocol.js +85 -0
- package/dist/ida/IdaOperationRunner.js +246 -61
- package/dist/ida/IdaProtocolValues.js +88 -5
- package/dist/ida/IdaProvider.js +45 -10
- package/dist/ida/IdaProviderCapabilities.js +37 -8
- package/dist/ida/IdaSessionClient.js +379 -60
- package/dist/ida/IdaWorkspace.js +54 -6
- package/dist/inspector/V8InspectorCaptureProjection.js +14 -2
- package/dist/inspector/V8InspectorEndpoint.js +15 -13
- package/dist/inspector/V8InspectorProvider.js +43 -7
- package/dist/javascript/analysis/JavaScriptAnalysisTransfer.js +44 -12
- package/dist/javascript/analysis/JavaScriptAnalysisWorker.js +107 -32
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerProtocol.js +7 -4
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerSchemas.js +85 -10
- package/dist/javascript/analysis/JavaScriptAnalysisWorkerServer.js +16 -6
- package/dist/javascript/recovery/RecoveryFiles.js +107 -13
- package/dist/javascript/recovery/WakaruExecution.js +19 -11
- package/dist/javascript/recovery/WakaruProvider.js +12 -9
- package/dist/javascript/recovery/WakaruPublication.js +24 -10
- package/dist/javascript/recovery/WakaruRelease.js +1 -1
- package/dist/javascript/recovery/WakaruReport.js +3 -2
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +2 -16
- package/dist/javascript/sourceMaps/SourceMapCommand.js +22 -4
- package/dist/javascript/sourceMaps/SourceMapDecoder.js +22 -4
- package/dist/javascript/sourceMaps/SourceMapFormat.js +25 -38
- package/dist/javascript/sourceMaps/TraceSourceMap.js +34 -6
- package/dist/jeb/JebMcpConnection.js +148 -82
- package/dist/jeb/JebMcpConnectionOwner.js +116 -0
- package/dist/jeb/JebMcpDeadline.js +46 -0
- package/dist/jeb/JebMcpEndpoint.js +6 -1
- package/dist/jeb/JebProvider.js +82 -58
- package/dist/kuna/KunaAddress.js +11 -0
- package/dist/kuna/KunaCommand.js +217 -0
- package/dist/kuna/KunaConfiguration.js +90 -0
- package/dist/kuna/KunaDoctor.js +198 -0
- package/dist/kuna/KunaInstallation.js +137 -0
- package/dist/kuna/KunaJson.js +23 -0
- package/dist/kuna/KunaJsonStream.js +433 -0
- package/dist/kuna/KunaLimits.js +5 -0
- package/dist/kuna/KunaProjectCache.js +804 -0
- package/dist/kuna/KunaProjectExport.js +202 -0
- package/dist/kuna/KunaProjectFiles.js +191 -0
- package/dist/kuna/KunaProjectReader.js +115 -0
- package/dist/kuna/KunaProvider.js +217 -0
- package/dist/kuna/KunaProviderCapabilities.js +102 -0
- package/dist/kuna/KunaQueryErrors.js +12 -0
- package/dist/kuna/KunaQueryWork.js +113 -0
- package/dist/kuna/KunaReferenceFiles.js +258 -0
- package/dist/kuna/KunaReferenceQueries.js +211 -0
- package/dist/kuna/KunaRelease.js +10 -0
- package/dist/kuna/KunaRunSlots.js +56 -0
- package/dist/kuna/KunaSessionClient.js +1162 -0
- package/dist/kuna/KunaStringInventory.js +145 -0
- package/dist/kuna/KunaStringQueries.js +133 -0
- package/dist/kuna/KunaTargetCommands.js +205 -0
- package/dist/kuna/KunaUnavailable.js +11 -0
- package/dist/logger.js +14 -1
- package/dist/main/processShutdown.js +17 -0
- package/dist/main/shutdown.js +3 -0
- package/dist/main/transport.js +68 -4
- package/dist/main.js +16 -15
- package/dist/mcp/AnalysisProvider-BABWbLoM.js +38 -0
- package/dist/mcp/AnalysisSnapshotFiles-BXz0c37-.js +1423 -0
- package/dist/mcp/ArtifactFileOperation-64cQKI7B.js +1704 -0
- package/dist/mcp/ArtifactProvider-Dx6pmil1.js +2200 -0
- package/dist/mcp/ArtifactProviderMetadata-UCJr2oZW.js +167 -0
- package/dist/mcp/ArtifactReader-BrnwNaKY.js +78 -0
- package/dist/mcp/ArtifactResourceScope-zi3Dkqzy.js +175 -0
- package/dist/mcp/AsarHeader-B_IbppTz.js +31 -0
- package/dist/mcp/BinarySessionStatus-CZ9nnXMt.js +213 -0
- package/dist/mcp/BinaryTargetResolver-BUncASDP.js +1358 -0
- package/dist/mcp/BoundedFileBytes-DYt5q9G2.js +43 -0
- package/dist/mcp/CdpCaptureDocuments-Y2uFcBpl.js +795 -0
- package/dist/mcp/CdpCaptureValues-tNIg-gQK.js +97 -0
- package/dist/mcp/CdpEndpoint-BrhMhpSi.js +641 -0
- package/dist/mcp/CdpOptionalCommand-PZZhlqxv.js +120 -0
- package/dist/mcp/CdpTargetSession-BmmDC3XO.js +290 -0
- package/dist/mcp/DirectAnalysis-B9KuCHTG.js +417 -0
- package/dist/mcp/DirectAnalysisStatus-BgzopkIt.js +44 -0
- package/dist/mcp/ElectronFileScope-FXtK0d6I.js +110 -0
- package/dist/mcp/ElectronFuseFailures-uZ_wOV6T.js +610 -0
- package/dist/mcp/MachoLoadCommandReader-C2VGgHA3.js +330 -0
- package/dist/mcp/ManagedStaticProvider-CZuoPme2.js +5326 -0
- package/dist/mcp/NativeMacOSProvider-CMguKrvN.js +5495 -0
- package/dist/mcp/NativeMacOSProviderMetadata-B_RH4KXF.js +397 -0
- package/dist/mcp/OwnedCommand-BW1jBSt9.js +1241 -0
- package/dist/mcp/ProcedureAddressResolution-H6Qwpb_Y.js +59 -0
- package/dist/mcp/WorkflowEvidence-CO4C7ALz.js +118 -0
- package/dist/mcp/analysisErrorCleanup-Q344SnTO.js +34 -0
- package/dist/mcp/analysisErrorCore-BIEP7tvF.js +509 -0
- package/dist/mcp/analysisErrorProjection-B8teQwwD.js +942 -0
- package/dist/mcp/artifactToolContracts-C9dRDo-D.js +74 -0
- package/dist/mcp/browserObservation-DUraZs62.js +4633 -0
- package/dist/mcp/browserObservationError-C5okJ5el.js +63 -0
- package/dist/mcp/browserObservationSchemas-DwGGxBpu.js +573 -0
- package/dist/mcp/browserScenario-BRUz7yN0.js +3415 -0
- package/dist/mcp/browserScenarioCapture-CiMAsMx8.js +595 -0
- package/dist/mcp/callerPath-CpPnMZyN.js +678 -0
- package/dist/mcp/canonicalDigest-Bi_0_zGi.js +71 -0
- package/dist/mcp/electronActiveObservation-DV0Ffy9X.js +227 -0
- package/dist/mcp/electronFuses-D5SS7XXw.js +367 -0
- package/dist/mcp/electronObservation-DsN-NqY1.js +621 -0
- package/dist/mcp/electronObservation-wOYWwqgF.js +112 -0
- package/dist/mcp/electronScenario-CYrt2zBK.js +913 -0
- package/dist/mcp/emptyArraySchema-C0o2Sxwp.js +140 -0
- package/dist/mcp/enhancedInputs-6CCgB3VB.js +56 -0
- package/dist/mcp/javascriptRuntimeObservation-BVbhkO2-.js +693 -0
- package/dist/mcp/javascriptRuntimeObservation-Cu0Yedqq.js +121 -0
- package/dist/mcp/jsonSerialization-V-wWiFRE.js +152 -0
- package/dist/mcp/lipo-DSTgUqL1.js +395 -0
- package/dist/mcp/localPath-AxvW9aPe.js +19 -0
- package/dist/mcp/logger-BGdGHadX.js +48 -0
- package/dist/mcp/machoContainer-CMSxUBlK.js +605 -0
- package/dist/mcp/main-Cx-Z7m_n.js +80276 -0
- package/dist/mcp/main.js +6 -0
- package/dist/mcp/managedToolContracts-CSlbKJP-.js +101 -0
- package/dist/mcp/nativeValueTrace-BEZbDieM.js +3601 -0
- package/dist/mcp/officialToolContracts-CauCcSsc.js +1432 -0
- package/dist/mcp/peMachine-aP1iYnHq.js +95 -0
- package/dist/mcp/pngHeader-DQ-ObyY2.js +147 -0
- package/dist/mcp/propertyListKeys-BfCo0k4w.js +356 -0
- package/dist/mcp/providerCleanupError-DIRHxzWo.js +125 -0
- package/dist/mcp/providerIdentities--ptAh481.js +31 -0
- package/dist/mcp/providerIdentity-BCQ5n5tw.js +16 -0
- package/dist/mcp/providerOperationHealth-9DRSGM8N.js +71 -0
- package/dist/mcp/rolldown-runtime-BjeaiXFo.js +121 -0
- package/dist/mcp/safeJson-NeGfpkrI.js +25 -0
- package/dist/mcp/scanCanonical-CF3ATd1V.js +3788 -0
- package/dist/mcp/serverIdentity-BK0Ejd_Y.js +1507 -0
- package/dist/mcp/sourceMapEnvelope-DAaRUIGj.js +94 -0
- package/dist/mcp/toolContracts-BPoHQdlC.js +12414 -0
- package/dist/mcp/toolOutputSchemaGroups-MJ_f-PMK.js +17730 -0
- package/dist/mcp/webContentArtifact-DfGkgDcI.js +269 -0
- package/dist/mcp/webRuntime-ccyhkRru.js +74 -0
- package/dist/mcp/webSourceLocation-DKIum0vJ.js +13167 -0
- package/dist/mcpDoctor.js +95 -70
- package/dist/mcpStartupPolicy.js +20 -2
- package/dist/native/AppleDispatchCoverage.js +57 -17
- package/dist/native/AppleDispatchMetadata.js +82 -29
- package/dist/native/AppleMachoFixups.js +208 -35
- package/dist/native/AppleMachoSelection.js +30 -23
- package/dist/native/AppleObjcCategories.js +13 -3
- package/dist/native/AppleObjcDispatchFacets.js +95 -17
- package/dist/native/AppleObjcProperties.js +61 -17
- package/dist/native/AppleObjcProtocols.js +25 -7
- package/dist/native/AppleSwiftVtables.js +2 -0
- package/dist/native/CommandRunner.js +146 -32
- package/dist/native/LldbCallTracer.js +235 -179
- package/dist/native/LldbReadbackFiles.js +70 -0
- package/dist/native/LldbRetainedObservations.js +28 -56
- package/dist/native/MachoArchitectureSelection.js +50 -0
- package/dist/native/NativeCallObservation.js +55 -53
- package/dist/native/NativeCallTarget.js +95 -0
- package/dist/native/NativeMacOSProvider.js +318 -188
- package/dist/native/NativeMachoInspection.js +155 -81
- package/dist/native/NativePlistSource.js +179 -0
- package/dist/native/NativeUiCleanupError.js +30 -0
- package/dist/native/NativeUiHelperRuntime.js +48 -35
- package/dist/native/NativeUiObservation.js +69 -47
- package/dist/native/SignatureTargetBinding.js +147 -65
- package/dist/native/parsers/codesign.js +27 -10
- package/dist/native/parsers/demangle.js +22 -12
- package/dist/native/parsers/dyldInfo.js +73 -4
- package/dist/native/parsers/lipo.js +53 -19
- package/dist/native/parsers/machoUuid.js +150 -0
- package/dist/native/parsers/otool.js +275 -32
- package/dist/native/parsers/plist.js +40 -25
- package/dist/native/pe/PeResourceLayout.js +22 -7
- package/dist/native/pe/PeResourceParser.js +10 -9
- package/dist/native/pe/PeResourcesProvider.js +76 -15
- package/dist/native/pwndbg/CoreFileMappingAuthority.js +51 -0
- package/dist/native/pwndbg/PwndbgCoreContext.js +39 -28
- package/dist/native/pwntools/PwntoolsDecoder.js +339 -52
- package/dist/native/pwntools/PwntoolsFailures.js +19 -4
- package/dist/native/pwntools/PwntoolsInputLimit.js +27 -0
- package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +38 -16
- package/dist/native/pwntools/PwntoolsResourceLimits.js +3 -3
- package/dist/native/pwntools/RecordedCrashSourceBindings.js +12 -8
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +3 -1
- package/dist/objdump/ObjdumpCommand.js +24 -0
- package/dist/pcap/PcapCommand.js +146 -0
- package/dist/pcap/PcapConfiguration.js +93 -0
- package/dist/pcap/PcapNativeBound.js +58 -0
- package/dist/pcap/PcapOutput.js +276 -0
- package/dist/pcap/PcapProvider.js +454 -0
- package/dist/pcap/PcapSnapshot.js +191 -0
- package/dist/process/ArtifactAnalysisResources.js +306 -0
- package/dist/process/BoundedFileBytes.js +8 -3
- package/dist/process/CurrentEntrypointPath.js +8 -0
- package/dist/process/DarwinProcessRunTokenReader.js +276 -61
- package/dist/process/DetachedPgpSignature.js +57 -0
- package/dist/process/ExecFileBoundedOutput.js +44 -0
- package/dist/process/ExecFileOutput.js +44 -17
- package/dist/{hopper/HopperTargetLease.js → process/HopperLease.js} +76 -19
- package/dist/process/JavaScriptWorkerMemoryLimit.js +25 -0
- package/dist/process/LinuxResourceLimits.js +60 -0
- package/dist/process/MacCodeSignature.js +3 -0
- package/dist/process/OwnedCommand.js +144 -25
- package/dist/process/PrivateRuntimeRoot.js +9 -19
- package/dist/process/PrivateRuntimeRootUnavailableError.js +10 -0
- package/dist/process/ProcessOwnership.js +70 -17
- package/dist/process/ProcessOwnershipObservation.js +35 -4
- package/dist/process/ProviderDeadline.js +58 -12
- package/dist/process/ProviderProcess.js +233 -17
- package/dist/process/RegexMatcher.js +96 -0
- package/dist/process/SharedStartupAttempt.js +59 -0
- package/dist/process/WindowsAuthority.js +48 -39
- package/dist/process/WindowsBatchCommand.js +46 -0
- package/dist/process/boundedUtf8Text.js +13 -0
- package/dist/process/capture/FilesystemSnapshot.js +63 -11
- package/dist/process/capture/ProcessCaptureClock.js +2 -0
- package/dist/process/capture/ProcessCaptureError.js +64 -7
- package/dist/process/capture/ProcessCaptureJournal.js +2 -1
- package/dist/process/capture/ProcessCaptureLifecycle.js +104 -56
- package/dist/process/capture/ProcessCaptureProgress.js +7 -4
- package/dist/process/capture/ProcessHarness.js +34 -17
- package/dist/process/capture/ProcessNormalization.js +278 -36
- package/dist/process/capture/ProcessSampling.js +3 -2
- package/dist/process/capture/ProcessScenarioRuntimeValidation.js +13 -13
- package/dist/process/capture/TerminalRenderer.js +31 -10
- package/dist/process/ownedDebuggerSession.js +203 -0
- package/dist/process/snapshotEnvironment.js +8 -8
- package/dist/{application/binary → providers}/AnalysisClientCleanup.js +3 -3
- package/dist/providers/AnalysisClientCreation.js +193 -0
- package/dist/providers/AnalysisClientFailure.js +191 -0
- package/dist/providers/DeferredAnalysisClient.js +48 -0
- package/dist/providers/OwnedCommandCleanup.js +65 -0
- package/dist/providers/ProviderInspectionScope.js +10 -0
- package/dist/recordedCatalogDigests.js +2 -0
- package/dist/reference/ReferenceSourceReader.js +64 -1
- package/dist/reference/ReferenceSourceReaderEntries.js +79 -56
- package/dist/reference/ReferenceSourceReaderErrors.js +5 -1
- package/dist/reference/ReferenceSourceReaderFile.js +2 -2
- package/dist/reference/ReferenceSourceReaderTypes.js +1 -2
- package/dist/reference/ReferenceSourceReaderValidate.js +0 -1
- package/dist/rizin/RizinCommand.js +14 -0
- package/dist/rizin/RizinDebugSessionManager.js +1111 -0
- package/dist/rust/RustAuditableReader.js +309 -0
- package/dist/rust/RustBinaryImage.js +116 -0
- package/dist/rust/RustBinaryProvider.js +194 -0
- package/dist/server/EvidenceMcpServer.js +160 -37
- package/dist/server/admittedToolOperation.js +7 -2
- package/dist/server/contractToolHandler.js +17 -4
- package/dist/server/createServer.js +179 -30
- package/dist/server/externalMutationAdmission.js +50 -0
- package/dist/server/mcpProgress.js +4 -2
- package/dist/server/promptCompletion.js +43 -28
- package/dist/server/providerEnvironment.js +3 -0
- package/dist/server/registerAnalysisViewTool.js +6 -2
- package/dist/server/registerAndroidTools.js +22 -4
- package/dist/server/registerApplicationTools/projectMobileApplicationGraph.js +8 -1
- package/dist/server/registerArtifactComparisonTool.js +13 -2
- package/dist/server/registerArtifactTools.js +21 -1
- package/dist/server/registerBrowserScenarioTool.js +7 -5
- package/dist/server/registerBrowserTools.js +4 -8
- package/dist/server/registerBundleComparisonTool.js +4 -4
- package/dist/server/registerCaptureTools.js +12 -0
- package/dist/server/registerCutterTools.js +32 -0
- package/dist/server/registerElectronTools.js +13 -21
- package/dist/server/registerEnhancedTools.js +7 -6
- package/dist/server/registerEvidenceTools.js +14 -10
- package/dist/server/registerEvmTools.js +22 -4
- package/dist/server/registerFlutterTools.js +17 -0
- package/dist/server/registerFridaTools.js +201 -0
- package/dist/server/registerFunctionComparisonTool.js +29 -9
- package/dist/server/registerGdbTools.js +64 -0
- package/dist/server/registerGoTools.js +9 -0
- package/dist/server/registerInvestigationTools/helpers.js +2 -2
- package/dist/server/registerInvestigationTools.js +31 -27
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +3 -9
- package/dist/server/registerManagedTools.js +11 -1
- package/dist/server/registerManagedWorkflowTools/evidence.js +14 -7
- package/dist/server/registerNativeTools.js +14 -0
- package/dist/server/registerOfficialTools.js +5 -0
- package/dist/server/registerPcapTools.js +35 -0
- package/dist/server/registerProcessComparisonTool.js +12 -2
- package/dist/server/registerReverseEngineeringTools.js +86 -0
- package/dist/server/registerRizinDebugTools.js +53 -0
- package/dist/server/registerRustTools.js +9 -0
- package/dist/server/registerSessionRecordTools.js +19 -13
- package/dist/server/registerSessionStatusTool.js +33 -8
- package/dist/server/registerSessionTools.js +31 -31
- package/dist/server/registerSignalTools.js +12 -0
- package/dist/server/registerSqliteTools.js +9 -0
- package/dist/server/registerWasmTools.js +46 -0
- package/dist/server/registerWebNetworkCaptureTool.js +24 -10
- package/dist/server/retainedSummaryDelivery.js +28 -0
- package/dist/server/runDerivedOperation.js +2 -0
- package/dist/server/sessionAvailabilityPolicy.js +3 -0
- package/dist/server/toolRegistrationOptions.js +8 -0
- package/dist/server/toolResult.js +52 -19
- package/dist/server/toolResultEncoding.js +36 -3
- package/dist/serverIdentity.js +17 -8
- package/dist/signals/SigrokRecordingProvider.js +346 -0
- package/dist/signals/parseDecoderDiscovery.js +65 -0
- package/dist/sqlite/SqliteDatabaseFailures.js +147 -0
- package/dist/sqlite/SqliteDatabaseInspection.js +436 -0
- package/dist/sqlite/SqliteDatabaseLimits.js +16 -0
- package/dist/sqlite/SqliteDatabaseProvider.js +295 -0
- package/dist/sqlite/SqliteDatabaseSnapshot.js +182 -0
- package/dist/sqlite/SqliteDatabaseWorker.js +46 -0
- package/dist/sqlite/SqliteDatabaseWorkerExecution.js +127 -0
- package/dist/wasm/WabtArtifactProvider.js +358 -0
- package/dist/wasm/WabtFailures.js +119 -0
- package/dist/wasm/WabtInterface.js +309 -0
- package/dist/wasm/WabtOutput.js +60 -0
- package/dist/wasm/WabtRelease.js +12 -0
- package/dist/wasm/WabtRuntime.js +58 -0
- package/dist/wasm/WabtString.js +48 -0
- package/dist/wasm/WabtWat.js +147 -0
- package/dist/wasm/WasmGlueAdapter.js +66 -0
- package/dist/wasm/WasmInterfaceBudget.js +11 -0
- package/dist/windows/WindowsNativeLoader.js +53 -9
- package/dist/windows/WindowsOwnedProcess.js +150 -17
- package/dist/windows/WindowsPrivateRuntime.js +66 -2
- package/install.sh +157 -98
- package/licenses/Apache-2.0.txt +202 -0
- package/licenses/GCC-Runtime-Library-Exception-3.1.txt +73 -0
- package/licenses/GPL-3.0.txt +674 -0
- package/licenses/LGPL-2.0.txt +480 -0
- package/licenses/MIT-template.txt +18 -0
- package/licenses/MinGW-w64-runtime.txt +240 -0
- package/licenses/Node-22.19.0-LICENSE.txt +2666 -0
- package/licenses/README.md +68 -0
- package/licenses/cfworker-MIT.txt +21 -0
- package/licenses/dotnet-runtime-MIT.txt +23 -0
- package/licenses/frida-17.23.2-COPYING.txt +50 -0
- package/licenses/ghidra-12.1.4-DISCLAIMER.txt +13 -0
- package/licenses/ghidra-12.1.4-LICENSE.txt +201 -0
- package/licenses/ghidra-12.1.4-NOTICE.txt +49 -0
- package/licenses/npm-dependencies.txt +3757 -0
- package/licenses/npm-runtime-notices.txt +8722 -0
- package/licenses/upstream-sources.json +72 -0
- package/licenses/xterm-MIT.txt +21 -0
- package/native/windows/README.md +130 -12
- package/native/windows/build/manifest.json +2 -2
- package/native/windows/build/rea-windows-x64.node +0 -0
- package/package.json +97 -22
- package/scripts/electron-active-hook-boundaries.cjs +15 -2
- package/scripts/electron-active-hook.cjs +412 -47
- package/scripts/hopper-demo-x11.py +65 -13
- package/scripts/prepack.mjs +5 -0
- package/scripts/rea-android-workspace-guardian.mjs +46 -0
- package/scripts/rea.mjs +89 -26
- package/scripts/verify-windows-native-artifact.mjs +2 -2
- package/skills/reverse-engineer-anything/SKILL.md +146 -11
- package/skills/reverse-engineer-anything/references/android-applications.md +3 -1
- package/skills/reverse-engineer-anything/references/connection-and-recovery.md +10 -10
- package/skills/reverse-engineer-anything/references/evidence-workflows.md +23 -0
- package/skills/reverse-engineer-anything/references/javascript-applications.md +72 -3
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +149 -19
- package/skills/reverse-engineer-anything/references/runtime-observation.md +57 -7
- package/third_party/README.md +1 -1
- package/third_party/wabt/README.md +24 -0
- package/dist/browser/history/HarCaptureAdapter.js +0 -20
- package/dist/cli/streamedJsonOutput.js +0 -135
- package/dist/hopper/HopperRegexWorker.js +0 -27
- /package/dist/{application/binary → process}/AbortablePromise.js +0 -0
|
@@ -5,14 +5,18 @@ import java.io.BufferedReader;
|
|
|
5
5
|
import java.io.BufferedWriter;
|
|
6
6
|
import java.io.ByteArrayOutputStream;
|
|
7
7
|
import java.io.IOException;
|
|
8
|
+
import java.io.InputStream;
|
|
8
9
|
import java.math.BigInteger;
|
|
9
10
|
import java.net.InetAddress;
|
|
10
11
|
import java.net.InetSocketAddress;
|
|
12
|
+
import java.net.SocketTimeoutException;
|
|
11
13
|
import java.net.StandardProtocolFamily;
|
|
12
14
|
import java.net.UnixDomainSocketAddress;
|
|
13
15
|
import java.nio.channels.Channels;
|
|
14
16
|
import java.nio.channels.ServerSocketChannel;
|
|
15
17
|
import java.nio.channels.SocketChannel;
|
|
18
|
+
import java.nio.ByteBuffer;
|
|
19
|
+
import java.nio.charset.CharacterCodingException;
|
|
16
20
|
import java.nio.charset.StandardCharsets;
|
|
17
21
|
import java.nio.file.AtomicMoveNotSupportedException;
|
|
18
22
|
import java.nio.file.Files;
|
|
@@ -22,8 +26,11 @@ import java.nio.file.StandardCopyOption;
|
|
|
22
26
|
import java.nio.file.StandardOpenOption;
|
|
23
27
|
import java.nio.file.attribute.PosixFilePermissions;
|
|
24
28
|
import java.security.MessageDigest;
|
|
29
|
+
import java.util.ArrayDeque;
|
|
25
30
|
import java.util.ArrayList;
|
|
31
|
+
import java.util.Arrays;
|
|
26
32
|
import java.util.Comparator;
|
|
33
|
+
import java.util.HashMap;
|
|
27
34
|
import java.util.HashSet;
|
|
28
35
|
import java.util.IdentityHashMap;
|
|
29
36
|
import java.util.Iterator;
|
|
@@ -52,6 +59,8 @@ import ghidra.app.decompiler.DecompiledFunction;
|
|
|
52
59
|
import ghidra.app.decompiler.ClangCaseToken;
|
|
53
60
|
import ghidra.app.decompiler.ClangNode;
|
|
54
61
|
import ghidra.framework.Application;
|
|
62
|
+
import ghidra.app.util.bin.format.pdb.PdbParserConstants;
|
|
63
|
+
import ghidra.framework.options.Options;
|
|
55
64
|
import ghidra.program.model.address.Address;
|
|
56
65
|
import ghidra.program.model.address.AddressIterator;
|
|
57
66
|
import ghidra.program.model.address.AddressSet;
|
|
@@ -74,6 +83,7 @@ import ghidra.program.model.listing.Function;
|
|
|
74
83
|
import ghidra.program.model.listing.FunctionIterator;
|
|
75
84
|
import ghidra.program.model.listing.Instruction;
|
|
76
85
|
import ghidra.program.model.listing.InstructionIterator;
|
|
86
|
+
import ghidra.program.model.listing.Listing;
|
|
77
87
|
import ghidra.program.model.listing.Variable;
|
|
78
88
|
import ghidra.program.model.mem.MemoryBlock;
|
|
79
89
|
import ghidra.program.model.mem.MemoryBlockSourceInfo;
|
|
@@ -82,6 +92,7 @@ import ghidra.program.model.address.SegmentedAddress;
|
|
|
82
92
|
import ghidra.program.model.reloc.Relocation;
|
|
83
93
|
import java.io.ByteArrayOutputStream;
|
|
84
94
|
import ghidra.program.model.symbol.Namespace;
|
|
95
|
+
import ghidra.program.model.symbol.FlowType;
|
|
85
96
|
import ghidra.program.model.symbol.RefType;
|
|
86
97
|
import ghidra.program.model.symbol.Reference;
|
|
87
98
|
import ghidra.program.model.symbol.ReferenceIterator;
|
|
@@ -100,12 +111,19 @@ import ghidra.program.model.pcode.PcodeBlock;
|
|
|
100
111
|
import ghidra.program.model.pcode.PcodeBlockBasic;
|
|
101
112
|
import ghidra.program.model.pcode.Varnode;
|
|
102
113
|
import ghidra.program.model.pcode.VarnodeAST;
|
|
114
|
+
import ghidra.program.util.ContextEvaluatorAdapter;
|
|
115
|
+
import ghidra.program.util.SymbolicPropogator;
|
|
116
|
+
import ghidra.program.util.VarnodeContext;
|
|
103
117
|
|
|
104
118
|
public final class ReaGhidraBridge extends HeadlessScript {
|
|
119
|
+
// At most 24 KiB after worst-case JSON escaping (six bytes per UTF-16 unit).
|
|
120
|
+
private static final int PDB_ATTRIBUTE_UTF16_BUDGET = 4096;
|
|
105
121
|
private static final int MAX_HIGH_PCODE_OPS = 3000;
|
|
106
122
|
private static final int MAX_HIGH_PCODE_INPUTS_PER_OP = 64;
|
|
107
123
|
private static final int MAX_HIGH_PCODE_DEF_USE_EDGES = 12000;
|
|
108
124
|
private static final Gson GSON = new GsonBuilder().serializeNulls().create();
|
|
125
|
+
private final Map<FileBytes, Boolean> targetSourceIdentity = new IdentityHashMap<>();
|
|
126
|
+
private String admittedTargetSha256;
|
|
109
127
|
private static final Set<String> DESCRIPTOR_KEYS = Set.of(
|
|
110
128
|
"transport",
|
|
111
129
|
"endpoint_path",
|
|
@@ -122,11 +140,13 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
122
140
|
"params"
|
|
123
141
|
);
|
|
124
142
|
private static final String[] CAPABILITIES = {
|
|
143
|
+
"read_binary_inventory_summary",
|
|
125
144
|
"annotate_native_function",
|
|
126
145
|
"set_address_name",
|
|
127
146
|
"set_addresses_names",
|
|
128
147
|
"inspect_native_load_image",
|
|
129
148
|
"read_bytes",
|
|
149
|
+
"search_bytes",
|
|
130
150
|
"address_to_file_offset",
|
|
131
151
|
"ping",
|
|
132
152
|
"shutdown",
|
|
@@ -182,10 +202,17 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
182
202
|
}
|
|
183
203
|
sessionDefaultAddressSpace =
|
|
184
204
|
currentProgram.getAddressFactory().getDefaultAddressSpace();
|
|
185
|
-
if (currentProgram.getExecutableFormat().equals("Raw Binary")
|
|
186
|
-
|
|
187
|
-
.
|
|
188
|
-
|
|
205
|
+
if (currentProgram.getExecutableFormat().equals("Raw Binary")) {
|
|
206
|
+
boolean dosCom = currentProgram.getLanguageID().getIdAsString()
|
|
207
|
+
.equals("x86:LE:16:Real Mode");
|
|
208
|
+
String preparation = dosCom ? "REA DOS COM prepared" : "REA raw binary prepared";
|
|
209
|
+
if (!currentProgram.getOptions(ghidra.program.model.listing.Program.PROGRAM_INFO)
|
|
210
|
+
.getBoolean(preparation, false)) {
|
|
211
|
+
throw new IllegalStateException(
|
|
212
|
+
dosCom ? "REA DOS COM entry/context preparation failed" :
|
|
213
|
+
"REA raw binary entry preparation failed"
|
|
214
|
+
);
|
|
215
|
+
}
|
|
189
216
|
}
|
|
190
217
|
if (!Application.getApplicationVersion().equals(descriptor.providerVersion)) {
|
|
191
218
|
throw new IllegalStateException("Ghidra provider version does not match the session");
|
|
@@ -200,6 +227,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
200
227
|
"Ghidra imported-byte digest does not match the admitted target"
|
|
201
228
|
);
|
|
202
229
|
}
|
|
230
|
+
admittedTargetSha256 = descriptor.targetSha256;
|
|
203
231
|
// GhidraScript wraps run() in a transaction. End it before serving so
|
|
204
232
|
// each edit owns a real outer transaction and can roll back immediately.
|
|
205
233
|
end(true);
|
|
@@ -273,7 +301,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
273
301
|
Files.move(pendingPath, endpointPath);
|
|
274
302
|
}
|
|
275
303
|
}
|
|
276
|
-
|
|
304
|
+
acceptAuthenticatedLoopbackClient(server, descriptor);
|
|
277
305
|
}
|
|
278
306
|
finally {
|
|
279
307
|
Files.deleteIfExists(pendingPath);
|
|
@@ -285,6 +313,50 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
285
313
|
return System.getProperty("os.name", "").startsWith("Windows");
|
|
286
314
|
}
|
|
287
315
|
|
|
316
|
+
private static String readLoopbackHandshake(
|
|
317
|
+
SocketChannel client, int maxBytes, long timeoutMillis) throws IOException {
|
|
318
|
+
long deadline = System.nanoTime() + timeoutMillis * 1_000_000L;
|
|
319
|
+
InputStream input = client.socket().getInputStream();
|
|
320
|
+
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
|
321
|
+
while (true) {
|
|
322
|
+
long remaining = deadline - System.nanoTime();
|
|
323
|
+
if (remaining <= 0) throw new SocketTimeoutException("Bridge authentication timed out");
|
|
324
|
+
client.socket().setSoTimeout((int) Math.max(1,
|
|
325
|
+
Math.min(Integer.MAX_VALUE, (remaining + 999_999L) / 1_000_000L)));
|
|
326
|
+
int value = input.read();
|
|
327
|
+
if (value == -1) return null;
|
|
328
|
+
if (value == '\n') return bytes.toString(StandardCharsets.UTF_8);
|
|
329
|
+
if (bytes.size() == maxBytes) throw new IOException("Bridge authentication frame is too large");
|
|
330
|
+
bytes.write(value);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
private void acceptAuthenticatedLoopbackClient(
|
|
335
|
+
ServerSocketChannel server, SessionDescriptor descriptor) throws Exception {
|
|
336
|
+
while (true) {
|
|
337
|
+
try (SocketChannel client = server.accept()) {
|
|
338
|
+
Request first;
|
|
339
|
+
try {
|
|
340
|
+
String line = readLoopbackHandshake(client, 64 * 1024, 1_000);
|
|
341
|
+
if (line == null) continue;
|
|
342
|
+
first = parseRequest(line, descriptor.token);
|
|
343
|
+
}
|
|
344
|
+
catch (IOException | RuntimeException rejected) {
|
|
345
|
+
// A rejected unauthenticated peer cannot consume the bridge session.
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
client.socket().setSoTimeout(0);
|
|
349
|
+
try (BufferedReader reader = new BufferedReader(
|
|
350
|
+
Channels.newReader(client, StandardCharsets.UTF_8));
|
|
351
|
+
BufferedWriter writer = new BufferedWriter(
|
|
352
|
+
Channels.newWriter(client, StandardCharsets.UTF_8))) {
|
|
353
|
+
serveClient(descriptor, reader, writer, first);
|
|
354
|
+
}
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
288
360
|
private void acceptClient(
|
|
289
361
|
ServerSocketChannel server,
|
|
290
362
|
SessionDescriptor descriptor) throws Exception {
|
|
@@ -295,26 +367,28 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
295
367
|
BufferedWriter writer = new BufferedWriter(
|
|
296
368
|
Channels.newWriter(client, StandardCharsets.UTF_8)
|
|
297
369
|
)) {
|
|
298
|
-
serveClient(descriptor, reader, writer);
|
|
370
|
+
serveClient(descriptor, reader, writer, null);
|
|
299
371
|
}
|
|
300
372
|
}
|
|
301
373
|
|
|
302
374
|
private void serveClient(
|
|
303
375
|
SessionDescriptor descriptor,
|
|
304
376
|
BufferedReader reader,
|
|
305
|
-
BufferedWriter writer
|
|
377
|
+
BufferedWriter writer,
|
|
378
|
+
Request first) throws Exception {
|
|
306
379
|
while (true) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
380
|
+
Request request = first;
|
|
381
|
+
first = null;
|
|
382
|
+
if (request == null) {
|
|
383
|
+
String line = reader.readLine();
|
|
384
|
+
if (line == null) return;
|
|
385
|
+
try {
|
|
386
|
+
request = parseRequest(line, descriptor.token);
|
|
387
|
+
}
|
|
388
|
+
catch (RuntimeException exception) {
|
|
389
|
+
writeFailure(writer, 1, "invalid_request", "Bridge request is invalid");
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
318
392
|
}
|
|
319
393
|
try {
|
|
320
394
|
if (request.method.equals("shutdown")) {
|
|
@@ -354,8 +428,10 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
354
428
|
);
|
|
355
429
|
}
|
|
356
430
|
return switch (request.method) {
|
|
431
|
+
case "read_binary_inventory_summary" -> binaryInventorySummary(request.params);
|
|
357
432
|
case "inspect_native_load_image" -> inspectNativeLoadImage(request.params);
|
|
358
433
|
case "read_bytes" -> readMemoryBytes(request.params);
|
|
434
|
+
case "search_bytes" -> searchMemoryBytes(request.params, descriptor);
|
|
359
435
|
case "address_to_file_offset" -> addressToFileOffset(request.params);
|
|
360
436
|
case "address_name" -> addressName(request.params);
|
|
361
437
|
case "list_documents" -> listDocuments(request.params);
|
|
@@ -375,12 +451,14 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
375
451
|
case "search_procedures" -> search(request.params, true);
|
|
376
452
|
case "search_strings" -> search(request.params, false);
|
|
377
453
|
case "inspect_native_data_type" -> inspectNativeDataType(request.params);
|
|
378
|
-
case "inspect_native_instruction" -> inspectNativeInstruction(request.params);
|
|
454
|
+
case "inspect_native_instruction" -> inspectNativeInstruction(request.params, true);
|
|
379
455
|
case "resolve_native_call_targets" -> resolveNativeCallTargets(request.params);
|
|
380
456
|
case "xrefs" -> xrefs(request.params);
|
|
381
457
|
case "analyze_function" -> {
|
|
382
458
|
FunctionAnalysisObservation observation = analyzeFunctionObservation(request.params);
|
|
383
|
-
|
|
459
|
+
JsonObject result = functionObservation(observation.dossier(), observation.limitations());
|
|
460
|
+
result.add("relationship_coverage", observation.relationshipCoverage());
|
|
461
|
+
yield result;
|
|
384
462
|
}
|
|
385
463
|
case "set_address_name", "set_addresses_names" -> {
|
|
386
464
|
if (!descriptor.transport.equals("unix-socket"))
|
|
@@ -436,6 +514,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
436
514
|
.toArray(String[]::new)
|
|
437
515
|
));
|
|
438
516
|
result.add("target", target);
|
|
517
|
+
result.add("pdb", pdbObservation());
|
|
439
518
|
JsonArray extensions = analysisExtensions.reports();
|
|
440
519
|
if (extensions.size() > 0) result.add("analysis_extensions", extensions);
|
|
441
520
|
// Written by ReaGhidraApplySeeds before auto-analysis; REA checks it
|
|
@@ -443,9 +522,49 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
443
522
|
String seeds = currentProgram.getOptions(ghidra.program.model.listing.Program.PROGRAM_INFO)
|
|
444
523
|
.getString("REA analysis seeds", null);
|
|
445
524
|
if (seeds != null) result.add("analysis_seeds", JsonParser.parseString(seeds));
|
|
525
|
+
// Written by ReaGhidraMipsSoftFloat after analysis; REA requires it
|
|
526
|
+
// exactly when the committed profile declares soft-float storage.
|
|
527
|
+
String softFloat = currentProgram.getOptions(ghidra.program.model.listing.Program.PROGRAM_INFO)
|
|
528
|
+
.getString("REA MIPS soft-float storage", null);
|
|
529
|
+
if (softFloat != null) result.add("mips_soft_float_storage", JsonParser.parseString(softFloat));
|
|
446
530
|
return result;
|
|
447
531
|
}
|
|
448
532
|
|
|
533
|
+
/** Read loader/analyzer-owned facts without searching for or applying companions. */
|
|
534
|
+
private JsonObject pdbObservation() {
|
|
535
|
+
Options info = currentProgram.getOptions(ghidra.program.model.listing.Program.PROGRAM_INFO);
|
|
536
|
+
JsonObject pdb = new JsonObject();
|
|
537
|
+
String[] names = {"file", "guid", "age", "signature", "version"};
|
|
538
|
+
String[] attributes = {
|
|
539
|
+
PdbParserConstants.PDB_FILE, PdbParserConstants.PDB_GUID,
|
|
540
|
+
PdbParserConstants.PDB_AGE, PdbParserConstants.PDB_SIGNATURE,
|
|
541
|
+
PdbParserConstants.PDB_VERSION
|
|
542
|
+
};
|
|
543
|
+
int remaining = PDB_ATTRIBUTE_UTF16_BUDGET;
|
|
544
|
+
JsonArray omitted = new JsonArray();
|
|
545
|
+
for (int index = 0; index < names.length; index++) {
|
|
546
|
+
String value = info.getString(attributes[index], null);
|
|
547
|
+
if (value != null && value.length() > remaining) {
|
|
548
|
+
omitted.add(names[index]);
|
|
549
|
+
pdb.add(names[index], JsonNull.INSTANCE);
|
|
550
|
+
} else {
|
|
551
|
+
pdb.addProperty(names[index], value);
|
|
552
|
+
if (value != null) remaining -= value.length();
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (omitted.size() > 0) {
|
|
556
|
+
JsonObject limit = new JsonObject();
|
|
557
|
+
limit.addProperty("utf16_budget", PDB_ATTRIBUTE_UTF16_BUDGET);
|
|
558
|
+
limit.add("omitted_attributes", omitted);
|
|
559
|
+
pdb.add("resource_limit", limit);
|
|
560
|
+
}
|
|
561
|
+
if (info.contains(PdbParserConstants.PDB_LOADED))
|
|
562
|
+
pdb.addProperty("loaded", info.getBoolean(PdbParserConstants.PDB_LOADED, false));
|
|
563
|
+
else
|
|
564
|
+
pdb.add("loaded", JsonNull.INSTANCE);
|
|
565
|
+
return pdb;
|
|
566
|
+
}
|
|
567
|
+
|
|
449
568
|
private static String bytesHex(byte[] bytes) {
|
|
450
569
|
return java.util.HexFormat.of().formatHex(bytes);
|
|
451
570
|
}
|
|
@@ -621,24 +740,173 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
621
740
|
return result;
|
|
622
741
|
}
|
|
623
742
|
|
|
624
|
-
private JsonObject
|
|
743
|
+
private JsonObject searchMemoryBytes(JsonObject params, SessionDescriptor descriptor) throws Exception {
|
|
744
|
+
// mask, start, end, and cursor are omitted when absent; JSON encoding drops those keys.
|
|
745
|
+
Set<String> keys = params.keySet();
|
|
746
|
+
if (!keys.containsAll(Set.of("document", "pattern", "limit")) ||
|
|
747
|
+
!Set.of("document", "pattern", "mask", "start", "end", "limit", "cursor").containsAll(keys))
|
|
748
|
+
throw new RequestFailure("invalid_request", "Bridge request fields are invalid");
|
|
749
|
+
requireDocument(params);
|
|
750
|
+
// Public input validation owns the grammar; validate again at the socket boundary.
|
|
751
|
+
String pattern = requireString(params, "pattern").replaceAll("[\\s\\p{Z}\\uFEFF]", "");
|
|
752
|
+
String mask = params.has("mask") ? requireString(params, "mask") : null;
|
|
753
|
+
if (mask != null) mask = mask.replaceAll("[\\s\\p{Z}\\uFEFF]", "");
|
|
754
|
+
if (pattern.isEmpty() || pattern.length() % 2 != 0 ||
|
|
755
|
+
(mask != null && mask.length() != pattern.length()))
|
|
756
|
+
throw new RequestFailure("invalid_request", "Mask length must equal a nonempty byte pattern length");
|
|
757
|
+
byte[] bytes = new byte[pattern.length() / 2];
|
|
758
|
+
byte[] masks = new byte[bytes.length];
|
|
759
|
+
boolean constrained = false;
|
|
760
|
+
for (int index = 0; index < bytes.length; index++) {
|
|
761
|
+
monitor.checkCancelled();
|
|
762
|
+
String pair = pattern.substring(index * 2, index * 2 + 2);
|
|
763
|
+
if ((!pair.equals("??") && !isHexadecimal(pair, 0, 2)) ||
|
|
764
|
+
(mask != null && !isHexadecimal(mask, index * 2, index * 2 + 2)))
|
|
765
|
+
throw new RequestFailure("invalid_request", "Use hexadecimal byte pairs or ?? wildcards");
|
|
766
|
+
int selected = mask == null ? 255 : Integer.parseInt(mask.substring(index * 2, index * 2 + 2), 16);
|
|
767
|
+
bytes[index] = (byte) (pair.equals("??") ? 0 : Integer.parseInt(pair, 16));
|
|
768
|
+
masks[index] = (byte) (pair.equals("??") ? 0 : selected);
|
|
769
|
+
constrained |= masks[index] != 0;
|
|
770
|
+
}
|
|
771
|
+
if (!constrained) throw new RequestFailure("invalid_request", "Pattern must constrain at least one bit");
|
|
772
|
+
int limit = requireBoundedInteger(params, "limit", 1, 1000);
|
|
773
|
+
Address start = params.has("start") ? requireAddress(params, "start") : null;
|
|
774
|
+
Address end = params.has("end") ? requireAddress(params, "end") : null;
|
|
775
|
+
if (start != null && end != null &&
|
|
776
|
+
(!start.getAddressSpace().equals(end.getAddressSpace()) || start.compareTo(end) > 0))
|
|
777
|
+
throw new RequestFailure("invalid_request", "Search bounds must be ordered in one address space");
|
|
778
|
+
JsonArray identity = new JsonArray();
|
|
779
|
+
for (String value : new String[] { descriptor.targetSha256, descriptor.profileDigest,
|
|
780
|
+
bytesHex(bytes), bytesHex(masks), start == null ? "" : canonicalAddress(start),
|
|
781
|
+
end == null ? "" : canonicalAddress(end), optionalString(params, "document") }) identity.add(value);
|
|
782
|
+
String binding = bytesHex(MessageDigest.getInstance("SHA-256").digest(identity.toString().getBytes(StandardCharsets.UTF_8)));
|
|
783
|
+
String cursor = params.has("cursor") ? requireString(params, "cursor") : null;
|
|
784
|
+
Address resume = null;
|
|
785
|
+
if (cursor != null) {
|
|
786
|
+
if (!cursor.startsWith(binding + ":"))
|
|
787
|
+
throw new RequestFailure("invalid_request", "Byte search cursor does not match the target and query");
|
|
788
|
+
resume = parseReaAddress(cursor.substring(binding.length() + 1));
|
|
789
|
+
MemoryBlock resumedBlock = currentProgram.getMemory().getBlock(resume);
|
|
790
|
+
Address bound = start == null ? end : start;
|
|
791
|
+
if (resumedBlock == null || !resumedBlock.isInitialized() ||
|
|
792
|
+
(bound != null && !bound.getAddressSpace().equals(resume.getAddressSpace())) ||
|
|
793
|
+
(start != null && resume.compareTo(start) < 0) ||
|
|
794
|
+
(end != null && resume.compareTo(end) > 0))
|
|
795
|
+
throw new RequestFailure("invalid_request", "Byte search cursor lies outside initialized query memory");
|
|
796
|
+
}
|
|
797
|
+
List<MemoryBlock> ordered = new ArrayList<>(List.of(currentProgram.getMemory().getBlocks()));
|
|
798
|
+
ordered.sort(Comparator.comparing(MemoryBlock::getStart));
|
|
799
|
+
JsonArray matches = new JsonArray();
|
|
800
|
+
JsonArray blocks = new JsonArray();
|
|
801
|
+
JsonArray skipped = new JsonArray();
|
|
802
|
+
JsonArray notLoaded = new JsonArray();
|
|
803
|
+
long covered = 0;
|
|
804
|
+
String next = null;
|
|
805
|
+
for (MemoryBlock block : ordered) {
|
|
806
|
+
monitor.checkCancelled();
|
|
807
|
+
Address low = block.getStart();
|
|
808
|
+
Address high = block.getEnd();
|
|
809
|
+
Address bound = start == null ? end : start;
|
|
810
|
+
if (bound != null && !bound.getAddressSpace().equals(low.getAddressSpace())) continue;
|
|
811
|
+
// Without bounds, search loaded memory only. Non-loaded file parts
|
|
812
|
+
// (such as .symtab) and overlays stay reachable through explicit bounds.
|
|
813
|
+
if (bound == null && (!block.isLoaded() || block.isOverlay())) {
|
|
814
|
+
notLoaded.add(byteSearchCoverage(block, low, high));
|
|
815
|
+
continue;
|
|
816
|
+
}
|
|
817
|
+
if (start != null && low.compareTo(start) < 0) low = start;
|
|
818
|
+
if (end != null && high.compareTo(end) > 0) high = end;
|
|
819
|
+
if (low.compareTo(high) > 0) continue;
|
|
820
|
+
if (!block.isInitialized()) {
|
|
821
|
+
skipped.add(byteSearchCoverage(block, low, high));
|
|
822
|
+
continue;
|
|
823
|
+
}
|
|
824
|
+
if (next != null) continue;
|
|
825
|
+
if (resume != null && low.compareTo(resume) < 0) low = resume;
|
|
826
|
+
if (low.compareTo(high) > 0 || !low.getAddressSpace().equals(high.getAddressSpace())) continue;
|
|
827
|
+
Address at = low;
|
|
828
|
+
Address examinedEnd = high;
|
|
829
|
+
while (at != null && at.compareTo(high) <= 0 && high.subtract(at) >= bytes.length - 1L) {
|
|
830
|
+
monitor.checkCancelled();
|
|
831
|
+
// Ghidra's end address bounds candidate starts, not the final matched byte.
|
|
832
|
+
Address found = currentProgram.getMemory().findBytes(at, high.subtract(bytes.length - 1L), bytes, masks, true, monitor);
|
|
833
|
+
monitor.checkCancelled();
|
|
834
|
+
if (found == null || high.subtract(found) < bytes.length - 1L) break;
|
|
835
|
+
if (matches.size() == limit) {
|
|
836
|
+
next = binding + ":" + canonicalAddress(found);
|
|
837
|
+
examinedEnd = found.addNoWrap(bytes.length - 1L);
|
|
838
|
+
break;
|
|
839
|
+
}
|
|
840
|
+
JsonObject match = new JsonObject();
|
|
841
|
+
match.addProperty("address", canonicalAddress(found));
|
|
842
|
+
match.addProperty("segment", block.getName());
|
|
843
|
+
Long offset = targetFileOffset(block, found).offset();
|
|
844
|
+
match.add("file_offset", offset == null ? JsonNull.INSTANCE : GSON.toJsonTree(offset));
|
|
845
|
+
Function function = currentProgram.getFunctionManager().getFunctionContaining(found);
|
|
846
|
+
JsonObject procedure = new JsonObject();
|
|
847
|
+
if (function != null) {
|
|
848
|
+
procedure.addProperty("address", canonicalAddress(function.getEntryPoint()));
|
|
849
|
+
procedure.addProperty("name", function.getName(true));
|
|
850
|
+
}
|
|
851
|
+
match.add("procedure", function == null ? JsonNull.INSTANCE : procedure);
|
|
852
|
+
matches.add(match);
|
|
853
|
+
at = found.next();
|
|
854
|
+
}
|
|
855
|
+
JsonObject coverage = byteSearchCoverage(block, low, examinedEnd);
|
|
856
|
+
covered = Math.addExact(covered, coverage.get("bytes").getAsLong());
|
|
857
|
+
blocks.add(coverage);
|
|
858
|
+
}
|
|
859
|
+
JsonObject searched = new JsonObject();
|
|
860
|
+
searched.add("blocks", blocks);
|
|
861
|
+
searched.addProperty("bytes", covered);
|
|
862
|
+
searched.add("skipped_uninitialized", skipped);
|
|
863
|
+
searched.add("skipped_not_loaded", notLoaded);
|
|
864
|
+
JsonObject result = new JsonObject();
|
|
865
|
+
result.add("matches", matches);
|
|
866
|
+
result.add("searched", searched);
|
|
867
|
+
result.addProperty("complete", next == null);
|
|
868
|
+
result.add("next_cursor", next == null ? JsonNull.INSTANCE : GSON.toJsonTree(next));
|
|
869
|
+
return result;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
private static JsonObject byteSearchCoverage(MemoryBlock block, Address low, Address high) {
|
|
873
|
+
JsonObject result = new JsonObject();
|
|
874
|
+
result.addProperty("segment", block.getName());
|
|
875
|
+
result.addProperty("start", canonicalAddress(low));
|
|
876
|
+
result.addProperty("end", canonicalAddress(high));
|
|
877
|
+
result.addProperty("bytes", high.subtract(low) + 1);
|
|
878
|
+
return result;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
private record TargetFileOffset(Long offset, int mappings) {}
|
|
882
|
+
|
|
883
|
+
private TargetFileOffset targetFileOffset(MemoryBlock block, Address address) throws Exception {
|
|
884
|
+
Long offset = null;
|
|
885
|
+
int mappings = 0;
|
|
886
|
+
for (MemoryBlockSourceInfo source : block.getSourceInfos()) {
|
|
887
|
+
if (!source.contains(address) || source.getFileBytes().isEmpty() ||
|
|
888
|
+
!isTargetSource(source.getFileBytes().get())) continue;
|
|
889
|
+
long candidate = source.getFileBytesOffset(address);
|
|
890
|
+
if (candidate < 0) continue;
|
|
891
|
+
offset = candidate;
|
|
892
|
+
mappings++;
|
|
893
|
+
}
|
|
894
|
+
return new TargetFileOffset(mappings == 1 && offset <= 9007199254740991L ? offset : null, mappings);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
private JsonObject addressToFileOffset(JsonObject params) throws Exception {
|
|
625
898
|
requireKeys(params, Set.of("document", "address"));
|
|
626
899
|
requireDocument(params);
|
|
627
900
|
Address address = requireAddress(params, "address");
|
|
628
901
|
MemoryBlock block = currentProgram.getMemory().getBlock(address);
|
|
629
902
|
if (block == null || !block.isInitialized())
|
|
630
903
|
throw new RequestFailure("invalid_request", "Address has no initialized file-backed memory: " + canonicalAddress(address));
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
fileOffset = offset;
|
|
638
|
-
mappings++;
|
|
639
|
-
}
|
|
640
|
-
if (mappings != 1)
|
|
641
|
-
throw new RequestFailure("invalid_request", "Address has " + mappings + " authoritative source mappings: " + canonicalAddress(address));
|
|
904
|
+
TargetFileOffset mapping = targetFileOffset(block, address);
|
|
905
|
+
if (mapping.mappings() != 1)
|
|
906
|
+
throw new RequestFailure("invalid_request", "Address has " + mapping.mappings() + " authoritative target-file mappings: " + canonicalAddress(address));
|
|
907
|
+
Long fileOffset = mapping.offset();
|
|
908
|
+
if (fileOffset == null)
|
|
909
|
+
throw new RequestFailure("invalid_request", "Address lacks a safe file offset: " + canonicalAddress(address));
|
|
642
910
|
JsonObject result = new JsonObject();
|
|
643
911
|
result.addProperty("address", canonicalAddress(address));
|
|
644
912
|
result.addProperty("file_offset", fileOffset);
|
|
@@ -661,14 +929,97 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
661
929
|
private JsonElement procedurePseudocode(JsonObject params) throws Exception {
|
|
662
930
|
requireKeys(params, Set.of("document", "procedure"));
|
|
663
931
|
requireDocument(params);
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
932
|
+
String selector = requireString(params, "procedure");
|
|
933
|
+
JsonObject selection = new JsonObject();
|
|
934
|
+
Function function = resolveDecompileProcedure(selector, selection);
|
|
935
|
+
try {
|
|
936
|
+
String value = decompiledText(decompile(function));
|
|
937
|
+
JsonObject result = functionObservation(
|
|
938
|
+
value == null ? JsonNull.INSTANCE : GSON.toJsonTree(value),
|
|
939
|
+
functionBoundaryLimitations(
|
|
940
|
+
function,
|
|
941
|
+
currentProgram.getListing().getInstructions(function.getBody(), true)
|
|
942
|
+
)
|
|
943
|
+
);
|
|
944
|
+
if (selection.size() > 0) result.add("selection", selection);
|
|
945
|
+
return result;
|
|
946
|
+
} catch (RequestFailure failure) {
|
|
947
|
+
if (selection.size() == 0) throw failure;
|
|
948
|
+
// Preserve completed resolution facts without changing the backend's
|
|
949
|
+
// failure code or suggesting that the successful mapping was invalid.
|
|
950
|
+
throw new RequestFailure(failure.code, "Selector " + selector +
|
|
951
|
+
" mapped to analysis address " + selection.get("mapped_address").getAsString() +
|
|
952
|
+
" and procedure " + canonicalAddress(function.getEntryPoint()) +
|
|
953
|
+
"; " + failure.getMessage());
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
private Function resolveDecompileProcedure(String selector, JsonObject selection) throws Exception {
|
|
958
|
+
String prefix = "file-offset:";
|
|
959
|
+
boolean explicitOffset = selector.startsWith(prefix);
|
|
960
|
+
if (!explicitOffset) {
|
|
961
|
+
try {
|
|
962
|
+
return resolveProcedure(selector);
|
|
963
|
+
} catch (RequestFailure failure) {
|
|
964
|
+
// Existing names/addresses win. Only an unresolved numeric input
|
|
965
|
+
// can fall back to source coordinates; ambiguity never falls back.
|
|
966
|
+
if (!failure.code.equals("not_found") || !selector.matches("0x[0-9a-fA-F]+"))
|
|
967
|
+
throw failure;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
String coordinate = explicitOffset ? selector.substring(prefix.length()) : selector;
|
|
971
|
+
if (!coordinate.matches("0x[0-9a-fA-F]+"))
|
|
972
|
+
throw new RequestFailure("invalid_request", "File offsets require hexadecimal file-offset:0x... syntax");
|
|
973
|
+
BigInteger parsed = new BigInteger(coordinate.substring(2), 16);
|
|
974
|
+
if (parsed.compareTo(BigInteger.valueOf(9007199254740991L)) > 0)
|
|
975
|
+
throw new RequestFailure("invalid_request", "File offset exceeds the exact JSON integer range");
|
|
976
|
+
long offset = parsed.longValueExact();
|
|
977
|
+
monitor.checkCancelled();
|
|
978
|
+
// Ghidra's convenience lookup spans every FileBytes and uses coordinates
|
|
979
|
+
// local to each object. Only a complete, digest-matched target source
|
|
980
|
+
// establishes that the caller's offset belongs to the admitted file.
|
|
981
|
+
Set<Address> mappedAddresses = new java.util.LinkedHashSet<>();
|
|
982
|
+
for (MemoryBlock block : currentProgram.getMemory().getBlocks()) {
|
|
983
|
+
for (MemoryBlockSourceInfo source : block.getSourceInfos()) {
|
|
984
|
+
monitor.checkCancelled();
|
|
985
|
+
FileBytes backing = source.getFileBytes().orElse(null);
|
|
986
|
+
if (backing == null || !isTargetSource(backing)) continue;
|
|
987
|
+
Address mapped = source.locateAddressForFileOffset(offset);
|
|
988
|
+
if (mapped != null) mappedAddresses.add(mapped);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
List<Address> candidates = new ArrayList<>(mappedAddresses);
|
|
992
|
+
if (candidates.size() > 1)
|
|
993
|
+
throw new RequestFailure("ambiguous", "File offset " + coordinate +
|
|
994
|
+
" has multiple loaded mappings: " + candidates.stream().map(ReaGhidraBridge::canonicalAddress).toList() +
|
|
995
|
+
"; select an explicit analysis address");
|
|
996
|
+
if (candidates.isEmpty())
|
|
997
|
+
throw new RequestFailure("not_found", "File offset " + coordinate +
|
|
998
|
+
" has no loaded source mapping for the admitted target file; Ghidra image base: " + canonicalAddress(currentProgram.getImageBase()) +
|
|
999
|
+
". Inspect mappings with rea inspect-native-load-image <path> --provider ghidra --json or MCP inspect_native_load_image.");
|
|
1000
|
+
Address mapped = candidates.get(0);
|
|
1001
|
+
Function function = functionAtOrContaining(mapped);
|
|
1002
|
+
if (function == null)
|
|
1003
|
+
throw new RequestFailure("not_found", "File offset " + coordinate +
|
|
1004
|
+
" maps to analysis address " + canonicalAddress(mapped) +
|
|
1005
|
+
", but no procedure starts at or contains that address in the current Ghidra analysis. " +
|
|
1006
|
+
"Choose an observed procedure with CLI rea search <path> . --kind procedures --mode regex --provider ghidra --json or MCP list_procedures.");
|
|
1007
|
+
selection.addProperty("file_offset", offset);
|
|
1008
|
+
selection.addProperty("mapped_address", canonicalAddress(mapped));
|
|
1009
|
+
selection.addProperty("procedure_address", canonicalAddress(function.getEntryPoint()));
|
|
1010
|
+
return function;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
private boolean isTargetSource(FileBytes source) throws Exception {
|
|
1014
|
+
Boolean observed = targetSourceIdentity.get(source);
|
|
1015
|
+
if (observed != null) return observed;
|
|
1016
|
+
// Original FileBytes are immutable even when analysis memory is edited.
|
|
1017
|
+
// Partial/auxiliary sources remain inspectable but cannot establish an
|
|
1018
|
+
// original-target offset from their object-local coordinates alone.
|
|
1019
|
+
boolean matched = source.getFileOffset() == 0 &&
|
|
1020
|
+
constantTimeEquals(hashFileBytes(source, false), admittedTargetSha256);
|
|
1021
|
+
targetSourceIdentity.put(source, matched);
|
|
1022
|
+
return matched;
|
|
672
1023
|
}
|
|
673
1024
|
|
|
674
1025
|
private JsonElement procedureAssembly(JsonObject params) throws Exception {
|
|
@@ -678,7 +1029,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
678
1029
|
InstructionScan scan = scanInstructions(function, Integer.MAX_VALUE);
|
|
679
1030
|
return functionObservation(
|
|
680
1031
|
GSON.toJsonTree(renderAssembly(scan.instructions)),
|
|
681
|
-
|
|
1032
|
+
functionBoundaryLimitations(function, scan.instructions)
|
|
682
1033
|
);
|
|
683
1034
|
}
|
|
684
1035
|
|
|
@@ -697,7 +1048,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
697
1048
|
limitations.add(
|
|
698
1049
|
"The fast path does not invoke the decompiler or scan whole-program names and strings."
|
|
699
1050
|
);
|
|
700
|
-
List<String> boundaryLimitations =
|
|
1051
|
+
List<String> boundaryLimitations = functionBoundaryLimitations(function, scan.instructions);
|
|
701
1052
|
for (String limitation : boundaryLimitations) limitations.add(limitation);
|
|
702
1053
|
JsonObject result = new JsonObject();
|
|
703
1054
|
result.add("procedure", procedureIdentity(function));
|
|
@@ -706,7 +1057,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
706
1057
|
return functionObservation(result, boundaryLimitations);
|
|
707
1058
|
}
|
|
708
1059
|
|
|
709
|
-
private
|
|
1060
|
+
private JsonObject procedureCalls(JsonObject params, boolean callers) throws Exception {
|
|
710
1061
|
requireKeys(params, Set.of("document", "procedure"));
|
|
711
1062
|
requireDocument(params);
|
|
712
1063
|
Function function = resolveProcedure(requireString(params, "procedure"));
|
|
@@ -719,7 +1070,19 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
719
1070
|
for (Function item : ordered) {
|
|
720
1071
|
result.add(canonicalAddress(item.getEntryPoint()));
|
|
721
1072
|
}
|
|
722
|
-
|
|
1073
|
+
if (callers) {
|
|
1074
|
+
JsonObject observation = functionObservation(result, functionBoundaryLimitations(function,
|
|
1075
|
+
currentProgram.getListing().getInstructions(function.getBody(), true)
|
|
1076
|
+
));
|
|
1077
|
+
observation.add("relationship_coverage", callRelationshipCoverage(null,
|
|
1078
|
+
unrepresentedIncomingCalls(function, observed)));
|
|
1079
|
+
monitor.checkCancelled();
|
|
1080
|
+
return observation;
|
|
1081
|
+
}
|
|
1082
|
+
CallBoundaryObservation calls = callBoundaryObservation(
|
|
1083
|
+
function, currentProgram.getListing().getInstructions(function.getBody(), true), observed, false, null
|
|
1084
|
+
);
|
|
1085
|
+
return callRelationshipObservation(result, calls);
|
|
723
1086
|
}
|
|
724
1087
|
|
|
725
1088
|
private JsonObject procedureInfo(JsonObject params) throws Exception {
|
|
@@ -738,7 +1101,8 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
738
1101
|
result.add("classification", functionClassification(function));
|
|
739
1102
|
return functionObservation(
|
|
740
1103
|
result,
|
|
741
|
-
|
|
1104
|
+
functionBoundaryLimitations(
|
|
1105
|
+
function,
|
|
742
1106
|
currentProgram.getListing().getInstructions(function.getBody(), true)
|
|
743
1107
|
)
|
|
744
1108
|
);
|
|
@@ -769,20 +1133,22 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
769
1133
|
result.addProperty("direction", direction);
|
|
770
1134
|
result.add("references", edges);
|
|
771
1135
|
result.addProperty("reference_kinds_available", true);
|
|
1136
|
+
List<String> limitations;
|
|
772
1137
|
JsonArray unresolvedCalls = new JsonArray();
|
|
773
|
-
if (direction.equals("outgoing"))
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
1138
|
+
if (direction.equals("outgoing")) {
|
|
1139
|
+
CallBoundaryObservation calls = callBoundaryObservation(
|
|
1140
|
+
function, currentProgram.getListing().getInstructions(function.getBody(), true), null, true, references
|
|
1141
|
+
);
|
|
1142
|
+
unresolvedCalls = calls.unresolvedCalls();
|
|
1143
|
+
limitations = calls.limitations();
|
|
1144
|
+
} else {
|
|
1145
|
+
limitations = functionBoundaryLimitations(
|
|
1146
|
+
function,
|
|
1147
|
+
currentProgram.getListing().getInstructions(function.getBody(), true)
|
|
1148
|
+
);
|
|
783
1149
|
}
|
|
784
1150
|
result.add("unresolved_calls", unresolvedCalls);
|
|
785
|
-
return result;
|
|
1151
|
+
return functionObservation(result, limitations);
|
|
786
1152
|
}
|
|
787
1153
|
|
|
788
1154
|
private JsonObject inspectNativeDataType(JsonObject params) throws Exception {
|
|
@@ -885,7 +1251,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
885
1251
|
return item;
|
|
886
1252
|
}
|
|
887
1253
|
|
|
888
|
-
private JsonObject inspectNativeInstruction(JsonObject params) throws Exception {
|
|
1254
|
+
private JsonObject inspectNativeInstruction(JsonObject params, boolean includeIncoming) throws Exception {
|
|
889
1255
|
requireKeys(params, Set.of("document", "address"));
|
|
890
1256
|
requireDocument(params);
|
|
891
1257
|
Address address = requireAddress(params, "address");
|
|
@@ -896,6 +1262,19 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
896
1262
|
result.add("procedure", function == null ? JsonNull.INSTANCE : GSON.toJsonTree(canonicalAddress(function.getEntryPoint())));
|
|
897
1263
|
result.addProperty("architecture", currentProgram.getLanguageID().getIdAsString());
|
|
898
1264
|
result.addProperty("mode", currentProgram.getLanguage().getLanguageDescription().getVariant());
|
|
1265
|
+
if (currentProgram.getLanguageID().getIdAsString().startsWith("MIPS:")) {
|
|
1266
|
+
JsonArray decoderContext = new JsonArray();
|
|
1267
|
+
var modeRegister = currentProgram.getRegister("ISA_MODE");
|
|
1268
|
+
if (modeRegister != null) {
|
|
1269
|
+
var modeValue = currentProgram.getProgramContext().getValue(modeRegister, address, false);
|
|
1270
|
+
JsonObject context = new JsonObject();
|
|
1271
|
+
context.addProperty("register", modeRegister.getName());
|
|
1272
|
+
context.add("value", modeValue == null ? JsonNull.INSTANCE : GSON.toJsonTree(modeValue.toString()));
|
|
1273
|
+
context.addProperty("source", "ghidra-program-context");
|
|
1274
|
+
decoderContext.add(context);
|
|
1275
|
+
}
|
|
1276
|
+
result.add("decoder_context", decoderContext);
|
|
1277
|
+
}
|
|
899
1278
|
JsonArray operands = new JsonArray();
|
|
900
1279
|
JsonArray references = new JsonArray();
|
|
901
1280
|
JsonArray destinations = new JsonArray();
|
|
@@ -968,6 +1347,15 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
968
1347
|
result.add("operands", operands);
|
|
969
1348
|
result.add("flow", flow);
|
|
970
1349
|
result.add("references", references);
|
|
1350
|
+
if (includeIncoming) {
|
|
1351
|
+
TreeMap<String, Reference> incoming = new TreeMap<>();
|
|
1352
|
+
visitObservedReferencesTo(address, reference -> addReference(incoming, reference));
|
|
1353
|
+
List<Reference> orderedIncoming = new ArrayList<>(incoming.values());
|
|
1354
|
+
orderedIncoming.sort(REFERENCE_ORDER);
|
|
1355
|
+
JsonArray incomingReferences = new JsonArray();
|
|
1356
|
+
for (Reference reference : orderedIncoming) incomingReferences.add(instructionReference(reference));
|
|
1357
|
+
result.add("incoming_references", incomingReferences);
|
|
1358
|
+
}
|
|
971
1359
|
List<String> limitations = new ArrayList<>(List.of("Operand components are Ghidra Listing decoder tokens; effective memory base/index/displacement roles and per-instruction context mode are unavailable. The mode field is the program language variant."));
|
|
972
1360
|
if (flow.get("kind").getAsString().equals("terminal")) limitations.add("No RETURN operation was observed in the provider's instruction p-code; terminal classification remains generic.");
|
|
973
1361
|
result.add("limitations", GSON.toJsonTree(limitations));
|
|
@@ -975,7 +1363,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
975
1363
|
}
|
|
976
1364
|
|
|
977
1365
|
private JsonObject resolveNativeCallTargets(JsonObject params) throws Exception {
|
|
978
|
-
JsonObject instruction = inspectNativeInstruction(params);
|
|
1366
|
+
JsonObject instruction = inspectNativeInstruction(params, false);
|
|
979
1367
|
JsonObject result = new JsonObject();
|
|
980
1368
|
result.add("call_site", instruction.get("address"));
|
|
981
1369
|
result.add("procedure", instruction.get("procedure"));
|
|
@@ -1013,16 +1401,8 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1013
1401
|
requireKeys(params, Set.of("document", "address"));
|
|
1014
1402
|
requireDocument(params);
|
|
1015
1403
|
Address address = requireAddress(params, "address");
|
|
1016
|
-
ReferenceIterator references = currentProgram.getReferenceManager().getReferencesTo(address);
|
|
1017
1404
|
Set<Address> sources = new HashSet<>();
|
|
1018
|
-
|
|
1019
|
-
monitor.checkCancelled();
|
|
1020
|
-
Reference reference = references.next();
|
|
1021
|
-
if (reference.isEntryPointReference()) {
|
|
1022
|
-
continue;
|
|
1023
|
-
}
|
|
1024
|
-
sources.add(reference.getFromAddress());
|
|
1025
|
-
}
|
|
1405
|
+
visitObservedReferencesTo(address, reference -> sources.add(reference.getFromAddress()));
|
|
1026
1406
|
List<Address> ordered = new ArrayList<>(sources);
|
|
1027
1407
|
ordered.sort(Address::compareTo);
|
|
1028
1408
|
JsonArray result = new JsonArray();
|
|
@@ -1162,19 +1542,28 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1162
1542
|
InstructionScan scan = scanInstructions(function, Integer.MAX_VALUE);
|
|
1163
1543
|
DecompileResults decompilation = decompile(function);
|
|
1164
1544
|
String pseudocode = decompiledText(decompilation);
|
|
1545
|
+
JsonObject availability = new JsonObject();
|
|
1546
|
+
availability.add("pseudocode", facetAvailability(
|
|
1547
|
+
pseudocode != null,
|
|
1548
|
+
function.isExternal() ? "Ghidra does not decompile external functions."
|
|
1549
|
+
: function.getBody().isEmpty() ? "Ghidra has no function body to decompile."
|
|
1550
|
+
: "Ghidra completed decompilation without returning pseudocode."
|
|
1551
|
+
));
|
|
1165
1552
|
if (pseudocode == null) {
|
|
1166
1553
|
pseudocode = "";
|
|
1167
1554
|
}
|
|
1168
|
-
List<Reference>
|
|
1169
|
-
|
|
1555
|
+
List<Reference> bodyIncoming = collectReferences(function, "incoming");
|
|
1556
|
+
List<Reference> incomingReferences = bodyIncoming.stream()
|
|
1170
1557
|
.filter(reference -> !function.getBody().contains(reference.getFromAddress()))
|
|
1171
1558
|
.toList();
|
|
1172
1559
|
List<Reference> outgoingReferences = collectReferences(function, "outgoing");
|
|
1173
1560
|
JsonArray incoming = referenceEdges(incomingReferences);
|
|
1174
1561
|
JsonArray outgoing = referenceEdges(outgoingReferences);
|
|
1175
|
-
JsonArray comments = comments(
|
|
1176
|
-
|
|
1177
|
-
JsonArray
|
|
1562
|
+
JsonArray comments = comments(function);
|
|
1563
|
+
Set<Function> callerFunctions = function.getCallingFunctions(monitor);
|
|
1564
|
+
JsonArray callers = procedureIdentities(callerFunctions);
|
|
1565
|
+
Set<Function> calleeFunctions = function.getCalledFunctions(monitor);
|
|
1566
|
+
JsonArray callees = procedureIdentities(calleeFunctions);
|
|
1178
1567
|
JsonArray referencedStrings = referencedStrings(outgoingReferences);
|
|
1179
1568
|
JsonArray referencedNames = referencedNames(outgoingReferences);
|
|
1180
1569
|
JsonArray blocks = basicBlockValues(function);
|
|
@@ -1195,12 +1584,28 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1195
1584
|
result.add("outgoing_references", outgoing);
|
|
1196
1585
|
result.add("referenced_strings", referencedStrings);
|
|
1197
1586
|
result.add("referenced_names", referencedNames);
|
|
1587
|
+
boolean swift = swiftProgram();
|
|
1588
|
+
boolean aarch64 = currentProgram.getLanguageID().getIdAsString().startsWith("AARCH64:");
|
|
1589
|
+
SwiftStringLiteralDecode swiftLiterals = swift && aarch64 ? swiftStringLiterals(function) : null;
|
|
1590
|
+
if (swiftLiterals != null) {
|
|
1591
|
+
result.add("swift_string_literals", swiftLiterals.literals());
|
|
1592
|
+
result.add("swift_string_literal_omissions", swiftLiterals.omissions());
|
|
1593
|
+
}
|
|
1198
1594
|
result.add("basic_blocks", blocks);
|
|
1199
1595
|
result.add(
|
|
1200
1596
|
"native_api",
|
|
1201
1597
|
nativeApiBoundary(function, decompilation)
|
|
1202
1598
|
);
|
|
1203
1599
|
result.add("native_value_flow", nativeValueFlow(decompilation));
|
|
1600
|
+
// Successful full queries distinguish collected empty sets from missing facts.
|
|
1601
|
+
// Availability does not claim that Ghidra resolved every runtime relationship.
|
|
1602
|
+
for (String facet : List.of("comments", "callers", "callees", "references", "strings_names", "cfg")) {
|
|
1603
|
+
availability.add(facet, facetAvailability(true, null));
|
|
1604
|
+
}
|
|
1605
|
+
availability.add("assembly", facetAvailability(
|
|
1606
|
+
!scan.truncated(), "The function instruction scan was truncated."
|
|
1607
|
+
));
|
|
1608
|
+
result.add("facet_availability", availability);
|
|
1204
1609
|
JsonArray limitations = new JsonArray();
|
|
1205
1610
|
limitations.add(
|
|
1206
1611
|
"Unresolved computed or indirect flows without target addresses are not represented as reference edges."
|
|
@@ -1214,8 +1619,24 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1214
1619
|
limitations.add(
|
|
1215
1620
|
"Synthetic Ghidra entry-point references without actionable memory sources are omitted."
|
|
1216
1621
|
);
|
|
1217
|
-
|
|
1218
|
-
|
|
1622
|
+
if (swift && aarch64) {
|
|
1623
|
+
limitations.add(
|
|
1624
|
+
"Swift String literals are decoded from constant register pairs at calls, returns and paired stores. Literals stored one word at a time, chosen by conditional selects, or built at runtime are not reported; candidate pairs at unresolved jumps are retained as unknown omissions."
|
|
1625
|
+
);
|
|
1626
|
+
if (swiftLiterals.omissions().size() > 0) {
|
|
1627
|
+
limitations.add(
|
|
1628
|
+
"Swift String literal records listed in swift_string_literal_omissions could not be retained or decoded within this dossier's remaining heap budget; later symbolic flows remain unexamined."
|
|
1629
|
+
);
|
|
1630
|
+
}
|
|
1631
|
+
} else if (swift) {
|
|
1632
|
+
limitations.add(
|
|
1633
|
+
"Swift String literal decoding is implemented for AArch64 register pairs only; no Swift literals were decoded for this architecture."
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1636
|
+
CallBoundaryObservation calls = callBoundaryObservation(
|
|
1637
|
+
function, scan.instructions, calleeFunctions, true, outgoingReferences);
|
|
1638
|
+
result.add("unresolved_calls", calls.unresolvedCalls());
|
|
1639
|
+
for (String limitation : calls.limitations()) {
|
|
1219
1640
|
limitations.add(limitation);
|
|
1220
1641
|
}
|
|
1221
1642
|
if (decompilation != null && decompilation.getErrorMessage() != null &&
|
|
@@ -1223,7 +1644,14 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1223
1644
|
limitations.add("Ghidra decompiler diagnostic: " + decompilation.getErrorMessage());
|
|
1224
1645
|
}
|
|
1225
1646
|
result.add("limitations", limitations);
|
|
1226
|
-
|
|
1647
|
+
monitor.checkCancelled();
|
|
1648
|
+
int missingCallers = 0;
|
|
1649
|
+
for (Reference reference : bodyIncoming) {
|
|
1650
|
+
monitor.checkCancelled();
|
|
1651
|
+
if (unrepresentedCaller(reference, callerFunctions)) missingCallers++;
|
|
1652
|
+
}
|
|
1653
|
+
return new FunctionAnalysisObservation(result, calls.limitations(),
|
|
1654
|
+
callRelationshipCoverage(calls, missingCallers));
|
|
1227
1655
|
}
|
|
1228
1656
|
|
|
1229
1657
|
private JsonObject nativeValueFlow(DecompileResults decompilation) throws Exception {
|
|
@@ -1548,6 +1976,18 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1548
1976
|
return result;
|
|
1549
1977
|
}
|
|
1550
1978
|
|
|
1979
|
+
private JsonObject binaryInventorySummary(JsonObject params) throws Exception {
|
|
1980
|
+
requireKeys(params, Set.of());
|
|
1981
|
+
JsonObject result = new JsonObject();
|
|
1982
|
+
result.addProperty("document", currentProgram.getName());
|
|
1983
|
+
result.add("segments", segments());
|
|
1984
|
+
// Count the owning inventories, preserving their exact discovery rules
|
|
1985
|
+
// without serializing function identities or string values for counts.
|
|
1986
|
+
result.addProperty("procedure_count", procedures().size());
|
|
1987
|
+
result.addProperty("string_count", strings().size());
|
|
1988
|
+
return result;
|
|
1989
|
+
}
|
|
1990
|
+
|
|
1551
1991
|
private JsonArray listNames(JsonObject params) throws Exception {
|
|
1552
1992
|
requireKeys(params, Set.of("document", "address"));
|
|
1553
1993
|
requireDocument(params);
|
|
@@ -1574,6 +2014,10 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1574
2014
|
private JsonArray listSegments(JsonObject params) {
|
|
1575
2015
|
requireKeys(params, Set.of("document"));
|
|
1576
2016
|
requireDocument(params);
|
|
2017
|
+
return segments();
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
private JsonArray segments() {
|
|
1577
2021
|
JsonArray result = new JsonArray();
|
|
1578
2022
|
String imageBase = canonicalAddress(currentProgram.getImageBase());
|
|
1579
2023
|
MemoryBlock[] blocks = currentProgram.getMemory().getBlocks();
|
|
@@ -1795,14 +2239,25 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1795
2239
|
Address address = explicitAddress ? parseReaAddress(value) : tryParseAddress(value);
|
|
1796
2240
|
if (address == null)
|
|
1797
2241
|
throw new RequestFailure("not_found", "Unknown Ghidra procedure name or address: " + value);
|
|
1798
|
-
Function function =
|
|
1799
|
-
if (function == null && address.isMemoryAddress())
|
|
1800
|
-
function = currentProgram.getFunctionManager().getFunctionContaining(address);
|
|
2242
|
+
Function function = functionAtOrContaining(address);
|
|
1801
2243
|
if (function == null)
|
|
1802
|
-
|
|
2244
|
+
// Other procedure operations retain their analysis-address semantics.
|
|
2245
|
+
throw new RequestFailure("not_found", "No procedure exists at the requested address: " + value +
|
|
2246
|
+
"; Ghidra image base: " + canonicalAddress(currentProgram.getImageBase()) +
|
|
2247
|
+
". Choose an observed analysis address. CLI: rea search <path> . --kind procedures --mode regex --provider ghidra --json; " +
|
|
2248
|
+
"MCP: list_procedures. Inspect the loaded base and source mappings with CLI rea analyze <path> --provider ghidra --json " +
|
|
2249
|
+
"and rea inspect-native-load-image <path> --provider ghidra --json, or MCP binary_overview and inspect_native_load_image. " +
|
|
2250
|
+
"Repeat the original target options. For decompile, select source coordinates explicitly with --file-offset=0x... or MCP procedure file-offset:0x....");
|
|
1803
2251
|
return function;
|
|
1804
2252
|
}
|
|
1805
2253
|
|
|
2254
|
+
private Function functionAtOrContaining(Address address) {
|
|
2255
|
+
Function function = currentProgram.getFunctionManager().getFunctionAt(address);
|
|
2256
|
+
return function == null && address.isMemoryAddress()
|
|
2257
|
+
? currentProgram.getFunctionManager().getFunctionContaining(address)
|
|
2258
|
+
: function;
|
|
2259
|
+
}
|
|
2260
|
+
|
|
1806
2261
|
private JsonObject nativeApiBoundary(
|
|
1807
2262
|
Function function,
|
|
1808
2263
|
DecompileResults decompilation
|
|
@@ -2916,52 +3371,278 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
2916
3371
|
return result;
|
|
2917
3372
|
}
|
|
2918
3373
|
|
|
2919
|
-
private
|
|
3374
|
+
private static JsonObject facetAvailability(boolean available, String reason) {
|
|
3375
|
+
JsonObject result = new JsonObject();
|
|
3376
|
+
result.addProperty("available", available);
|
|
3377
|
+
if (!available) result.addProperty("reason", reason);
|
|
3378
|
+
return result;
|
|
3379
|
+
}
|
|
3380
|
+
|
|
3381
|
+
private JsonObject callRelationshipObservation(JsonElement value, CallBoundaryObservation calls)
|
|
2920
3382
|
throws Exception {
|
|
2921
|
-
|
|
3383
|
+
monitor.checkCancelled();
|
|
3384
|
+
JsonObject result = functionObservation(value, calls.limitations());
|
|
3385
|
+
result.add("relationship_coverage", callRelationshipCoverage(calls, null));
|
|
3386
|
+
return result;
|
|
3387
|
+
}
|
|
3388
|
+
|
|
3389
|
+
private static JsonObject callRelationshipCoverage(
|
|
3390
|
+
CallBoundaryObservation calls, Integer missingCallers) {
|
|
3391
|
+
JsonObject coverage = completeResolvedCallCoverage();
|
|
3392
|
+
Integer omitted = calls == null ? null : calls.unrepresentedCalleeCalls();
|
|
3393
|
+
JsonArray directions = new JsonArray();
|
|
3394
|
+
if (missingCallers != null && missingCallers > 0) directions.add("callers");
|
|
3395
|
+
String callerLimitation = missingCallers != null && missingCallers > 0
|
|
3396
|
+
? "Ghidra's caller inventory omits sources of " + missingCallers +
|
|
3397
|
+
" call reference(s) into this function's body." : null;
|
|
3398
|
+
if ((calls != null && omitted == null) || (calls == null && missingCallers == null)) {
|
|
3399
|
+
coverage.addProperty("status", "unknown");
|
|
3400
|
+
String reason = calls == null ? "No call inventory was examined."
|
|
3401
|
+
: "The callee inventory was not examined alongside decoded call targets.";
|
|
3402
|
+
coverage.addProperty("reason", reason + (callerLimitation == null ? "" : " " + callerLimitation));
|
|
3403
|
+
if (calls == null && missingCallers == null) directions.add("callers");
|
|
3404
|
+
directions.add("callees");
|
|
3405
|
+
coverage.add("limited_directions", directions);
|
|
3406
|
+
return coverage;
|
|
3407
|
+
}
|
|
3408
|
+
JsonArray limitations = new JsonArray();
|
|
3409
|
+
if (callerLimitation != null) limitations.add(callerLimitation);
|
|
3410
|
+
if (omitted != null && omitted > 0) {
|
|
3411
|
+
limitations.add("Ghidra's callee inventory omits targets of " + omitted +
|
|
3412
|
+
" call reference(s) or decoded call(s) without destinations.");
|
|
3413
|
+
directions.add("callees");
|
|
3414
|
+
}
|
|
3415
|
+
if (!limitations.isEmpty()) {
|
|
3416
|
+
coverage.addProperty("status", "partial");
|
|
3417
|
+
coverage.add("limitations", limitations);
|
|
3418
|
+
coverage.add("limited_directions", directions);
|
|
3419
|
+
}
|
|
3420
|
+
return coverage;
|
|
3421
|
+
}
|
|
3422
|
+
|
|
3423
|
+
private static JsonObject completeResolvedCallCoverage() {
|
|
3424
|
+
JsonObject coverage = new JsonObject();
|
|
3425
|
+
coverage.addProperty("status", "complete");
|
|
3426
|
+
JsonArray diagnostics = new JsonArray();
|
|
3427
|
+
diagnostics.add(
|
|
3428
|
+
"Only resolved Ghidra call references are returned; unresolved computed or indirect calls remain unknown, while function classifications distinguish thunks and externals."
|
|
3429
|
+
);
|
|
3430
|
+
coverage.add("diagnostics", diagnostics);
|
|
3431
|
+
return coverage;
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
private boolean unrepresentedCaller(Reference reference, Set<Function> callers) {
|
|
3435
|
+
if (!reference.getReferenceType().isCall()) return false;
|
|
3436
|
+
Function caller = containingFunction(reference.getFromAddress());
|
|
3437
|
+
return caller == null || !callers.contains(caller);
|
|
3438
|
+
}
|
|
3439
|
+
|
|
3440
|
+
private int unrepresentedIncomingCalls(Function function, Set<Function> callers)
|
|
3441
|
+
throws Exception {
|
|
3442
|
+
int[] omitted = { 0 };
|
|
3443
|
+
visitReferences(function, "incoming", reference -> {
|
|
3444
|
+
if (unrepresentedCaller(reference, callers)) omitted[0]++;
|
|
3445
|
+
});
|
|
3446
|
+
return omitted[0];
|
|
3447
|
+
}
|
|
3448
|
+
|
|
3449
|
+
private List<String> functionBoundaryLimitations(
|
|
3450
|
+
Function function, Iterable<Instruction> instructions)
|
|
3451
|
+
throws Exception {
|
|
3452
|
+
FunctionBoundaryLimitations boundary = new FunctionBoundaryLimitations(function);
|
|
3453
|
+
for (Instruction instruction : instructions) boundary.observe(instruction);
|
|
3454
|
+
return boundary.values();
|
|
3455
|
+
}
|
|
3456
|
+
|
|
3457
|
+
private CallBoundaryObservation callBoundaryObservation(
|
|
3458
|
+
Function function, Iterable<Instruction> instructions, Set<Function> returnedCallees,
|
|
3459
|
+
boolean includeUnresolvedSites, List<Reference> observedReferences)
|
|
3460
|
+
throws Exception {
|
|
3461
|
+
FunctionBoundaryLimitations boundary = new FunctionBoundaryLimitations(function);
|
|
3462
|
+
CallBoundaryReferences calls = new CallBoundaryReferences(returnedCallees, includeUnresolvedSites);
|
|
3463
|
+
if (observedReferences == null) visitReferences(function, "outgoing", calls::observe);
|
|
3464
|
+
else for (Reference reference : observedReferences) {
|
|
3465
|
+
monitor.checkCancelled();
|
|
3466
|
+
calls.observe(reference);
|
|
3467
|
+
}
|
|
2922
3468
|
for (Instruction instruction : instructions) {
|
|
3469
|
+
boundary.observe(instruction);
|
|
3470
|
+
if (!instruction.getFlowType().isCall()) continue;
|
|
3471
|
+
boolean destination = false;
|
|
3472
|
+
for (Reference reference : instruction.getReferencesFrom()) {
|
|
3473
|
+
if (!reference.getReferenceType().isCall()) continue;
|
|
3474
|
+
destination = true;
|
|
3475
|
+
break;
|
|
3476
|
+
}
|
|
3477
|
+
if (!destination) {
|
|
3478
|
+
calls.unrepresented++;
|
|
3479
|
+
calls.unresolved(instruction.getAddress(),
|
|
3480
|
+
"Instruction decoder identifies a call but ReferenceManager supplies no call destination");
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
return new CallBoundaryObservation(boundary.values(),
|
|
3484
|
+
returnedCallees == null ? null : calls.unrepresented, calls.unresolvedCalls());
|
|
3485
|
+
}
|
|
3486
|
+
|
|
3487
|
+
private final class FunctionBoundaryLimitations {
|
|
3488
|
+
private final Function function;
|
|
3489
|
+
private final List<String> limitations = new ArrayList<>();
|
|
3490
|
+
private Instruction beforePrevious;
|
|
3491
|
+
private Instruction previous;
|
|
3492
|
+
|
|
3493
|
+
private FunctionBoundaryLimitations(Function function) {
|
|
3494
|
+
this.function = function;
|
|
3495
|
+
}
|
|
3496
|
+
|
|
3497
|
+
private void observe(Instruction instruction) throws Exception {
|
|
2923
3498
|
monitor.checkCancelled();
|
|
2924
|
-
|
|
2925
|
-
|
|
3499
|
+
String limitation = terminalCallLimitation(instruction);
|
|
3500
|
+
if (limitation != null) limitations.add(limitation);
|
|
3501
|
+
if (beforePrevious != null && previous != null) {
|
|
3502
|
+
String seh = borlandSehHandlerLimitation(
|
|
3503
|
+
function, beforePrevious, previous, instruction);
|
|
3504
|
+
if (seh != null) limitations.add(seh);
|
|
2926
3505
|
}
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
3506
|
+
beforePrevious = previous;
|
|
3507
|
+
previous = instruction;
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
private List<String> values() {
|
|
3511
|
+
return List.copyOf(limitations);
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
|
|
3515
|
+
private String borlandSehHandlerLimitation(
|
|
3516
|
+
Function function, Instruction handlerPush, Instruction framePush,
|
|
3517
|
+
Instruction frameLink) {
|
|
3518
|
+
if (!immediatelyPrecedes(handlerPush, framePush) ||
|
|
3519
|
+
!immediatelyPrecedes(framePush, frameLink) ||
|
|
3520
|
+
!handlerPush.getMnemonicString().equalsIgnoreCase("PUSH") ||
|
|
3521
|
+
handlerPush.getNumOperands() != 1 ||
|
|
3522
|
+
!framePush.getMnemonicString().equalsIgnoreCase("PUSH") ||
|
|
3523
|
+
framePush.getNumOperands() != 1 ||
|
|
3524
|
+
!frameLink.getMnemonicString().equalsIgnoreCase("MOV") ||
|
|
3525
|
+
frameLink.getNumOperands() != 2 ||
|
|
3526
|
+
!sameFsMemoryOperand(framePush, frameLink) ||
|
|
3527
|
+
!hasRegisterOperand(frameLink, 1, "ESP"))
|
|
3528
|
+
return null;
|
|
3529
|
+
Object[] handlerOperand = handlerPush.getOpObjects(0);
|
|
3530
|
+
if (handlerOperand.length != 1 || !(handlerOperand[0] instanceof Scalar scalar) ||
|
|
3531
|
+
scalar.bitLength() != 32)
|
|
3532
|
+
return null;
|
|
3533
|
+
Address handler = currentProgram.getAddressFactory().getDefaultAddressSpace()
|
|
3534
|
+
.getAddress(scalar.getUnsignedValue());
|
|
3535
|
+
if (function.getBody().contains(handler)) return null;
|
|
3536
|
+
return "Ghidra Listing shows a Borland/Delphi-style SEH frame registration at " +
|
|
3537
|
+
canonicalAddress(frameLink.getAddress()) + " (push " + canonicalAddress(handler) +
|
|
3538
|
+
" followed by fs-segment stack chaining); handler " + canonicalAddress(handler) +
|
|
3539
|
+
" lies outside this procedure's body, so callees, strings, and cross-references may omit the handler region.";
|
|
3540
|
+
}
|
|
3541
|
+
|
|
3542
|
+
private static boolean immediatelyPrecedes(Instruction first, Instruction second) {
|
|
3543
|
+
Address fallThrough = first.getFallThrough();
|
|
3544
|
+
return fallThrough != null && fallThrough.equals(second.getAddress());
|
|
3545
|
+
}
|
|
3546
|
+
|
|
3547
|
+
private static boolean sameFsMemoryOperand(Instruction first, Instruction second) {
|
|
3548
|
+
String firstOperand = normalizedFsMemoryOperand(first);
|
|
3549
|
+
String secondOperand = normalizedFsMemoryOperand(second);
|
|
3550
|
+
return firstOperand != null && firstOperand.equalsIgnoreCase(secondOperand);
|
|
3551
|
+
}
|
|
3552
|
+
|
|
3553
|
+
private static String normalizedFsMemoryOperand(Instruction instruction) {
|
|
3554
|
+
String representation = instruction.getDefaultOperandRepresentation(0);
|
|
3555
|
+
representation = representation.replaceAll("(?i)\\b(?:byte|word|dword|qword)\\s+ptr\\s+", "")
|
|
3556
|
+
.replaceAll("\\s+", "");
|
|
3557
|
+
return representation.regionMatches(true, 0, "fs:", 0, 3) &&
|
|
3558
|
+
representation.indexOf('[') >= 0 ? representation : null;
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3561
|
+
private static boolean hasRegisterOperand(
|
|
3562
|
+
Instruction instruction, int operand, String name) {
|
|
3563
|
+
for (Object object : instruction.getOpObjects(operand)) {
|
|
3564
|
+
if (object instanceof Register register && register.getName().equalsIgnoreCase(name))
|
|
3565
|
+
return true;
|
|
3566
|
+
}
|
|
3567
|
+
return false;
|
|
3568
|
+
}
|
|
3569
|
+
|
|
3570
|
+
private final class CallBoundaryReferences {
|
|
3571
|
+
private final Set<Function> returnedCallees;
|
|
3572
|
+
private final TreeMap<Address, String> unresolved;
|
|
3573
|
+
private int unrepresented;
|
|
3574
|
+
|
|
3575
|
+
CallBoundaryReferences(Set<Function> returnedCallees, boolean includeUnresolvedSites) {
|
|
3576
|
+
this.returnedCallees = returnedCallees;
|
|
3577
|
+
unresolved = includeUnresolvedSites ? new TreeMap<>() : null;
|
|
3578
|
+
}
|
|
3579
|
+
|
|
3580
|
+
void observe(Reference reference) {
|
|
3581
|
+
if (!reference.getReferenceType().isCall()) return;
|
|
3582
|
+
// Reference identity follows the same containing-function owner as referenceEdge.
|
|
3583
|
+
Function target = containingFunction(reference.getToAddress());
|
|
3584
|
+
if (returnedCallees != null && (target == null || !returnedCallees.contains(target)))
|
|
3585
|
+
unrepresented++;
|
|
3586
|
+
if (target == null) unresolved(reference.getFromAddress(),
|
|
3587
|
+
"A call destination has no known containing Ghidra procedure");
|
|
3588
|
+
}
|
|
3589
|
+
|
|
3590
|
+
void unresolved(Address address, String reason) {
|
|
3591
|
+
if (unresolved != null) unresolved.put(address, reason);
|
|
3592
|
+
}
|
|
3593
|
+
|
|
3594
|
+
JsonArray unresolvedCalls() {
|
|
3595
|
+
if (unresolved == null) return null;
|
|
3596
|
+
JsonArray result = new JsonArray();
|
|
3597
|
+
for (var item : unresolved.entrySet()) {
|
|
3598
|
+
JsonObject site = new JsonObject();
|
|
3599
|
+
site.addProperty("address", canonicalAddress(item.getKey()));
|
|
3600
|
+
site.addProperty("reason", item.getValue());
|
|
3601
|
+
result.add(site);
|
|
2933
3602
|
}
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
limitation.append("
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
if (target
|
|
2956
|
-
limitation.append("
|
|
3603
|
+
return result;
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
|
|
3607
|
+
private String terminalCallLimitation(Instruction instruction) {
|
|
3608
|
+
if (!instruction.getFlowType().isCall() || !instruction.getFlowType().isTerminal())
|
|
3609
|
+
return null;
|
|
3610
|
+
Address[] destinations = instruction.getFlows();
|
|
3611
|
+
StringBuilder limitation = new StringBuilder();
|
|
3612
|
+
limitation.append("Ghidra Listing reports a terminal call at ")
|
|
3613
|
+
.append(canonicalAddress(instruction.getAddress()));
|
|
3614
|
+
if (destinations.length == 0) {
|
|
3615
|
+
limitation.append(" with no resolved callee; its no-return basis is unknown.");
|
|
3616
|
+
}
|
|
3617
|
+
else {
|
|
3618
|
+
limitation.append(" to ");
|
|
3619
|
+
for (int index = 0; index < destinations.length; index++) {
|
|
3620
|
+
if (index > 0) limitation.append(", ");
|
|
3621
|
+
Address destination = destinations[index];
|
|
3622
|
+
limitation.append(canonicalAddress(destination));
|
|
3623
|
+
Function target = currentProgram.getFunctionManager().getFunctionAt(destination);
|
|
3624
|
+
if (target == null) {
|
|
3625
|
+
limitation.append(" (callee identity unknown)");
|
|
2957
3626
|
}
|
|
2958
3627
|
else {
|
|
2959
|
-
limitation.append("
|
|
3628
|
+
limitation.append(" ").append(procedureName(target));
|
|
3629
|
+
limitation.append(" (external=").append(target.isExternal());
|
|
3630
|
+
limitation.append(", thunk=").append(target.isThunk());
|
|
3631
|
+
limitation.append(", hasNoReturn=").append(target.hasNoReturn()).append(")");
|
|
2960
3632
|
}
|
|
2961
3633
|
}
|
|
2962
|
-
|
|
3634
|
+
limitation.append("; fallthrough is excluded by Ghidra's flow model.");
|
|
3635
|
+
Function target = destinations.length == 1
|
|
3636
|
+
? currentProgram.getFunctionManager().getFunctionAt(destinations[0])
|
|
3637
|
+
: null;
|
|
3638
|
+
if (target != null && target.hasNoReturn()) {
|
|
3639
|
+
limitation.append(" This records Ghidra's FunctionManager flag, not an independent verification that the callee cannot return.");
|
|
3640
|
+
}
|
|
3641
|
+
else {
|
|
3642
|
+
limitation.append(" The reason for the terminal flow is not established by this observation.");
|
|
3643
|
+
}
|
|
2963
3644
|
}
|
|
2964
|
-
return
|
|
3645
|
+
return limitation.toString();
|
|
2965
3646
|
}
|
|
2966
3647
|
|
|
2967
3648
|
private static String renderAssembly(List<Instruction> instructions) {
|
|
@@ -2987,43 +3668,62 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
2987
3668
|
private List<Reference> collectReferences(
|
|
2988
3669
|
Function function,
|
|
2989
3670
|
String direction) throws Exception {
|
|
3671
|
+
TreeMap<String, Reference> observed = new TreeMap<>();
|
|
3672
|
+
visitReferences(function, direction, reference -> addReference(observed, reference));
|
|
3673
|
+
List<Reference> result = new ArrayList<>(observed.values());
|
|
3674
|
+
result.sort(REFERENCE_ORDER);
|
|
3675
|
+
return result;
|
|
3676
|
+
}
|
|
3677
|
+
|
|
3678
|
+
@FunctionalInterface
|
|
3679
|
+
private interface ReferenceVisitor {
|
|
3680
|
+
void accept(Reference reference) throws Exception;
|
|
3681
|
+
}
|
|
3682
|
+
|
|
3683
|
+
private void visitReferences(Function function, String direction, ReferenceVisitor visitor)
|
|
3684
|
+
throws Exception {
|
|
2990
3685
|
// References can target instruction interiors or originate in embedded
|
|
2991
3686
|
// data. Use actual body ownership, including an external's exact entry.
|
|
2992
|
-
AddressSet scope =
|
|
2993
|
-
scope.add(function.getEntryPoint());
|
|
3687
|
+
AddressSet scope = functionObservationScope(function);
|
|
2994
3688
|
boolean outgoing = direction.equals("outgoing");
|
|
2995
3689
|
AddressIterator addresses = outgoing
|
|
2996
3690
|
? currentProgram.getReferenceManager().getReferenceSourceIterator(scope, true)
|
|
2997
3691
|
: currentProgram.getReferenceManager().getReferenceDestinationIterator(scope, true);
|
|
2998
|
-
TreeMap<String, Reference> observed = new TreeMap<>();
|
|
2999
3692
|
while (addresses.hasNext()) {
|
|
3000
3693
|
monitor.checkCancelled();
|
|
3001
3694
|
Address address = addresses.next();
|
|
3002
3695
|
if (outgoing) {
|
|
3003
|
-
|
|
3004
|
-
.getReferencesFrom(address)) {
|
|
3005
|
-
monitor.checkCancelled();
|
|
3006
|
-
addReference(observed, reference);
|
|
3007
|
-
}
|
|
3696
|
+
visitObservedReferencesFrom(address, visitor);
|
|
3008
3697
|
}
|
|
3009
3698
|
else {
|
|
3010
|
-
|
|
3011
|
-
.getReferencesTo(address);
|
|
3012
|
-
while (iterator.hasNext()) {
|
|
3013
|
-
monitor.checkCancelled();
|
|
3014
|
-
addReference(observed, iterator.next());
|
|
3015
|
-
}
|
|
3699
|
+
visitObservedReferencesTo(address, visitor);
|
|
3016
3700
|
}
|
|
3017
3701
|
}
|
|
3018
|
-
List<Reference> result = new ArrayList<>(observed.values());
|
|
3019
|
-
result.sort(REFERENCE_ORDER);
|
|
3020
|
-
return result;
|
|
3021
3702
|
}
|
|
3022
3703
|
|
|
3023
|
-
private
|
|
3024
|
-
|
|
3025
|
-
|
|
3704
|
+
private void visitObservedReferencesFrom(Address address, ReferenceVisitor visitor)
|
|
3705
|
+
throws Exception {
|
|
3706
|
+
for (Reference reference : currentProgram.getReferenceManager().getReferencesFrom(address)) {
|
|
3707
|
+
monitor.checkCancelled();
|
|
3708
|
+
visitObservedReference(reference, visitor);
|
|
3026
3709
|
}
|
|
3710
|
+
}
|
|
3711
|
+
|
|
3712
|
+
private void visitObservedReferencesTo(Address address, ReferenceVisitor visitor)
|
|
3713
|
+
throws Exception {
|
|
3714
|
+
ReferenceIterator references = currentProgram.getReferenceManager().getReferencesTo(address);
|
|
3715
|
+
while (references.hasNext()) {
|
|
3716
|
+
monitor.checkCancelled();
|
|
3717
|
+
visitObservedReference(references.next(), visitor);
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
3720
|
+
|
|
3721
|
+
private static void visitObservedReference(Reference reference, ReferenceVisitor visitor)
|
|
3722
|
+
throws Exception {
|
|
3723
|
+
if (!reference.isEntryPointReference()) visitor.accept(reference);
|
|
3724
|
+
}
|
|
3725
|
+
|
|
3726
|
+
private static void addReference(TreeMap<String, Reference> observed, Reference reference) {
|
|
3027
3727
|
String key = canonicalAddress(reference.getFromAddress()) + "\u0000" +
|
|
3028
3728
|
canonicalAddress(reference.getToAddress()) + "\u0000" +
|
|
3029
3729
|
reference.getReferenceType().getName() + "\u0000" +
|
|
@@ -3032,6 +3732,12 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
3032
3732
|
observed.putIfAbsent(key, reference);
|
|
3033
3733
|
}
|
|
3034
3734
|
|
|
3735
|
+
private static AddressSet functionObservationScope(Function function) {
|
|
3736
|
+
AddressSet scope = new AddressSet(function.getBody());
|
|
3737
|
+
scope.add(function.getEntryPoint());
|
|
3738
|
+
return scope;
|
|
3739
|
+
}
|
|
3740
|
+
|
|
3035
3741
|
private JsonArray referenceEdges(List<Reference> references) {
|
|
3036
3742
|
JsonArray result = new JsonArray();
|
|
3037
3743
|
for (Reference reference : references) {
|
|
@@ -3185,23 +3891,28 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
3185
3891
|
return result;
|
|
3186
3892
|
}
|
|
3187
3893
|
|
|
3188
|
-
private
|
|
3894
|
+
private JsonArray comments(Function function) throws Exception {
|
|
3895
|
+
Listing listing = currentProgram.getListing();
|
|
3896
|
+
AddressSet scope = functionObservationScope(function);
|
|
3897
|
+
AddressIterator addresses = listing.getCommentAddressIterator(scope, true);
|
|
3189
3898
|
TreeMap<String, JsonObject> observed = new TreeMap<>();
|
|
3190
|
-
|
|
3899
|
+
while (addresses.hasNext()) {
|
|
3900
|
+
monitor.checkCancelled();
|
|
3901
|
+
Address address = addresses.next();
|
|
3191
3902
|
for (CommentType type : CommentType.values()) {
|
|
3192
|
-
String text =
|
|
3903
|
+
String text = listing.getComment(type, address);
|
|
3193
3904
|
if (text == null || text.isEmpty()) {
|
|
3194
3905
|
continue;
|
|
3195
3906
|
}
|
|
3196
3907
|
String kind = type == CommentType.EOL ? "inline" : "comment";
|
|
3197
3908
|
JsonObject item = new JsonObject();
|
|
3198
|
-
item.addProperty("address", canonicalAddress(
|
|
3909
|
+
item.addProperty("address", canonicalAddress(address));
|
|
3199
3910
|
item.addProperty("kind", kind);
|
|
3200
3911
|
item.addProperty("text", text);
|
|
3201
|
-
String key = canonicalAddress(
|
|
3912
|
+
String key = canonicalAddress(address) + "\u0000" +
|
|
3202
3913
|
kind + "\u0000" + type.name() + "\u0000" + text;
|
|
3203
3914
|
observed.put(key, item);
|
|
3204
|
-
|
|
3915
|
+
}
|
|
3205
3916
|
}
|
|
3206
3917
|
JsonArray result = new JsonArray();
|
|
3207
3918
|
observed.values().forEach(result::add);
|
|
@@ -3256,6 +3967,376 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
3256
3967
|
return result;
|
|
3257
3968
|
}
|
|
3258
3969
|
|
|
3970
|
+
private boolean swiftProgram() {
|
|
3971
|
+
for (MemoryBlock block : currentProgram.getMemory().getBlocks()) {
|
|
3972
|
+
String name = block.getName();
|
|
3973
|
+
if (name.startsWith("__swift5_") || name.startsWith("swift5_")) return true;
|
|
3974
|
+
}
|
|
3975
|
+
return false;
|
|
3976
|
+
}
|
|
3977
|
+
|
|
3978
|
+
/**
|
|
3979
|
+
* Swift passes a String as two words: small literals carry their bytes in the words and
|
|
3980
|
+
* immortal large literals carry their count and a biased pointer to the bytes. Ghidra keeps
|
|
3981
|
+
* neither as a data reference, so decode constant pairs where Swift consumes them: argument
|
|
3982
|
+
* and return registers at calls, tail calls and returns, and both registers of one STP.
|
|
3983
|
+
* The canonical empty string is a small literal with a zero count.
|
|
3984
|
+
*/
|
|
3985
|
+
private SwiftStringLiteralDecode swiftStringLiterals(Function function) throws Exception {
|
|
3986
|
+
return swiftStringLiterals(function, new SwiftLiteralBudget());
|
|
3987
|
+
}
|
|
3988
|
+
|
|
3989
|
+
// An explicit budget makes capacity omissions deterministic in producer tests.
|
|
3990
|
+
private SwiftStringLiteralDecode swiftStringLiterals(
|
|
3991
|
+
Function function,
|
|
3992
|
+
SwiftLiteralBudget budget
|
|
3993
|
+
) throws Exception {
|
|
3994
|
+
Register[] registers = new Register[31];
|
|
3995
|
+
for (int index = 0; index < registers.length; index++) {
|
|
3996
|
+
registers[index] = currentProgram.getRegister("x" + index);
|
|
3997
|
+
}
|
|
3998
|
+
TreeMap<String, JsonObject> observed = new TreeMap<>();
|
|
3999
|
+
TreeMap<String, JsonObject> omitted = new TreeMap<>();
|
|
4000
|
+
Map<String, Boolean> selectedValues = new HashMap<>();
|
|
4001
|
+
SymbolicPropogator propagator = new SymbolicPropogator(currentProgram, false);
|
|
4002
|
+
propagator.flowConstants(function.getEntryPoint(), function.getBody(), new ContextEvaluatorAdapter() {
|
|
4003
|
+
@Override
|
|
4004
|
+
public boolean evaluateContextBefore(VarnodeContext context, Instruction instruction) {
|
|
4005
|
+
// Returning true ends only the current flow, so every queued flow checks the shared stop.
|
|
4006
|
+
if (budget.stopped()) return true;
|
|
4007
|
+
FlowType flow = instruction.getFlowType();
|
|
4008
|
+
Address[] flowTargets = instruction.getFlows();
|
|
4009
|
+
boolean unresolvedJump = flow.isJump() && !flow.isConditional() && flowTargets.length == 0;
|
|
4010
|
+
for (Register[] pair : swiftStringPairs(function, instruction, registers)) {
|
|
4011
|
+
Long word = registerConstant(context, pair[0]);
|
|
4012
|
+
Long object = registerConstant(context, pair[1]);
|
|
4013
|
+
if (word == null || object == null) continue;
|
|
4014
|
+
SwiftLiteralLayout layout = swiftLiteralLayout(word, object);
|
|
4015
|
+
if (layout == null) continue;
|
|
4016
|
+
// A selected word can combine with a path-dependent ordinary move. Cache the
|
|
4017
|
+
// provenance question per site/register, charging retained cache state to the
|
|
4018
|
+
// same dossier budget before allocating it.
|
|
4019
|
+
boolean selected = false;
|
|
4020
|
+
boolean provenanceOverCapacity = false;
|
|
4021
|
+
for (Register register : pair) {
|
|
4022
|
+
String provenanceKey = canonicalAddress(instruction.getAddress()) + "\u0000" +
|
|
4023
|
+
register.getBaseRegister().getName();
|
|
4024
|
+
Boolean value = selectedValues.get(provenanceKey);
|
|
4025
|
+
if (value == null) {
|
|
4026
|
+
if (!budget.takeState()) {
|
|
4027
|
+
provenanceOverCapacity = true;
|
|
4028
|
+
break;
|
|
4029
|
+
}
|
|
4030
|
+
value = selectedValue(function, instruction, register);
|
|
4031
|
+
selectedValues.put(provenanceKey, value);
|
|
4032
|
+
}
|
|
4033
|
+
if (value) {
|
|
4034
|
+
selected = true;
|
|
4035
|
+
break;
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
if (selected) continue;
|
|
4039
|
+
// Forks can reach one site with different constants, so the words are part of the key.
|
|
4040
|
+
String key = canonicalAddress(instruction.getAddress()) + "\u0000" + pair[0].getName() +
|
|
4041
|
+
"\u0000" + pair[1].getName() + "\u0000" + Long.toUnsignedString(word, 16) +
|
|
4042
|
+
"\u0000" + Long.toUnsignedString(object, 16);
|
|
4043
|
+
if (observed.containsKey(key) || omitted.containsKey(key)) continue;
|
|
4044
|
+
// Every record draws on the budget; the first one that does not fit is kept as an
|
|
4045
|
+
// omission and decoding stops, so later sites are never examined.
|
|
4046
|
+
String value = layout.smallValue();
|
|
4047
|
+
boolean overCapacity = provenanceOverCapacity || !budget.take(layout.byteLength());
|
|
4048
|
+
if (!overCapacity && value == null) {
|
|
4049
|
+
try {
|
|
4050
|
+
value = swiftLargeLiteralText(layout);
|
|
4051
|
+
} catch (OutOfMemoryError exhausted) {
|
|
4052
|
+
overCapacity = true;
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
4055
|
+
if (value == null && !overCapacity) continue;
|
|
4056
|
+
JsonObject item = overCapacity
|
|
4057
|
+
? swiftStringOmission(layout, word, object)
|
|
4058
|
+
: swiftStringItem(value, layout, word, object);
|
|
4059
|
+
if (unresolvedJump && !overCapacity)
|
|
4060
|
+
item = swiftStringOmission(layout, word, object, "unresolved_jump");
|
|
4061
|
+
item.addProperty("source_address", canonicalAddress(instruction.getAddress()));
|
|
4062
|
+
JsonArray pairRegisters = new JsonArray();
|
|
4063
|
+
pairRegisters.add(pair[0].getName());
|
|
4064
|
+
pairRegisters.add(pair[1].getName());
|
|
4065
|
+
item.add("registers", pairRegisters);
|
|
4066
|
+
(overCapacity || unresolvedJump ? omitted : observed).put(key, item);
|
|
4067
|
+
if (overCapacity) {
|
|
4068
|
+
budget.stop();
|
|
4069
|
+
return true;
|
|
4070
|
+
}
|
|
4071
|
+
}
|
|
4072
|
+
return false;
|
|
4073
|
+
}
|
|
4074
|
+
}, false, monitor);
|
|
4075
|
+
JsonArray literals = new JsonArray();
|
|
4076
|
+
observed.values().forEach(literals::add);
|
|
4077
|
+
JsonArray omissions = new JsonArray();
|
|
4078
|
+
omitted.values().forEach(omissions::add);
|
|
4079
|
+
return new SwiftStringLiteralDecode(literals, omissions);
|
|
4080
|
+
}
|
|
4081
|
+
|
|
4082
|
+
private static List<Register[]> swiftStringPairs(
|
|
4083
|
+
Function function,
|
|
4084
|
+
Instruction instruction,
|
|
4085
|
+
Register[] registers
|
|
4086
|
+
) {
|
|
4087
|
+
List<Register[]> pairs = new ArrayList<>();
|
|
4088
|
+
if (instruction.getMnemonicString().equals("stp")) {
|
|
4089
|
+
Register first = instruction.getRegister(0);
|
|
4090
|
+
Register second = instruction.getRegister(1);
|
|
4091
|
+
if (first != null && second != null && first.getBitLength() == 64 && second.getBitLength() == 64) {
|
|
4092
|
+
pairs.add(new Register[] {first, second});
|
|
4093
|
+
}
|
|
4094
|
+
return pairs;
|
|
4095
|
+
}
|
|
4096
|
+
FlowType flow = instruction.getFlowType();
|
|
4097
|
+
boolean returns = false;
|
|
4098
|
+
for (PcodeOp operation : instruction.getPcode()) {
|
|
4099
|
+
if (operation.getOpcode() == PcodeOp.RETURN) returns = true;
|
|
4100
|
+
}
|
|
4101
|
+
// A jump is a proven tail call only when it has resolved targets and all leave the
|
|
4102
|
+
// body. For unresolved targetless jumps, candidate literals remain unknown omissions.
|
|
4103
|
+
Address[] targets = instruction.getFlows();
|
|
4104
|
+
boolean tailCall = flow.isJump() && !flow.isConditional() && targets.length > 0 &&
|
|
4105
|
+
Arrays.stream(targets).allMatch(target -> !function.getBody().contains(target));
|
|
4106
|
+
boolean unresolvedJump = flow.isJump() && !flow.isConditional() && targets.length == 0;
|
|
4107
|
+
if (!flow.isCall() && !returns && !tailCall && !unresolvedJump) return pairs;
|
|
4108
|
+
// A String occupies two consecutive registers among x0-x7, or x0 and x1 when returned.
|
|
4109
|
+
int lastFirstRegister = returns ? 0 : 6;
|
|
4110
|
+
for (int index = 0; index <= lastFirstRegister; index++) {
|
|
4111
|
+
pairs.add(new Register[] {registers[index], registers[index + 1]});
|
|
4112
|
+
}
|
|
4113
|
+
return pairs;
|
|
4114
|
+
}
|
|
4115
|
+
|
|
4116
|
+
private static Long registerConstant(VarnodeContext context, Register register) {
|
|
4117
|
+
Varnode value = context.getRegisterVarnodeValue(register);
|
|
4118
|
+
return value != null && context.isConstant(value) ? value.getOffset() : null;
|
|
4119
|
+
}
|
|
4120
|
+
|
|
4121
|
+
// Search every predecessor path for the reaching definitions, following register copies,
|
|
4122
|
+
// since a select copied into an argument register or defined before a branch forks just as
|
|
4123
|
+
// independently as one written there directly.
|
|
4124
|
+
private boolean selectedValue(Function function, Instruction use, Register register) {
|
|
4125
|
+
ArrayDeque<Instruction> instructions = new ArrayDeque<>();
|
|
4126
|
+
ArrayDeque<Register> targets = new ArrayDeque<>();
|
|
4127
|
+
Set<String> visited = new HashSet<>();
|
|
4128
|
+
for (Instruction predecessor : predecessors(function, use)) {
|
|
4129
|
+
instructions.push(predecessor);
|
|
4130
|
+
targets.push(register.getBaseRegister());
|
|
4131
|
+
}
|
|
4132
|
+
while (!instructions.isEmpty()) {
|
|
4133
|
+
Instruction instruction = instructions.pop();
|
|
4134
|
+
Register target = targets.pop();
|
|
4135
|
+
if (!visited.add(canonicalAddress(instruction.getAddress()) + "\u0000" + target.getName())) continue;
|
|
4136
|
+
boolean defines = false;
|
|
4137
|
+
for (Object result : instruction.getResultObjects()) {
|
|
4138
|
+
if (result instanceof Register written && written.getBaseRegister().equals(target)) defines = true;
|
|
4139
|
+
}
|
|
4140
|
+
Register next = target;
|
|
4141
|
+
if (defines) {
|
|
4142
|
+
PcodeOp[] operations = instruction.getPcode();
|
|
4143
|
+
for (PcodeOp operation : operations) {
|
|
4144
|
+
if (operation.getOpcode() == PcodeOp.CBRANCH && operation.getInput(0).isConstant()) return true;
|
|
4145
|
+
}
|
|
4146
|
+
Register source = copiedRegister(operations);
|
|
4147
|
+
if (source == null) continue;
|
|
4148
|
+
next = source.getBaseRegister();
|
|
4149
|
+
}
|
|
4150
|
+
for (Instruction predecessor : predecessors(function, instruction)) {
|
|
4151
|
+
instructions.push(predecessor);
|
|
4152
|
+
targets.push(next);
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
return false;
|
|
4156
|
+
}
|
|
4157
|
+
|
|
4158
|
+
private List<Instruction> predecessors(Function function, Instruction instruction) {
|
|
4159
|
+
List<Instruction> result = new ArrayList<>();
|
|
4160
|
+
Address from = instruction.getFallFrom();
|
|
4161
|
+
if (from != null) {
|
|
4162
|
+
Instruction previous = currentProgram.getListing().getInstructionAt(from);
|
|
4163
|
+
if (previous != null) result.add(previous);
|
|
4164
|
+
}
|
|
4165
|
+
for (Reference reference : currentProgram.getReferenceManager().getReferencesTo(instruction.getAddress())) {
|
|
4166
|
+
if (!reference.getReferenceType().isFlow() || reference.getReferenceType().isCall()) continue;
|
|
4167
|
+
if (!function.getBody().contains(reference.getFromAddress())) continue;
|
|
4168
|
+
Instruction source = currentProgram.getListing().getInstructionAt(reference.getFromAddress());
|
|
4169
|
+
if (source != null) result.add(source);
|
|
4170
|
+
}
|
|
4171
|
+
return result;
|
|
4172
|
+
}
|
|
4173
|
+
|
|
4174
|
+
private Register copiedRegister(PcodeOp[] operations) {
|
|
4175
|
+
if (operations.length != 1) return null;
|
|
4176
|
+
int opcode = operations[0].getOpcode();
|
|
4177
|
+
Varnode input = operations[0].getInput(0);
|
|
4178
|
+
if ((opcode != PcodeOp.COPY && opcode != PcodeOp.INT_ZEXT) || input == null || !input.isRegister()) return null;
|
|
4179
|
+
return currentProgram.getRegister(input);
|
|
4180
|
+
}
|
|
4181
|
+
|
|
4182
|
+
/** Validate the ABI layout of a pair; a small literal is decoded here, a large one only located. */
|
|
4183
|
+
private SwiftLiteralLayout swiftLiteralLayout(long word, long object) {
|
|
4184
|
+
int discriminator = (int) (object >>> 60);
|
|
4185
|
+
if (discriminator == 0xE || discriminator == 0xA) {
|
|
4186
|
+
int count = (int) ((object >>> 56) & 0xF);
|
|
4187
|
+
byte[] bytes = new byte[15];
|
|
4188
|
+
for (int index = 0; index < 8; index++) bytes[index] = (byte) (word >>> (8 * index));
|
|
4189
|
+
for (int index = 0; index < 7; index++) bytes[8 + index] = (byte) (object >>> (8 * index));
|
|
4190
|
+
for (int index = count; index < bytes.length; index++) {
|
|
4191
|
+
if (bytes[index] != 0) return null;
|
|
4192
|
+
}
|
|
4193
|
+
// Count zero is the canonical empty string (object 0xE000000000000000, word 0).
|
|
4194
|
+
String value = swiftStringText(bytes, count, discriminator == 0xE);
|
|
4195
|
+
return value == null ? null : new SwiftLiteralLayout("small", null, count, true, value);
|
|
4196
|
+
}
|
|
4197
|
+
int flags = (int) (word >>> 60);
|
|
4198
|
+
long count = word & 0xFFFFFFFFFFFFL;
|
|
4199
|
+
// Immortal literals: ASCII and NFC or neither, tail allocated, with a pointer biased by 32.
|
|
4200
|
+
if ((object >>> 56) != 0x80 || (flags != 0xD && flags != 0x1) || ((word >>> 48) & 0xFFF) != 0) {
|
|
4201
|
+
return null;
|
|
4202
|
+
}
|
|
4203
|
+
try {
|
|
4204
|
+
Address address = currentProgram.getAddressFactory().getDefaultAddressSpace()
|
|
4205
|
+
.getAddress((object & 0x00FFFFFFFFFFFFFFL) + 0x20);
|
|
4206
|
+
MemoryBlock block = currentProgram.getMemory().getBlock(address);
|
|
4207
|
+
// The bytes and their terminator must lie in one initialized, non-executable block,
|
|
4208
|
+
// and Java arrays bound one read.
|
|
4209
|
+
if (block == null || !block.isInitialized() || block.isExecute() ||
|
|
4210
|
+
count >= block.getEnd().subtract(address) + 1 || count >= Integer.MAX_VALUE) {
|
|
4211
|
+
return null;
|
|
4212
|
+
}
|
|
4213
|
+
return new SwiftLiteralLayout("large", address, count, flags == 0xD, null);
|
|
4214
|
+
} catch (Exception unaddressable) {
|
|
4215
|
+
return null;
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
|
|
4219
|
+
private String swiftLargeLiteralText(SwiftLiteralLayout layout) {
|
|
4220
|
+
int count = (int) layout.byteLength();
|
|
4221
|
+
byte[] bytes = new byte[count + 1];
|
|
4222
|
+
try {
|
|
4223
|
+
if (currentProgram.getMemory().getBytes(layout.address(), bytes) != bytes.length) return null;
|
|
4224
|
+
} catch (Exception unreadable) {
|
|
4225
|
+
return null;
|
|
4226
|
+
}
|
|
4227
|
+
return bytes[count] == 0 ? swiftStringText(bytes, count, layout.ascii()) : null;
|
|
4228
|
+
}
|
|
4229
|
+
|
|
4230
|
+
/**
|
|
4231
|
+
* Every literal record of one dossier draws on half of the heap that was free when decoding
|
|
4232
|
+
* began. Text is charged at the worst case per UTF-8 byte: two bytes of UTF-16 text, then up
|
|
4233
|
+
* to six escaped JSON characters ("\\u0000") held as UTF-16 in Gson's growing writer buffer
|
|
4234
|
+
* (up to twice its length), again in the returned String, and once more as UTF-8 on the
|
|
4235
|
+
* socket. Each record also pays a fixed cost for its map key, JSON members, addresses, words
|
|
4236
|
+
* and their serialized form, so many empty or small literals are bounded too. Retained
|
|
4237
|
+
* provenance-cache entries draw on that same fixed-state allowance.
|
|
4238
|
+
*/
|
|
4239
|
+
private static final class SwiftLiteralBudget {
|
|
4240
|
+
private static final long BYTES_PER_LITERAL_BYTE = 2 + 6 * 2 * 2 + 6 * 2 + 6;
|
|
4241
|
+
private static final long BYTES_PER_RECORD = 4096;
|
|
4242
|
+
private long remaining;
|
|
4243
|
+
private boolean stopped;
|
|
4244
|
+
|
|
4245
|
+
SwiftLiteralBudget() {
|
|
4246
|
+
Runtime runtime = Runtime.getRuntime();
|
|
4247
|
+
remaining = Math.max(0, (runtime.maxMemory() - runtime.totalMemory() + runtime.freeMemory()) / 2);
|
|
4248
|
+
}
|
|
4249
|
+
|
|
4250
|
+
SwiftLiteralBudget(long remaining) {
|
|
4251
|
+
if (remaining < 0) throw new IllegalArgumentException("Swift literal budget must be nonnegative");
|
|
4252
|
+
this.remaining = remaining;
|
|
4253
|
+
}
|
|
4254
|
+
|
|
4255
|
+
boolean takeState() {
|
|
4256
|
+
if (remaining < BYTES_PER_RECORD) return false;
|
|
4257
|
+
remaining -= BYTES_PER_RECORD;
|
|
4258
|
+
return true;
|
|
4259
|
+
}
|
|
4260
|
+
|
|
4261
|
+
boolean take(long bytes) {
|
|
4262
|
+
if (remaining < BYTES_PER_RECORD ||
|
|
4263
|
+
bytes > (remaining - BYTES_PER_RECORD) / BYTES_PER_LITERAL_BYTE) {
|
|
4264
|
+
return false;
|
|
4265
|
+
}
|
|
4266
|
+
remaining -= BYTES_PER_RECORD + bytes * BYTES_PER_LITERAL_BYTE;
|
|
4267
|
+
return true;
|
|
4268
|
+
}
|
|
4269
|
+
|
|
4270
|
+
void stop() {
|
|
4271
|
+
stopped = true;
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4274
|
+
boolean stopped() {
|
|
4275
|
+
return stopped;
|
|
4276
|
+
}
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
// Swift String values may contain any scalar, including controls; JSON escapes them.
|
|
4280
|
+
private static String swiftStringText(byte[] bytes, int length, boolean ascii) {
|
|
4281
|
+
if (length < 0 || length > bytes.length) return null;
|
|
4282
|
+
for (int index = 0; index < length; index++) {
|
|
4283
|
+
if (ascii && bytes[index] < 0) return null;
|
|
4284
|
+
}
|
|
4285
|
+
try {
|
|
4286
|
+
return StandardCharsets.UTF_8.newDecoder().decode(ByteBuffer.wrap(bytes, 0, length)).toString();
|
|
4287
|
+
} catch (CharacterCodingException invalid) {
|
|
4288
|
+
return null;
|
|
4289
|
+
}
|
|
4290
|
+
}
|
|
4291
|
+
|
|
4292
|
+
private static JsonObject swiftStringOmission(SwiftLiteralLayout layout, long word, long object) {
|
|
4293
|
+
return swiftStringOmission(layout, word, object, "capacity");
|
|
4294
|
+
}
|
|
4295
|
+
|
|
4296
|
+
private static JsonObject swiftStringOmission(
|
|
4297
|
+
SwiftLiteralLayout layout,
|
|
4298
|
+
long word,
|
|
4299
|
+
long object,
|
|
4300
|
+
String reason
|
|
4301
|
+
) {
|
|
4302
|
+
JsonObject item = new JsonObject();
|
|
4303
|
+
item.addProperty("representation", layout.representation());
|
|
4304
|
+
if (layout.address() == null) {
|
|
4305
|
+
item.add("address", JsonNull.INSTANCE);
|
|
4306
|
+
} else {
|
|
4307
|
+
item.addProperty("address", canonicalAddress(layout.address()));
|
|
4308
|
+
}
|
|
4309
|
+
item.addProperty("byte_length", layout.byteLength());
|
|
4310
|
+
item.addProperty("reason", reason);
|
|
4311
|
+
item.add("words", swiftStringWords(word, object));
|
|
4312
|
+
return item;
|
|
4313
|
+
}
|
|
4314
|
+
|
|
4315
|
+
private static JsonObject swiftStringItem(
|
|
4316
|
+
String value,
|
|
4317
|
+
SwiftLiteralLayout layout,
|
|
4318
|
+
long word,
|
|
4319
|
+
long object
|
|
4320
|
+
) {
|
|
4321
|
+
JsonObject item = new JsonObject();
|
|
4322
|
+
item.addProperty("value", value);
|
|
4323
|
+
item.addProperty("representation", layout.representation());
|
|
4324
|
+
if (layout.address() == null) {
|
|
4325
|
+
item.add("address", JsonNull.INSTANCE);
|
|
4326
|
+
} else {
|
|
4327
|
+
item.addProperty("address", canonicalAddress(layout.address()));
|
|
4328
|
+
}
|
|
4329
|
+
item.add("words", swiftStringWords(word, object));
|
|
4330
|
+
return item;
|
|
4331
|
+
}
|
|
4332
|
+
|
|
4333
|
+
private static JsonArray swiftStringWords(long word, long object) {
|
|
4334
|
+
JsonArray words = new JsonArray();
|
|
4335
|
+
words.add("0x" + Long.toUnsignedString(word, 16));
|
|
4336
|
+
words.add("0x" + Long.toUnsignedString(object, 16));
|
|
4337
|
+
return words;
|
|
4338
|
+
}
|
|
4339
|
+
|
|
3259
4340
|
private static String exclusiveAddress(Address inclusive) {
|
|
3260
4341
|
Address next = inclusive.next();
|
|
3261
4342
|
if (next != null && next.getAddressSpace().equals(inclusive.getAddressSpace())) {
|
|
@@ -3794,7 +4875,16 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
3794
4875
|
private record InventoryItem(Address address, String value, JsonObject facts) {}
|
|
3795
4876
|
private record AddressNameRequest(String inputAddress, Address address, String name) {}
|
|
3796
4877
|
private record FunctionEntry(Function function, InventoryItem item) {}
|
|
3797
|
-
private record FunctionAnalysisObservation(JsonObject dossier, List<String> limitations) {}
|
|
4878
|
+
private record FunctionAnalysisObservation(JsonObject dossier, List<String> limitations, JsonObject relationshipCoverage) {}
|
|
4879
|
+
private record CallBoundaryObservation(List<String> limitations, Integer unrepresentedCalleeCalls, JsonArray unresolvedCalls) {}
|
|
4880
|
+
private record SwiftStringLiteralDecode(JsonArray literals, JsonArray omissions) {}
|
|
4881
|
+
private record SwiftLiteralLayout(
|
|
4882
|
+
String representation,
|
|
4883
|
+
Address address,
|
|
4884
|
+
long byteLength,
|
|
4885
|
+
boolean ascii,
|
|
4886
|
+
String smallValue
|
|
4887
|
+
) {}
|
|
3798
4888
|
private record InstructionScan(List<Instruction> instructions, boolean truncated) {}
|
|
3799
4889
|
private record SessionDescriptor(
|
|
3800
4890
|
String transport,
|