rea-agents 6.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -17
- package/bridge/android/ReaJadxBridge.java +14 -5
- package/bridge/ghidra/ReaGhidraBridge.java +173 -47
- package/bridge/hopper_bridge.py +310 -128
- package/bridge/mitmproxy/capture.py +0 -2
- package/bridge/native/rea_lldb_tracer.py +630 -94
- package/bridge/process/ProcessRunTokenReader.swift +39 -5
- package/bridge/pwntools/recorded_crash_impl.py +4 -0
- package/dist/android/JadxConfiguration.js +196 -33
- package/dist/android/JadxMcpTransport.js +4 -0
- package/dist/android/JadxProtocol.js +6 -0
- package/dist/android/JadxProvider.js +19 -2
- package/dist/android/JadxSession.js +23 -4
- package/dist/application/AnalysisContextQueries.js +8 -35
- package/dist/application/AnalysisDocument.js +32 -0
- package/dist/application/AppBundleExecutable.js +67 -21
- package/dist/application/CallPathTracing.js +19 -3
- package/dist/application/CapabilityInventory.js +6 -3
- package/dist/application/ClientConfigurationDocument.js +871 -6
- package/dist/application/ClientRegistrationIdentity.js +26 -5
- package/dist/application/ClientRegistrationStatus.js +29 -14
- package/dist/application/DirectAnalysis.js +27 -37
- package/dist/application/Doctor.js +4 -2
- package/dist/application/DoctorScope.js +25 -13
- package/dist/application/EnhancedLiteralTracing.js +22 -25
- package/dist/application/EnhancedTools.js +13 -11
- package/dist/application/EvidenceBundleFiles.js +23 -11
- package/dist/application/FunctionAnalysisEvidence.js +2 -3
- package/dist/application/InventoryProjectionEvidence.js +4 -3
- package/dist/application/InvestigationProviders.js +3 -2
- package/dist/application/JsonFiles.js +50 -28
- package/dist/application/ProcedureAddressResolution.js +11 -0
- package/dist/application/ReconstructionCoverageService.js +7 -4
- package/dist/application/ReconstructionObligationLedgerService.js +4 -3
- package/dist/application/Setup.js +13 -1
- package/dist/application/SetupClientConfiguration.js +10 -15
- package/dist/application/SetupHost.js +5 -2
- package/dist/application/SetupPlan.js +5 -3
- package/dist/application/SupportedClients.js +34 -1
- package/dist/application/Uninstall.js +4 -3
- package/dist/application/Update.js +18 -3
- package/dist/application/UpdateRuntime.js +46 -25
- package/dist/application/WebModuleTraceService.js +4 -2
- package/dist/application/WebNetworkCaptureService.js +4 -2
- package/dist/application/WebRuntimeService.js +5 -3
- package/dist/application/WebScriptExportService.js +2 -2
- package/dist/application/WebSourceLocationService.js +4 -2
- package/dist/application/WorkflowEvidence.js +82 -0
- package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
- package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
- package/dist/application/binary/AnalysisSnapshotCache.js +3 -6
- package/dist/application/binary/BinarySession.js +95 -68
- package/dist/application/binary/BinarySessionOpen.js +3 -3
- package/dist/application/binary/BinarySessionRecords.js +25 -3
- package/dist/application/binary/BinarySessionStatus.js +17 -1
- package/dist/application/binary/CompositeProvider.js +13 -0
- package/dist/application/binary/LazyAnalysisProvider.js +3 -0
- package/dist/application/binaryDiagnostics/BinaryLayoutService.js +4 -2
- package/dist/application/binaryDiagnostics/RecordedCrashService.js +4 -2
- package/dist/application/evm/EvmInterfaceService.js +4 -2
- package/dist/application/investigation/EvidenceLedger.js +21 -7
- package/dist/application/investigation/InvestigationRecords.js +8 -0
- package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +24 -3
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
- package/dist/application/javascript/JavaScriptApplicationService.js +22 -15
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +5 -4
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +6 -3
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +11 -3
- package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
- package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
- package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +63 -61
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +23 -1
- package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
- package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
- package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
- package/dist/application/managed/ManagedReconstructionService.js +4 -3
- package/dist/application/process/ProcessCli.js +14 -6
- package/dist/application/process/ProcessEvidence.js +4 -3
- package/dist/application/workflowInputError.js +18 -0
- package/dist/artifacts/ArtifactProvider.js +12 -2
- package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
- package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
- package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
- package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
- package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
- package/dist/artifacts/apple/MachoLoadCommandReader.js +92 -31
- package/dist/artifacts/apple/NibArchive.js +81 -14
- package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
- package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +13 -8
- package/dist/artifacts/inventory/scanCanonical.js +11 -14
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
- package/dist/browser/CdpCaptureCompleteness.js +2 -0
- package/dist/browser/CdpCaptureEventHandlers.js +76 -11
- package/dist/browser/CdpCaptureEventTypes.js +5 -1
- package/dist/browser/CdpCaptureEvents.js +25 -0
- package/dist/browser/CdpConnection.js +30 -11
- package/dist/browser/CdpOptionalCommand.js +2 -3
- package/dist/browser/CdpPageCapture.js +23 -1
- package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
- package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +123 -124
- package/dist/browser/WebSourceMapFetcher.js +426 -72
- package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
- package/dist/browser/history/CaptureFailures.js +37 -1
- package/dist/browser/history/CaptureRelease.js +5 -0
- package/dist/browser/history/HarCaptureAdapter.js +3 -3
- package/dist/browser/history/HarJson.js +3 -2
- package/dist/browser/history/HistoricalCaptureDecoder.js +4 -2
- package/dist/cli/analysisSelector.js +23 -0
- package/dist/cli/applicationCommands.js +2 -3
- package/dist/cli/coreBinaryCommands.js +70 -12
- package/dist/cli/electronCommands.js +7 -6
- package/dist/cli/javascriptApplicationAnalysis.js +7 -3
- package/dist/cli/jsonOutput.js +4 -99
- package/dist/cli/nativeCallCommands.js +2 -3
- package/dist/cli/webRuntimeCommands.js +8 -8
- package/dist/cli.js +2 -1
- package/dist/cliCommandNames.js +0 -1
- package/dist/cliJsonInput.js +9 -4
- package/dist/config/environment.js +4 -0
- package/dist/config/ghidraStartupTimeout.js +17 -0
- package/dist/config/mcpResponseBudget.js +22 -0
- package/dist/config/parseConfig.js +2 -1
- package/dist/contracts/enhancedInputs.js +5 -3
- package/dist/contracts/enhancedToolContracts.js +3 -3
- package/dist/contracts/hopperMemoryContracts.js +2 -5
- package/dist/contracts/javascript/electronToolContracts.js +1 -1
- package/dist/contracts/managed/managedToolContracts.js +2 -4
- package/dist/contracts/native/nativeToolContracts.js +4 -2
- package/dist/contracts/officialToolContracts.js +14 -15
- package/dist/contracts/promptContracts.js +3 -3
- package/dist/contracts/sessionLifecycleInputs.js +3 -7
- package/dist/contracts/sessionStatusContract.js +2 -4
- package/dist/contracts/sessionToolContracts.js +4 -6
- package/dist/contracts/sessionToolSchemas.js +2 -5
- package/dist/contracts/toolContractExamples.js +0 -1
- package/dist/contracts/toolContractHelpers.js +4 -1
- package/dist/contracts/toolEffects.js +0 -1
- package/dist/contracts/toolOutputSchemaGroups.js +28 -27
- package/dist/contracts/toolOutputSchemaPrimitives.js +18 -0
- package/dist/contracts/toolSchemaMetadata.js +69 -10
- package/dist/contracts/webNetworkCaptureToolContracts.js +1 -1
- package/dist/domain/analysisErrorBase.js +8 -3
- package/dist/domain/analysisErrorCore.js +3 -1
- package/dist/domain/analysisErrorPresentation.js +72 -17
- package/dist/domain/analysisErrorProjection.js +106 -27
- package/dist/domain/android/androidAnalysis.js +2 -4
- package/dist/domain/android/androidApplication.js +17 -9
- package/dist/domain/apple/appleApplication.js +41 -14
- package/dist/domain/apple/dyldEnvironment.js +73 -0
- package/dist/domain/apple/dylibResolution.js +120 -9
- package/dist/domain/apple/dylibResolutionFindings.js +9 -7
- package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
- package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
- package/dist/domain/apple/keyedArchive.js +9 -1
- package/dist/domain/apple/machoContainer.js +54 -0
- package/dist/domain/apple/plistNumbers.js +76 -0
- package/dist/domain/artifactIdentity.js +29 -0
- package/dist/domain/artifactInventoryEvidence.js +19 -24
- package/dist/domain/bridgeCandidateProjection.js +71 -0
- package/dist/domain/browserCompleteness.js +1 -0
- package/dist/domain/browserObservationError.js +24 -5
- package/dist/domain/browserScenarioValues.js +2 -6
- package/dist/domain/bundleComparison.js +3 -2
- package/dist/domain/canonicalJsonDigestSteps.js +133 -0
- package/dist/domain/canonicalOrdering.js +9 -5
- package/dist/domain/changedBehavior.js +6 -6
- package/dist/domain/comparisonSourceEvidence.js +40 -0
- package/dist/domain/configurationErrors.js +1 -1
- package/dist/domain/evidence.js +64 -9
- package/dist/domain/evidenceBundle.js +42 -1
- package/dist/domain/evidenceErrors.js +12 -1
- package/dist/domain/explicitSensitiveFailure.js +17 -1
- package/dist/domain/firmware/firmwareAnalysis.js +6 -7
- package/dist/domain/hopperErrors.js +23 -2
- package/dist/domain/hopperValues.js +51 -8
- package/dist/domain/immutableJson.js +114 -0
- package/dist/domain/inputIssueProjection.js +3 -0
- package/dist/domain/javascript/electronActiveObservation.js +30 -4
- package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
- package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
- package/dist/domain/javascript/javascriptAstValues.js +20 -0
- package/dist/domain/javascript/javascriptRecovery.js +3 -8
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
- package/dist/domain/javascript/javascriptSemanticGraph.js +13 -0
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
- package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
- package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
- package/dist/domain/javascript/javascriptSourceParser.js +6 -2
- package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
- package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
- package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
- package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
- package/dist/domain/jsonSerialization.js +109 -0
- package/dist/domain/jsonValue.js +90 -6
- package/dist/domain/localPath.js +6 -0
- package/dist/domain/managed/managedApplicationGraph.js +10 -10
- package/dist/domain/managed/managedInspectionEvidence.js +16 -0
- package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
- package/dist/domain/managed/managedNativeVerification.js +3 -9
- package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
- package/dist/domain/native/nativeCallObservation.js +33 -11
- package/dist/domain/native/nativeCallPartialObservation.js +33 -0
- package/dist/domain/process/processCapture.js +8 -4
- package/dist/domain/process/processComparison.js +38 -4
- package/dist/domain/process/processScenario.js +11 -10
- package/dist/domain/propertyListKeys.js +1 -1
- package/dist/domain/propertyListXmlText.js +19 -0
- package/dist/domain/providerAdapterError.js +1 -1
- package/dist/domain/providerOperationHealth.js +54 -0
- package/dist/domain/reconstructionVerification.js +6 -43
- package/dist/domain/reconstructionVerificationSchemas.js +2 -2
- package/dist/domain/staticRuntimeCorrelation.js +6 -43
- package/dist/domain/webBundleAnalysis.js +20 -8
- package/dist/domain/webBundleAnalyzerInspection.js +13 -8
- package/dist/domain/webBundleAnalyzerResult.js +41 -2
- package/dist/domain/webRuntime.js +19 -5
- package/dist/domain/webSourceLocation.js +1 -0
- package/dist/firmware/FirmwareFiles.js +1 -1
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
- package/dist/ghidra/GhidraClient.js +47 -14
- package/dist/ghidra/GhidraDiagnostics.js +7 -7
- package/dist/ghidra/GhidraFunctionValues.js +10 -7
- package/dist/ghidra/GhidraInstallation.js +18 -21
- package/dist/ghidra/GhidraInventoryValues.js +14 -4
- package/dist/ghidra/GhidraJavaLaunch.js +62 -0
- package/dist/ghidra/GhidraLauncher.js +33 -16
- package/dist/ghidra/GhidraProviderCapabilities.js +14 -2
- package/dist/ghidra/GhidraProviderClient.js +23 -12
- package/dist/ghidra/GhidraSessionError.js +11 -7
- package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
- package/dist/ghidra/GhidraTransport.js +20 -0
- package/dist/hopper/BridgeLauncher.js +31 -11
- package/dist/hopper/HopperAnalysisProfile.js +62 -4
- package/dist/hopper/HopperCleanup.js +15 -3
- package/dist/hopper/HopperClient.js +222 -14
- package/dist/hopper/HopperFileOffset.js +237 -0
- package/dist/hopper/HopperMachOImage.js +196 -0
- package/dist/hopper/HopperOperationStage.js +6 -0
- package/dist/hopper/HopperProvider.js +63 -9
- package/dist/hopper/HopperProviderCapabilities.js +19 -1
- package/dist/hopper/HopperRegexSearch.js +137 -0
- package/dist/hopper/HopperRegexWorker.js +27 -0
- package/dist/hopper/HopperRequestQueue.js +68 -19
- package/dist/hopper/HopperTargetLease.js +3 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
- package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
- package/dist/inspector/V8InspectorProvider.js +47 -11
- package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
- package/dist/javascript/sourceMaps/SourceMapCommand.js +16 -0
- package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
- package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
- package/dist/mcpDoctor.js +62 -2
- package/dist/native/AppleDispatchCoverage.js +47 -6
- package/dist/native/AppleDispatchDecodeFacts.js +6 -0
- package/dist/native/AppleDispatchMetadata.js +6 -3
- package/dist/native/AppleMachoFixups.js +48 -24
- package/dist/native/AppleMachoSelection.js +32 -16
- package/dist/native/AppleObjcCategories.js +6 -2
- package/dist/native/AppleObjcDispatchFacets.js +5 -2
- package/dist/native/AppleObjcProperties.js +2 -1
- package/dist/native/AppleSwiftDispatchFacets.js +27 -21
- package/dist/native/AppleSwiftVtables.js +21 -15
- package/dist/native/CommandRunner.js +81 -84
- package/dist/native/LldbCallTracer.js +365 -102
- package/dist/native/LldbRetainedObservations.js +178 -0
- package/dist/native/NativeCallObservation.js +62 -3
- package/dist/native/NativeMacOSProvider.js +98 -17
- package/dist/native/SignatureTargetBinding.js +155 -0
- package/dist/native/parsers/lipo.js +71 -1
- package/dist/native/pwndbg/PwndbgCoreContext.js +25 -5
- package/dist/native/pwntools/RecordedCrashStructureBindings.js +2 -0
- package/dist/process/DarwinProcessRunTokenReader.js +8 -9
- package/dist/process/ExecFileOutput.js +20 -0
- package/dist/process/OwnedCommand.js +7 -2
- package/dist/process/ProcessOwnership.js +203 -53
- package/dist/process/ProcessOwnershipObservation.js +49 -4
- package/dist/process/ProviderProcess.js +38 -7
- package/dist/process/capture/ProcessCaptureError.js +2 -2
- package/dist/process/capture/ProcessCaptureLifecycle.js +100 -34
- package/dist/server/EvidenceMcpServer.js +146 -0
- package/dist/server/createServer.js +15 -8
- package/dist/server/registerAndroidTools.js +2 -4
- package/dist/server/registerApplicationTools/helpers.js +2 -4
- package/dist/server/registerArtifactComparisonTool.js +11 -7
- package/dist/server/registerBinaryDiagnosticsTools.js +2 -4
- package/dist/server/registerBrowserScenarioTool.js +2 -4
- package/dist/server/registerBrowserTools.js +2 -4
- package/dist/server/registerBundleComparisonTool.js +2 -3
- package/dist/server/registerCloseLifecycleTool.js +8 -18
- package/dist/server/registerElectronTools.js +2 -4
- package/dist/server/registerEnhancedTools.js +18 -59
- package/dist/server/registerEvidenceTools.js +2 -4
- package/dist/server/registerEvmTools.js +2 -4
- package/dist/server/registerFirmwareTools.js +2 -4
- package/dist/server/registerFunctionComparisonTool.js +10 -6
- package/dist/server/registerInvestigationTools.js +7 -7
- package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
- package/dist/server/registerOfficialTools.js +2 -4
- package/dist/server/registerProcessComparisonTool.js +71 -45
- package/dist/server/registerRecordedCrashTools.js +2 -4
- package/dist/server/registerSessionRecordTools.js +5 -6
- package/dist/server/registerSessionStatusTool.js +17 -3
- package/dist/server/registerSessionTools.js +11 -3
- package/dist/server/registerWebModuleTool.js +2 -4
- package/dist/server/registerWebNetworkCaptureTool.js +2 -4
- package/dist/server/registerWebRuntimeTools.js +3 -7
- package/dist/server/registerWebScriptTool.js +2 -4
- package/dist/server/registerWebSourceLocationTool.js +2 -4
- package/dist/server/runDerivedOperation.js +15 -3
- package/dist/server/sessionAvailabilityPolicy.js +0 -1
- package/dist/server/toolRegistrationOptions.js +2 -2
- package/dist/server/toolResult.js +62 -10
- package/dist/server/toolResultEncoding.js +33 -0
- package/install.sh +1 -1
- package/native/windows/build/manifest.json +1 -1
- package/package.json +8 -3
- package/scripts/electron-active-hook-boundaries.cjs +18 -20
- package/scripts/electron-active-hook.cjs +241 -37
- package/skills/reverse-engineer-anything/SKILL.md +11 -3
- package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
- package/dist/ghidra/GhidraDefaults.js +0 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
**English** · [简体中文](README_zh.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [العربية](README_ar.md)
|
|
3
|
+
**English** · [简体中文](README_zh.md) · [繁體中文](README_zh-TW.md) · [日本語](README_ja.md) · [한국어](README_ko.md) · [Türkçe](README_tr.md) · [Русский](README_ru.md) · [Tiếng Việt](README_vi.md) · [ไทย](README_th.md) · [Deutsch](README_de.md) · [Español](README_es.md) · [Українська](README_uk.md) · [Polski](README_pl.md) · [Português (Brasil)](README_pt-BR.md) · [العربية](README_ar.md) · [فارسی](README_fa.md)
|
|
4
4
|
|
|
5
5
|
# REA: Reverse Engineer Anything
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
[](https://www.npmjs.com/package/rea-agents)
|
|
12
12
|
[](https://github.com/morluto/rea/actions/workflows/ci.yml)
|
|
13
|
-
[](docs/
|
|
13
|
+
[](docs/mcp-contracts.md#generated-catalog)
|
|
14
14
|
[](https://nodejs.org/)
|
|
15
15
|
[](https://skills.sh/morluto/rea/reverse-engineer-anything)
|
|
16
16
|
[](LICENSE)
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
<a href="https://trendshift.io/repositories/82054?utm_source=repository-badge&utm_medium=badge&utm_campaign=badge-repository-82054" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/repositories/82054" alt="morluto%2Frea | Trendshift" width="250" height="55"/></a>
|
|
20
20
|
|
|
21
|
-
**[Website](https://
|
|
21
|
+
**[Website](https://rea.tools/) · [Guides](https://rea.tools/guides/) · [Showcases](https://rea.tools/showcase/)**
|
|
22
22
|
|
|
23
23
|
[Quick start](#quick-start) · [How REA works](#how-rea-works) · [What you can analyze](#what-you-can-analyze) · [Showcases](#showcases) · [FAQ](#faq) · [Documentation](#documentation)
|
|
24
24
|
|
|
@@ -54,7 +54,7 @@ REA connects your agent to tools for inspecting native binaries, JavaScript and
|
|
|
54
54
|
|
|
55
55
|
Setup registers REA with your agent and installs matching workflow instructions. Native analysis can use an existing Hopper or Ghidra installation; setup can optionally install Hopper with approval. Static JavaScript analysis needs neither engine.
|
|
56
56
|
|
|
57
|
-
> **[Visit the REA website](https://
|
|
57
|
+
> **[Visit the REA website](https://rea.tools/)** for setup instructions, illustrated guides, and real case studies.
|
|
58
58
|
|
|
59
59
|
## Quick start
|
|
60
60
|
|
|
@@ -70,7 +70,7 @@ Choose your agents, review the proposed changes, and approve them. Setup adds
|
|
|
70
70
|
REA's MCP server and matching workflow instructions, with backups of existing
|
|
71
71
|
configuration. Restart your agent afterward.
|
|
72
72
|
|
|
73
|
-
Setup supports Claude Code, Codex, Cursor, Gemini CLI and
|
|
73
|
+
Setup supports Claude Code, Codex, Cursor, Gemini CLI, Grok Build and
|
|
74
74
|
[other agents](docs/installation.md#supported-agents). See
|
|
75
75
|
[installation and setup](docs/installation.md) for provider configuration and
|
|
76
76
|
manual MCP registration.
|
|
@@ -149,12 +149,12 @@ Additional tools and host support depend on the target:
|
|
|
149
149
|
|
|
150
150
|
| Target | What REA returns | Requirements and guide |
|
|
151
151
|
| ---------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
152
|
-
| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](https://
|
|
152
|
+
| Native binaries | Pseudocode, assembly, strings, symbols, calls and references | Hopper, Ghidra or IDA; [native analysis](https://rea.tools/guides/native/) |
|
|
153
153
|
| Offline ELF layout | Sections, segments, original symbols/relocations and static mitigation candidates | Caller-supplied pwntools on Linux x64; [binary diagnostics](docs/binary-diagnostics.md) |
|
|
154
154
|
| EVM bytecode | Dispatch selectors, byte offsets, inferred arguments and mutability | Local raw/hex carrier; [offline EVM guide](docs/evm-bytecode.md) |
|
|
155
155
|
| Recorded Linux crashes | Raw notes, every recorded thread's registers/signals and optional mapping candidates | Caller-supplied pwntools; optional GDB/pwndbg; [recorded crashes](docs/recorded-crashes.md) |
|
|
156
|
-
| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; [application analysis](https://
|
|
157
|
-
| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](https://
|
|
156
|
+
| JavaScript / Electron | Modules, imports, source maps, routes, IPC and native add-on relationships | Node.js and npm; [application analysis](https://rea.tools/guides/javascript/) |
|
|
157
|
+
| Websites | Page structure, scripts, network observations and requested screenshots | A Chrome-family browser; [browser analysis](https://rea.tools/guides/browser/) |
|
|
158
158
|
| Saved network captures | Requests, responses, exposed payloads and source locations | HAR; mitmdump on Linux for native mitmproxy captures; [capture guide](docs/web-network-captures.md) |
|
|
159
159
|
| .NET assemblies | Metadata, CIL instructions, declared native dependencies and build comparisons | Static inspection; [managed-code guide](docs/managed-code-analysis.md) |
|
|
160
160
|
| Android APKs | Manifest declarations, classes, decompiled methods and references | Headless JADX and a full JDK on Linux/macOS; [Android guide](docs/android-analysis.md) |
|
|
@@ -173,6 +173,8 @@ Native formats and host support vary by provider. See
|
|
|
173
173
|
[IDA guide](docs/ida-provider.md), and
|
|
174
174
|
[experimental Windows Ghidra support](docs/windows-ghidra-p0.md).
|
|
175
175
|
Ghidra also supports [16-bit DOS analysis](docs/ghidra-dos.md).
|
|
176
|
+
For large binaries, raise its startup deadline with
|
|
177
|
+
`REA_GHIDRA_STARTUP_TIMEOUT_MS`.
|
|
176
178
|
For provider selection, see the [CLI guide](docs/cli.md#choose-a-provider).
|
|
177
179
|
Check [release availability](docs/installation.md#released-package-and-main)
|
|
178
180
|
for features added since the latest npm release.
|
|
@@ -185,7 +187,7 @@ Follow a sound call into its position-to-pan helper, inspect the instructions,
|
|
|
185
187
|
and turn incomplete pseudocode into C. The reconstruction passes 3,205
|
|
186
188
|
original-x86 cases and reproduces all 63 compiled function bytes.
|
|
187
189
|
|
|
188
|
-
[Read the case study](https://
|
|
190
|
+
[Read the case study](https://rea.tools/showcase/dx-ball/) ·
|
|
189
191
|
[Reconstruction repository](https://github.com/N0zoM1z0/dx-ball)
|
|
190
192
|
|
|
191
193
|
### Notion: trace the Electron clipboard bridge
|
|
@@ -193,7 +195,7 @@ original-x86 cases and reproduces all 63 compiled function bytes.
|
|
|
193
195
|
Find the renderer's clipboard API, follow it through preload and IPC into the
|
|
194
196
|
main process, and inspect the rich clipboard format.
|
|
195
197
|
|
|
196
|
-
[Read the case study](https://
|
|
198
|
+
[Read the case study](https://rea.tools/showcase/notion/)
|
|
197
199
|
|
|
198
200
|
### TH04: recover a DOS bullet-ring calculation
|
|
199
201
|
|
|
@@ -201,7 +203,7 @@ Inspect the original PC-98 game's 16-bit instructions, recover the fixed and
|
|
|
201
203
|
aimed angle calculations, and compare the reconstructed C++ with the
|
|
202
204
|
historical compiler output.
|
|
203
205
|
|
|
204
|
-
[Read the case study](https://
|
|
206
|
+
[Read the case study](https://rea.tools/showcase/th04/) ·
|
|
205
207
|
[Reconstruction repository](https://github.com/N0zoM1z0/th04)
|
|
206
208
|
|
|
207
209
|
If you've used REA on something interesting, we'd love to see it. Share your
|
|
@@ -289,14 +291,14 @@ with your REA version, target type, steps to reproduce and error output.
|
|
|
289
291
|
|
|
290
292
|
## Documentation
|
|
291
293
|
|
|
292
|
-
Start with the website's [worked guides](https://
|
|
294
|
+
Start with the website's [worked guides](https://rea.tools/guides/).
|
|
293
295
|
For exact options, prerequisites and result contracts:
|
|
294
296
|
|
|
295
297
|
- [Installation and setup](docs/installation.md): agent registration, provider configuration, updates and uninstall.
|
|
296
298
|
- [Readiness and troubleshooting](docs/installation.md#check-readiness-for-your-task): diagnose one agent or analysis engine.
|
|
297
299
|
- [CLI and Evidence](docs/cli.md): commands, provider selection, snapshots, import/export and exit statuses.
|
|
298
300
|
- [MCP contracts](docs/mcp-contracts.md) and [agent prompts](docs/mcp-prompts.md): tool results, sessions and guided investigations.
|
|
299
|
-
- [Tool catalog](docs/
|
|
301
|
+
- [Tool catalog](docs/mcp-contracts.md#generated-catalog): build-generated inventory of tools, providers and CLI commands.
|
|
300
302
|
- [Roadmap](docs/roadmap.md): planned work and capability trackers.
|
|
301
303
|
|
|
302
304
|
Report vulnerabilities through [SECURITY.md](SECURITY.md).
|
|
@@ -313,13 +315,13 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and checks,
|
|
|
313
315
|
|
|
314
316
|
## Project links
|
|
315
317
|
|
|
316
|
-
[Website](https://
|
|
318
|
+
[Website](https://rea.tools/) · [npm](https://www.npmjs.com/package/rea-agents) · [skills.sh](https://skills.sh/morluto/rea/reverse-engineer-anything) · [Issues](https://github.com/morluto/rea/issues) · [Security](SECURITY.md)
|
|
317
319
|
|
|
318
|
-
##
|
|
320
|
+
## Star history
|
|
319
321
|
|
|
320
|
-
|
|
322
|
+
🎉 **20,000 GitHub stars — thank you!**
|
|
321
323
|
|
|
322
|
-
|
|
324
|
+
Thanks to everyone using REA, reporting bugs, testing builds, and contributing fixes.
|
|
323
325
|
|
|
324
326
|
<a href="https://www.star-history.com/?repos=morluto%2Frea&type=date">
|
|
325
327
|
<picture>
|
|
@@ -332,3 +334,7 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and checks,
|
|
|
332
334
|
## Disclaimer
|
|
333
335
|
|
|
334
336
|
REA provides tools for lawful reverse-engineering research, analysis, and reconstruction. You are responsible for obtaining any required authorization and complying with applicable laws. The project does not endorse illegal or unauthorized use.
|
|
337
|
+
|
|
338
|
+
## License
|
|
339
|
+
|
|
340
|
+
[MIT](LICENSE)
|
|
@@ -25,6 +25,11 @@ class ReaJadxBridge {
|
|
|
25
25
|
private record MethodSnapshot(String name, String shortId, Map<String, Object> summary) {}
|
|
26
26
|
private record ClassSnapshot(JavaClass node, List<MethodSnapshot> methods, Map<String, Object> summary) {}
|
|
27
27
|
|
|
28
|
+
private static final class InputFailure extends IllegalArgumentException {
|
|
29
|
+
final String field;
|
|
30
|
+
InputFailure(String field, String message) { super(message); this.field = field; }
|
|
31
|
+
}
|
|
32
|
+
|
|
28
33
|
private ReaJadxBridge(SessionHolder holder) { this.holder = holder; }
|
|
29
34
|
|
|
30
35
|
private static CallToolResult text(String value, boolean failed) {
|
|
@@ -100,8 +105,9 @@ class ReaJadxBridge {
|
|
|
100
105
|
}
|
|
101
106
|
String name = string(args, "class_name");
|
|
102
107
|
List<ClassSnapshot> candidates = classes.get(name);
|
|
103
|
-
if (candidates == null) throw new
|
|
104
|
-
|
|
108
|
+
if (candidates == null) throw new InputFailure("class_name", "Exact class not found: " + name
|
|
109
|
+
+ "; use search_android_classes to discover fully qualified names.");
|
|
110
|
+
if (candidates.size() != 1) throw new InputFailure("class_name", "Ambiguous metadata class identity: " + name
|
|
105
111
|
+ "; raw identities: " + candidates.stream().map(candidate -> candidate.node().getRawName()).toList());
|
|
106
112
|
return candidates.get(0);
|
|
107
113
|
}
|
|
@@ -109,7 +115,8 @@ class ReaJadxBridge {
|
|
|
109
115
|
private List<MethodSnapshot> methods(ClassSnapshot cls, JsonObject args) {
|
|
110
116
|
String name = string(args, "method_name");
|
|
111
117
|
List<MethodSnapshot> result = cls.methods().stream().filter(method -> method.name().equals(name)).toList();
|
|
112
|
-
if (result.isEmpty()) throw new
|
|
118
|
+
if (result.isEmpty()) throw new InputFailure("method_name", "Method not found: " + name
|
|
119
|
+
+ "; use inspect_android_class to discover available methods.");
|
|
113
120
|
return result;
|
|
114
121
|
}
|
|
115
122
|
|
|
@@ -141,7 +148,7 @@ class ReaJadxBridge {
|
|
|
141
148
|
if (name.equals("get_method_body")) {
|
|
142
149
|
List<MethodSnapshot> overloads = methods(cls, args);
|
|
143
150
|
int index = integer(args, "overload_index", 0);
|
|
144
|
-
if (index >= overloads.size()) throw new
|
|
151
|
+
if (index >= overloads.size()) throw new InputFailure("overload_index", "overload_index out of range: " + index);
|
|
145
152
|
JavaMethod method = method(cls, overloads.get(index));
|
|
146
153
|
JadxSession.SmartCode code = current.getMethodBodySmart(method, current.getMaxSourceBytes(), true);
|
|
147
154
|
return json(Map.of("class_name", cls.summary().get("full_name"),
|
|
@@ -155,7 +162,7 @@ class ReaJadxBridge {
|
|
|
155
162
|
if (name.equals("get_xrefs_to_class")) uses = cls.node().getUseIn();
|
|
156
163
|
else {
|
|
157
164
|
List<MethodSnapshot> overloads = methods(cls, args);
|
|
158
|
-
if (overloads.size() != 1) throw new
|
|
165
|
+
if (overloads.size() != 1) throw new InputFailure("method_name", "Method references require a unique overload");
|
|
159
166
|
target += "." + overloads.get(0).name();
|
|
160
167
|
uses = method(cls, overloads.get(0)).getUseIn();
|
|
161
168
|
}
|
|
@@ -211,6 +218,8 @@ class ReaJadxBridge {
|
|
|
211
218
|
tool.getInputSchema().getRequired(), null), description, null, null, null, null, null, null);
|
|
212
219
|
server.addTool(narrowed, (connection, request, continuation) -> {
|
|
213
220
|
try { return bridge.handle(name, request.getArguments()); }
|
|
221
|
+
catch (InputFailure error) { return text(JSON.toJson(Map.of(
|
|
222
|
+
"kind", "invalid-input", "field", error.field, "message", error.getMessage())), true); }
|
|
214
223
|
catch (IllegalArgumentException error) { return text(error.getMessage(), true); }
|
|
215
224
|
});
|
|
216
225
|
}
|
|
@@ -52,6 +52,8 @@ import ghidra.app.decompiler.ClangCaseToken;
|
|
|
52
52
|
import ghidra.app.decompiler.ClangNode;
|
|
53
53
|
import ghidra.framework.Application;
|
|
54
54
|
import ghidra.program.model.address.Address;
|
|
55
|
+
import ghidra.program.model.address.AddressIterator;
|
|
56
|
+
import ghidra.program.model.address.AddressSet;
|
|
55
57
|
import ghidra.program.model.address.AddressSpace;
|
|
56
58
|
import ghidra.program.model.address.AddressRange;
|
|
57
59
|
import ghidra.program.model.address.AddressRangeIterator;
|
|
@@ -723,8 +725,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
723
725
|
if (!direction.equals("incoming") && !direction.equals("outgoing")) {
|
|
724
726
|
throw new RequestFailure("invalid_request", "direction must be incoming or outgoing");
|
|
725
727
|
}
|
|
726
|
-
|
|
727
|
-
List<Reference> references = collectReferences(scan.instructions, direction);
|
|
728
|
+
List<Reference> references = collectReferences(function, direction);
|
|
728
729
|
JsonArray edges = new JsonArray();
|
|
729
730
|
for (Reference reference : references) {
|
|
730
731
|
edges.add(referenceEdge(reference));
|
|
@@ -735,7 +736,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
735
736
|
result.add("references", edges);
|
|
736
737
|
result.addProperty("reference_kinds_available", true);
|
|
737
738
|
JsonArray unresolvedCalls = new JsonArray();
|
|
738
|
-
if (direction.equals("outgoing")) for (Instruction instruction :
|
|
739
|
+
if (direction.equals("outgoing")) for (Instruction instruction : scanInstructions(function, Integer.MAX_VALUE).instructions) {
|
|
739
740
|
if (!instruction.getFlowType().isCall()) continue;
|
|
740
741
|
boolean resolved = false;
|
|
741
742
|
for (Reference reference : instruction.getReferencesFrom()) if (reference.getReferenceType().isCall()) resolved = true;
|
|
@@ -1007,6 +1008,11 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1007
1008
|
Address entry = function.getEntryPoint();
|
|
1008
1009
|
if (function.isExternal() || !currentProgram.getMemory().contains(entry))
|
|
1009
1010
|
throw new RequestFailure("invalid_request", "Annotations require a local function entry: " + canonicalAddress(entry));
|
|
1011
|
+
for (String field : List.of("name", "comment", "inline_comment")) {
|
|
1012
|
+
if (params.has(field)) validateAnnotationText(requireText(params, field), field);
|
|
1013
|
+
}
|
|
1014
|
+
String leafName = params.has("name")
|
|
1015
|
+
? annotationLeafName(function, requireString(params, "name")) : null;
|
|
1010
1016
|
int transaction = currentProgram.startTransaction("REA function annotations");
|
|
1011
1017
|
boolean commit = false;
|
|
1012
1018
|
try {
|
|
@@ -1020,7 +1026,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1020
1026
|
}
|
|
1021
1027
|
}
|
|
1022
1028
|
if (params.has("name"))
|
|
1023
|
-
function.setName(
|
|
1029
|
+
function.setName(leafName, SourceType.USER_DEFINED);
|
|
1024
1030
|
monitor.checkCancelled();
|
|
1025
1031
|
invalidateAnalysisCaches();
|
|
1026
1032
|
JsonObject readback = annotationReadback(function);
|
|
@@ -1028,7 +1034,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1028
1034
|
if (!params.has(field)) continue;
|
|
1029
1035
|
String requested = requireText(params, field);
|
|
1030
1036
|
JsonElement measured = readback.get(field);
|
|
1031
|
-
String expected =
|
|
1037
|
+
String expected = field.equals("name") ? leafName : requested.isEmpty() ? null : requested;
|
|
1032
1038
|
String observed = field.equals("name") ? function.getName() :
|
|
1033
1039
|
(measured.isJsonNull() ? null : measured.getAsString());
|
|
1034
1040
|
if (!java.util.Objects.equals(expected, observed))
|
|
@@ -1058,6 +1064,22 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1058
1064
|
}
|
|
1059
1065
|
}
|
|
1060
1066
|
|
|
1067
|
+
private String annotationLeafName(Function function, String requested) {
|
|
1068
|
+
// Fully qualified readback must be usable as an idempotent rename input.
|
|
1069
|
+
if (requested.equals(procedureName(function))) return function.getName();
|
|
1070
|
+
String namespace = function.getParentNamespace().isGlobal()
|
|
1071
|
+
? "" : function.getParentNamespace().getName(true);
|
|
1072
|
+
String prefix = namespace + "::";
|
|
1073
|
+
if (!namespace.isEmpty() && requested.startsWith(prefix)) {
|
|
1074
|
+
String leaf = requested.substring(prefix.length());
|
|
1075
|
+
if (!leaf.isEmpty()) return leaf;
|
|
1076
|
+
throw new RequestFailure("invalid_function_name",
|
|
1077
|
+
"Function name has an empty leaf within namespace " + namespace + " at " +
|
|
1078
|
+
canonicalAddress(function.getEntryPoint()) + ": " + requested);
|
|
1079
|
+
}
|
|
1080
|
+
return requested;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1061
1083
|
private static String requireText(JsonObject params, String field) {
|
|
1062
1084
|
JsonElement value = params.get(field);
|
|
1063
1085
|
if (value == null || !value.isJsonPrimitive() || !value.getAsJsonPrimitive().isString())
|
|
@@ -1065,6 +1087,21 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1065
1087
|
return value.getAsString();
|
|
1066
1088
|
}
|
|
1067
1089
|
|
|
1090
|
+
private static void validateAnnotationText(String text, String field) {
|
|
1091
|
+
for (int index = 0; index < text.length(); index++) {
|
|
1092
|
+
char character = text.charAt(index);
|
|
1093
|
+
if (character == 0)
|
|
1094
|
+
throw new RequestFailure("invalid_request", "Annotation " + field + " contains NUL at UTF-16 index " + index + "; Ghidra's decompiler cannot marshal NUL text");
|
|
1095
|
+
if (Character.isHighSurrogate(character) && index + 1 < text.length() &&
|
|
1096
|
+
Character.isLowSurrogate(text.charAt(index + 1))) {
|
|
1097
|
+
index++;
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
if (Character.isSurrogate(character))
|
|
1101
|
+
throw new RequestFailure("invalid_request", "Annotation " + field + " contains an unpaired Unicode surrogate at UTF-16 index " + index + "; Ghidra cannot preserve it as annotation text");
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1068
1105
|
private JsonObject analyzeFunction(JsonObject params) throws Exception {
|
|
1069
1106
|
requireKeys(params, Set.of("procedure"));
|
|
1070
1107
|
Function function = resolveProcedure(requireString(params, "procedure"));
|
|
@@ -1074,11 +1111,11 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1074
1111
|
if (pseudocode == null) {
|
|
1075
1112
|
pseudocode = "";
|
|
1076
1113
|
}
|
|
1077
|
-
List<Reference> incomingReferences = collectReferences(
|
|
1114
|
+
List<Reference> incomingReferences = collectReferences(function, "incoming")
|
|
1078
1115
|
.stream()
|
|
1079
1116
|
.filter(reference -> !function.getBody().contains(reference.getFromAddress()))
|
|
1080
1117
|
.toList();
|
|
1081
|
-
List<Reference> outgoingReferences = collectReferences(
|
|
1118
|
+
List<Reference> outgoingReferences = collectReferences(function, "outgoing");
|
|
1082
1119
|
JsonArray incoming = referenceEdges(incomingReferences);
|
|
1083
1120
|
JsonArray outgoing = referenceEdges(outgoingReferences);
|
|
1084
1121
|
JsonArray comments = comments(scan.instructions);
|
|
@@ -1471,6 +1508,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1471
1508
|
: regexMatcher(expression, caseSensitive);
|
|
1472
1509
|
JsonArray items = new JsonArray();
|
|
1473
1510
|
for (InventoryItem item : inventory) {
|
|
1511
|
+
monitor.checkCancelled();
|
|
1474
1512
|
if (!matcher.matches(item.value)) {
|
|
1475
1513
|
continue;
|
|
1476
1514
|
}
|
|
@@ -1581,33 +1619,36 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
1581
1619
|
}
|
|
1582
1620
|
|
|
1583
1621
|
private Function resolveProcedure(String value) throws Exception {
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
Function function = entry.function;
|
|
1598
|
-
Symbol symbol = function.getSymbol();
|
|
1599
|
-
String qualified = symbol == null ? function.getName() : symbol.getName(true);
|
|
1600
|
-
if (function.getName().equals(value) || qualified.equals(value)) {
|
|
1601
|
-
matches.add(function);
|
|
1622
|
+
// Explicit address syntax wins; an unprefixed identifier is first an
|
|
1623
|
+
// exact symbol name, even when every character is a hexadecimal digit.
|
|
1624
|
+
boolean explicitAddress = isExplicitReaAddress(value);
|
|
1625
|
+
if (!explicitAddress) {
|
|
1626
|
+
List<Function> matches = new ArrayList<>();
|
|
1627
|
+
for (FunctionEntry entry : procedures()) {
|
|
1628
|
+
monitor.checkCancelled();
|
|
1629
|
+
Function function = entry.function;
|
|
1630
|
+
Symbol symbol = function.getSymbol();
|
|
1631
|
+
String qualified = symbol == null ? function.getName() : symbol.getName(true);
|
|
1632
|
+
if (function.getName().equals(value) || qualified.equals(value)) {
|
|
1633
|
+
matches.add(function);
|
|
1634
|
+
}
|
|
1602
1635
|
}
|
|
1636
|
+
if (matches.size() > 1)
|
|
1637
|
+
throw new RequestFailure("ambiguous", "Ghidra procedure name is ambiguous: " + value +
|
|
1638
|
+
"; select an exact entry address from " + matches.stream()
|
|
1639
|
+
.map(function -> canonicalAddress(function.getEntryPoint())).toList());
|
|
1640
|
+
if (matches.size() == 1) return matches.get(0);
|
|
1603
1641
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1642
|
+
// Retain legacy bare-hex address input only when no symbol matches.
|
|
1643
|
+
Address address = explicitAddress ? parseReaAddress(value) : tryParseAddress(value);
|
|
1644
|
+
if (address == null)
|
|
1645
|
+
throw new RequestFailure("not_found", "Unknown Ghidra procedure name or address: " + value);
|
|
1646
|
+
Function function = currentProgram.getFunctionManager().getFunctionAt(address);
|
|
1647
|
+
if (function == null && address.isMemoryAddress())
|
|
1648
|
+
function = currentProgram.getFunctionManager().getFunctionContaining(address);
|
|
1649
|
+
if (function == null)
|
|
1650
|
+
throw new RequestFailure("not_found", "No procedure exists at the requested address: " + value);
|
|
1651
|
+
return function;
|
|
1611
1652
|
}
|
|
1612
1653
|
|
|
1613
1654
|
private JsonObject nativeApiBoundary(
|
|
@@ -2530,21 +2571,32 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
2530
2571
|
}
|
|
2531
2572
|
|
|
2532
2573
|
private List<Reference> collectReferences(
|
|
2533
|
-
|
|
2574
|
+
Function function,
|
|
2534
2575
|
String direction) throws Exception {
|
|
2576
|
+
// References can target instruction interiors or originate in embedded
|
|
2577
|
+
// data. Use actual body ownership, including an external's exact entry.
|
|
2578
|
+
AddressSet scope = new AddressSet(function.getBody());
|
|
2579
|
+
scope.add(function.getEntryPoint());
|
|
2580
|
+
boolean outgoing = direction.equals("outgoing");
|
|
2581
|
+
AddressIterator addresses = outgoing
|
|
2582
|
+
? currentProgram.getReferenceManager().getReferenceSourceIterator(scope, true)
|
|
2583
|
+
: currentProgram.getReferenceManager().getReferenceDestinationIterator(scope, true);
|
|
2535
2584
|
TreeMap<String, Reference> observed = new TreeMap<>();
|
|
2536
|
-
|
|
2585
|
+
while (addresses.hasNext()) {
|
|
2537
2586
|
monitor.checkCancelled();
|
|
2538
|
-
|
|
2587
|
+
Address address = addresses.next();
|
|
2588
|
+
if (outgoing) {
|
|
2539
2589
|
for (Reference reference : currentProgram.getReferenceManager()
|
|
2540
|
-
.getReferencesFrom(
|
|
2590
|
+
.getReferencesFrom(address)) {
|
|
2591
|
+
monitor.checkCancelled();
|
|
2541
2592
|
addReference(observed, reference);
|
|
2542
2593
|
}
|
|
2543
2594
|
}
|
|
2544
2595
|
else {
|
|
2545
2596
|
ReferenceIterator iterator = currentProgram.getReferenceManager()
|
|
2546
|
-
.getReferencesTo(
|
|
2597
|
+
.getReferencesTo(address);
|
|
2547
2598
|
while (iterator.hasNext()) {
|
|
2599
|
+
monitor.checkCancelled();
|
|
2548
2600
|
addReference(observed, iterator.next());
|
|
2549
2601
|
}
|
|
2550
2602
|
}
|
|
@@ -2944,10 +2996,46 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
2944
2996
|
return parseReaAddress(requireString(params, name));
|
|
2945
2997
|
}
|
|
2946
2998
|
|
|
2999
|
+
private static boolean isExplicitReaAddress(String value) {
|
|
3000
|
+
if (value.regionMatches(true, 0, "0x", 0, 2) &&
|
|
3001
|
+
isHexadecimal(value, 2, value.length()))
|
|
3002
|
+
return true;
|
|
3003
|
+
int separator = value.toLowerCase(Locale.ROOT).lastIndexOf(":0x");
|
|
3004
|
+
if (separator <= 0 || !isHexadecimal(value, separator + 3, value.length()))
|
|
3005
|
+
return false;
|
|
3006
|
+
// Classify the encoded space iteratively. A repeated regex alternation
|
|
3007
|
+
// can exhaust Java's stack on a long ordinary symbol name.
|
|
3008
|
+
for (int index = 0; index < separator; index++) {
|
|
3009
|
+
char item = value.charAt(index);
|
|
3010
|
+
if ((item >= 'A' && item <= 'Z') ||
|
|
3011
|
+
(item >= 'a' && item <= 'z') ||
|
|
3012
|
+
(item >= '0' && item <= '9') ||
|
|
3013
|
+
item == '.' || item == '_' || item == '~' || item == '-')
|
|
3014
|
+
continue;
|
|
3015
|
+
if (item != '%' || index + 2 >= separator ||
|
|
3016
|
+
!isHexadecimal(value, index + 1, index + 3))
|
|
3017
|
+
return false;
|
|
3018
|
+
index += 2;
|
|
3019
|
+
}
|
|
3020
|
+
return true;
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
private static boolean isHexadecimal(String value, int start, int end) {
|
|
3024
|
+
if (start >= end) return false;
|
|
3025
|
+
for (int index = start; index < end; index++) {
|
|
3026
|
+
char item = value.charAt(index);
|
|
3027
|
+
if (!((item >= '0' && item <= '9') ||
|
|
3028
|
+
(item >= 'a' && item <= 'f') ||
|
|
3029
|
+
(item >= 'A' && item <= 'F')))
|
|
3030
|
+
return false;
|
|
3031
|
+
}
|
|
3032
|
+
return true;
|
|
3033
|
+
}
|
|
3034
|
+
|
|
2947
3035
|
private Address parseReaAddress(String value) {
|
|
2948
3036
|
Address address = tryParseAddress(value);
|
|
2949
3037
|
if (address == null) {
|
|
2950
|
-
throw new RequestFailure("invalid_request", "Unknown or invalid Ghidra address");
|
|
3038
|
+
throw new RequestFailure("invalid_request", "Unknown or invalid Ghidra address: " + value);
|
|
2951
3039
|
}
|
|
2952
3040
|
return address;
|
|
2953
3041
|
}
|
|
@@ -2956,22 +3044,31 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
2956
3044
|
try {
|
|
2957
3045
|
String spaceName = null;
|
|
2958
3046
|
String offset = value;
|
|
2959
|
-
int separator = value.lastIndexOf(":0x");
|
|
3047
|
+
int separator = value.toLowerCase(Locale.ROOT).lastIndexOf(":0x");
|
|
2960
3048
|
if (separator >= 0) {
|
|
2961
3049
|
spaceName = decodeAddressSpace(value.substring(0, separator));
|
|
2962
3050
|
offset = value.substring(separator + 3);
|
|
2963
3051
|
}
|
|
2964
|
-
else if (value.startsWith("0x")) {
|
|
3052
|
+
else if (value.startsWith("0x") || value.startsWith("0X")) {
|
|
2965
3053
|
offset = value.substring(2);
|
|
2966
3054
|
}
|
|
2967
|
-
if (!offset.
|
|
3055
|
+
if (!isHexadecimal(offset, 0, offset.length())) {
|
|
2968
3056
|
return null;
|
|
2969
3057
|
}
|
|
2970
3058
|
AddressSpace space = spaceName == null
|
|
2971
3059
|
? currentProgram.getAddressFactory().getDefaultAddressSpace()
|
|
2972
3060
|
: currentProgram.getAddressFactory().getAddressSpace(spaceName);
|
|
2973
|
-
|
|
2974
|
-
|
|
3061
|
+
if (space == null) return null;
|
|
3062
|
+
Address address = space.getAddress(offset);
|
|
3063
|
+
BigInteger requestedOffset = new BigInteger(offset, 16);
|
|
3064
|
+
BigInteger parsedOffset = new BigInteger(Long.toUnsignedString(address.getOffset()));
|
|
3065
|
+
if (!requestedOffset.equals(parsedOffset))
|
|
3066
|
+
throw new RequestFailure("invalid_request",
|
|
3067
|
+
"Ghidra address offset cannot be represented without truncation in space " +
|
|
3068
|
+
space.getName() + ": requested " + value + ", parsed " + canonicalAddress(address));
|
|
3069
|
+
return address;
|
|
3070
|
+
}
|
|
3071
|
+
catch (RequestFailure failure) { throw failure; }
|
|
2975
3072
|
catch (Exception exception) {
|
|
2976
3073
|
return null;
|
|
2977
3074
|
}
|
|
@@ -3055,9 +3152,29 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
3055
3152
|
);
|
|
3056
3153
|
}
|
|
3057
3154
|
catch (PatternSyntaxException exception) {
|
|
3058
|
-
|
|
3155
|
+
// Java wraps compiler stack exhaustion in PatternSyntaxException
|
|
3156
|
+
// without retaining its cause. This producer reason is not bad syntax.
|
|
3157
|
+
if (exception.getDescription().equals("Stack overflow during pattern compilation"))
|
|
3158
|
+
throw regexStackExhausted(expression, "compiling");
|
|
3159
|
+
throw new RequestFailure("invalid_request", "Invalid regex pattern " + expression + ": " + exception.getDescription() + " at index " + exception.getIndex());
|
|
3160
|
+
}
|
|
3161
|
+
catch (StackOverflowError exhausted) {
|
|
3162
|
+
throw regexStackExhausted(expression, "compiling");
|
|
3059
3163
|
}
|
|
3060
|
-
return value ->
|
|
3164
|
+
return value -> {
|
|
3165
|
+
try {
|
|
3166
|
+
return pattern.matcher(value).find();
|
|
3167
|
+
}
|
|
3168
|
+
catch (StackOverflowError exhausted) {
|
|
3169
|
+
throw regexStackExhausted(expression, "matching");
|
|
3170
|
+
}
|
|
3171
|
+
};
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3174
|
+
private static RequestFailure regexStackExhausted(String expression, String stage) {
|
|
3175
|
+
return new RequestFailure("regex_stack_exhausted",
|
|
3176
|
+
"Ghidra's Java regex engine exhausted its stack while " + stage +
|
|
3177
|
+
" pattern " + expression + ". Use literal mode or simplify the regex; the session remains usable.");
|
|
3061
3178
|
}
|
|
3062
3179
|
|
|
3063
3180
|
private static SessionDescriptor readDescriptor(Path path) throws IOException {
|
|
@@ -3114,7 +3231,7 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
3114
3231
|
private void requireDocument(JsonObject params) {
|
|
3115
3232
|
String document = optionalString(params, "document");
|
|
3116
3233
|
if (document != null && !document.equals(currentProgram.getName())) {
|
|
3117
|
-
throw new RequestFailure("not_found", "Unknown Ghidra Program identity");
|
|
3234
|
+
throw new RequestFailure("not_found", "Unknown Ghidra Program identity: " + document + "; active program: " + currentProgram.getName());
|
|
3118
3235
|
}
|
|
3119
3236
|
}
|
|
3120
3237
|
|
|
@@ -3226,7 +3343,16 @@ public final class ReaGhidraBridge extends HeadlessScript {
|
|
|
3226
3343
|
|
|
3227
3344
|
private static void writeResponse(BufferedWriter writer, JsonObject response) throws IOException {
|
|
3228
3345
|
String encoded = GSON.toJson(response);
|
|
3229
|
-
|
|
3346
|
+
// Gson leaves UTF-16 surrogates literal. Escape them in JSON so even
|
|
3347
|
+
// diagnostics quoting ill-formed caller text remain lossless UTF-8.
|
|
3348
|
+
int start = 0;
|
|
3349
|
+
for (int index = 0; index < encoded.length(); index++) {
|
|
3350
|
+
if (!Character.isSurrogate(encoded.charAt(index))) continue;
|
|
3351
|
+
writer.write(encoded, start, index - start);
|
|
3352
|
+
writer.write("\\u" + Integer.toHexString(encoded.charAt(index)));
|
|
3353
|
+
start = index + 1;
|
|
3354
|
+
}
|
|
3355
|
+
writer.write(encoded, start, encoded.length() - start);
|
|
3230
3356
|
writer.newLine();
|
|
3231
3357
|
writer.flush();
|
|
3232
3358
|
}
|