rea-agents 5.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/README.md +168 -655
  2. package/bridge/android/ReaJadxBridge.java +14 -5
  3. package/bridge/ghidra/ReaGhidraBridge.java +173 -47
  4. package/bridge/hopper_bridge.py +310 -128
  5. package/bridge/mitmproxy/capture.py +208 -0
  6. package/bridge/native/rea_lldb_tracer.py +839 -0
  7. package/bridge/process/ProcessRunTokenReader.swift +297 -0
  8. package/bridge/process/ProcessRunTokenReaderMain.swift +35 -0
  9. package/bridge/pwndbg/core_context.py +101 -0
  10. package/bridge/pwndbg/launch.py +39 -0
  11. package/bridge/pwndbg/launch_impl.py +34 -0
  12. package/bridge/pwntools/decoder_runtime.py +59 -0
  13. package/bridge/pwntools/layout.py +39 -0
  14. package/bridge/pwntools/layout_impl.py +309 -0
  15. package/bridge/pwntools/recorded_crash.py +39 -0
  16. package/bridge/pwntools/recorded_crash_impl.py +147 -0
  17. package/dist/android/JadxConfiguration.js +196 -33
  18. package/dist/android/JadxMcpTransport.js +4 -0
  19. package/dist/android/JadxProtocol.js +6 -0
  20. package/dist/android/JadxProvider.js +20 -2
  21. package/dist/android/JadxSession.js +23 -4
  22. package/dist/application/AnalysisContextQueries.js +8 -35
  23. package/dist/application/AnalysisDocument.js +32 -0
  24. package/dist/application/AppBundleExecutable.js +67 -21
  25. package/dist/application/CallPathTracing.js +19 -3
  26. package/dist/application/CapabilityInventory.js +27 -3
  27. package/dist/application/ClientConfigurationDocument.js +871 -6
  28. package/dist/application/ClientRegistrationIdentity.js +26 -5
  29. package/dist/application/ClientRegistrationStatus.js +29 -14
  30. package/dist/application/DirectAnalysis.js +97 -33
  31. package/dist/application/Doctor.js +4 -2
  32. package/dist/application/DoctorScope.js +25 -13
  33. package/dist/application/EnhancedLiteralTracing.js +22 -25
  34. package/dist/application/EnhancedTools.js +13 -11
  35. package/dist/application/EvidenceBundleFiles.js +24 -12
  36. package/dist/application/FunctionAnalysisEvidence.js +2 -3
  37. package/dist/application/InventoryProjectionEvidence.js +4 -3
  38. package/dist/application/InvestigationProviders.js +3 -2
  39. package/dist/application/JsonFiles.js +50 -28
  40. package/dist/application/ProcedureAddressResolution.js +11 -0
  41. package/dist/application/ReconstructionCoverageService.js +7 -4
  42. package/dist/application/ReconstructionObligationCandidates.js +5 -1
  43. package/dist/application/ReconstructionObligationLedgerService.js +4 -3
  44. package/dist/application/Setup.js +13 -1
  45. package/dist/application/SetupClientConfiguration.js +10 -15
  46. package/dist/application/SetupHost.js +5 -2
  47. package/dist/application/SetupPlan.js +5 -3
  48. package/dist/application/SupportedClients.js +34 -1
  49. package/dist/application/Uninstall.js +4 -3
  50. package/dist/application/Update.js +18 -3
  51. package/dist/application/UpdateRuntime.js +46 -25
  52. package/dist/application/WebModuleTraceService.js +4 -2
  53. package/dist/application/WebNetworkCapturePort.js +1 -0
  54. package/dist/application/WebNetworkCaptureService.js +134 -0
  55. package/dist/application/WebRuntimeService.js +5 -3
  56. package/dist/application/WebScriptExportService.js +2 -2
  57. package/dist/application/WebSourceLocationService.js +4 -2
  58. package/dist/application/WindowsCapabilities.js +1 -1
  59. package/dist/application/WorkflowEvidence.js +82 -0
  60. package/dist/application/binary/AnalysisProviderEvaluation.js +21 -5
  61. package/dist/application/binary/AnalysisProviderRegistry.js +2 -0
  62. package/dist/application/binary/AnalysisSnapshotCache.js +52 -12
  63. package/dist/application/binary/BinarySession.js +131 -76
  64. package/dist/application/binary/BinarySessionOpen.js +19 -6
  65. package/dist/application/binary/BinarySessionRecords.js +45 -3
  66. package/dist/application/binary/BinarySessionStatus.js +17 -1
  67. package/dist/application/binary/CompositeProvider.js +13 -0
  68. package/dist/application/binary/LazyAnalysisProvider.js +3 -0
  69. package/dist/application/binaryDiagnostics/BinaryLayoutPort.js +1 -0
  70. package/dist/application/binaryDiagnostics/BinaryLayoutService.js +59 -0
  71. package/dist/application/binaryDiagnostics/RecordedCrashPort.js +1 -0
  72. package/dist/application/binaryDiagnostics/RecordedCrashService.js +62 -0
  73. package/dist/application/evm/EvmInterfacePort.js +1 -0
  74. package/dist/application/evm/EvmInterfaceService.js +64 -0
  75. package/dist/application/investigation/EvidenceLedger.js +21 -7
  76. package/dist/application/investigation/InvestigationRecords.js +8 -0
  77. package/dist/application/javascript/JavaScriptAnalysisControl.js +34 -0
  78. package/dist/application/javascript/JavaScriptApplicationEvidence.js +25 -5
  79. package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +19 -2
  80. package/dist/application/javascript/JavaScriptApplicationService.js +34 -14
  81. package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +5 -5
  82. package/dist/application/javascript/JavaScriptArtifactAnalysis.js +47 -27
  83. package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +39 -7
  84. package/dist/application/javascript/JavaScriptArtifactGraphDocuments.js +26 -2
  85. package/dist/application/javascript/JavaScriptArtifactPathResolution.js +80 -27
  86. package/dist/application/javascript/JavaScriptArtifactReconstruction.js +33 -12
  87. package/dist/application/javascript/JavaScriptModuleRelationships.js +37 -8
  88. package/dist/application/javascript/JavaScriptRecoveryService.js +4 -2
  89. package/dist/application/javascript/JavaScriptRuntimeObservationService.js +3 -1
  90. package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +3 -3
  91. package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +7 -7
  92. package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +149 -72
  93. package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +14 -15
  94. package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +41 -1
  95. package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +7 -7
  96. package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +5 -9
  97. package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +3 -3
  98. package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +118 -12
  99. package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +3 -3
  100. package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +27 -5
  101. package/dist/application/managed/ManagedApplicationGraphService.js +4 -3
  102. package/dist/application/managed/ManagedMemberComparisonService.js +7 -4
  103. package/dist/application/managed/ManagedNativeVerificationService.js +4 -3
  104. package/dist/application/managed/ManagedReconstructionService.js +4 -3
  105. package/dist/application/{ProcessCli.js → process/ProcessCli.js} +23 -15
  106. package/dist/application/{ProcessEvidence.js → process/ProcessEvidence.js} +8 -7
  107. package/dist/application/workflowInputError.js +18 -0
  108. package/dist/artifacts/ArtifactProvider.js +42 -5
  109. package/dist/artifacts/ArtifactProviderMetadata.js +2 -1
  110. package/dist/artifacts/MachOSliceArtifactReader.js +98 -14
  111. package/dist/artifacts/NativeDmgArtifactReader.js +13 -6
  112. package/dist/artifacts/ZipArtifactReader.js +3 -0
  113. package/dist/artifacts/apple/AppleAssetCatalogAnalysis.js +22 -3
  114. package/dist/artifacts/apple/DylibResolutionReader.js +259 -0
  115. package/dist/artifacts/apple/InterfaceBuilderAnalysis.js +176 -56
  116. package/dist/artifacts/apple/InterfaceBuilderDecodeBudget.js +195 -0
  117. package/dist/artifacts/apple/KeyedArchiveReader.js +36 -22
  118. package/dist/artifacts/apple/MachoLoadCommandReader.js +355 -0
  119. package/dist/artifacts/apple/NibArchive.js +81 -14
  120. package/dist/artifacts/apple/NibViewHierarchy.js +10 -3
  121. package/dist/artifacts/apple/PlistNumberLiterals.js +164 -0
  122. package/dist/{application → artifacts/extraction}/ArtifactExtraction.js +10 -10
  123. package/dist/{application → artifacts/inventory}/ArtifactGraphConstruction.js +16 -11
  124. package/dist/{application → artifacts/inventory}/ArtifactInventory.js +4 -4
  125. package/dist/{application/ArtifactInventory → artifacts/inventory}/classify.js +2 -2
  126. package/dist/{application/ArtifactInventory → artifacts/inventory}/reader.js +5 -5
  127. package/dist/{application/ArtifactInventory → artifacts/inventory}/scanCanonical.js +14 -17
  128. package/dist/{application/ArtifactInventory → artifacts/inventory}/scanReader.js +5 -5
  129. package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +6 -2
  130. package/dist/artifacts/readStableArtifact.js +20 -4
  131. package/dist/browser/CdpCaptureCompleteness.js +2 -0
  132. package/dist/browser/CdpCaptureEventHandlers.js +165 -12
  133. package/dist/browser/CdpCaptureEventTypes.js +5 -1
  134. package/dist/browser/CdpCaptureEvents.js +34 -0
  135. package/dist/browser/CdpConnection.js +30 -11
  136. package/dist/browser/CdpOptionalCommand.js +2 -3
  137. package/dist/browser/CdpPageCapture.js +23 -1
  138. package/dist/browser/PlaywrightElectronActiveActions.js +32 -23
  139. package/dist/browser/PlaywrightElectronActiveProjection.js +141 -0
  140. package/dist/browser/PlaywrightElectronActiveProvider.js +130 -122
  141. package/dist/browser/WebSourceMapFetcher.js +426 -72
  142. package/dist/browser/assets/LocalWebScriptArtifacts.js +2 -2
  143. package/dist/browser/history/CaptureFailures.js +137 -0
  144. package/dist/browser/history/CaptureFormatError.js +10 -0
  145. package/dist/browser/history/CaptureRedaction.js +65 -0
  146. package/dist/browser/history/CaptureRelease.js +17 -0
  147. package/dist/browser/history/HarCapture.js +165 -0
  148. package/dist/browser/history/HarCaptureAdapter.js +20 -0
  149. package/dist/browser/history/HarCaptureProcess.js +57 -0
  150. package/dist/browser/history/HarJson.js +92 -0
  151. package/dist/browser/history/HarSchema.js +72 -0
  152. package/dist/browser/history/HistoricalCaptureDecoder.js +188 -0
  153. package/dist/browser/history/HistoricalCaptureFormatAdapter.js +1 -0
  154. package/dist/browser/history/MitmproxyCaptureAdapter.js +42 -0
  155. package/dist/cli/analysisSelector.js +23 -0
  156. package/dist/cli/applicationCommands.js +2 -3
  157. package/dist/cli/artifactCommands.js +26 -1
  158. package/dist/cli/binaryDiagnosticsCommands.js +39 -0
  159. package/dist/cli/coreAnalysisCommands.js +2 -2
  160. package/dist/cli/coreBinaryCommands.js +78 -20
  161. package/dist/cli/electronCommands.js +21 -13
  162. package/dist/cli/evmCommands.js +24 -0
  163. package/dist/cli/firmwareCommands.js +6 -3
  164. package/dist/cli/javascriptApplicationAnalysis.js +20 -3
  165. package/dist/cli/jsonOutput.js +38 -0
  166. package/dist/cli/nativeCallCommands.js +34 -0
  167. package/dist/cli/processCommands.js +1 -1
  168. package/dist/cli/streamedJsonOutput.js +56 -0
  169. package/dist/cli/utilityCommands.js +2 -0
  170. package/dist/cli/webNetworkCaptureCommands.js +40 -0
  171. package/dist/cli/webRuntimeCommands.js +8 -8
  172. package/dist/cli.js +11 -4
  173. package/dist/cliBrowserScenarioCommands.js +2 -2
  174. package/dist/cliCommandNames.js +6 -1
  175. package/dist/cliJsonInput.js +35 -1
  176. package/dist/cliOutput.js +21 -6
  177. package/dist/composition/binaryDiagnostics.js +8 -0
  178. package/dist/composition/evm.js +4 -0
  179. package/dist/composition/webNetworkCaptures.js +6 -0
  180. package/dist/config/environment.js +4 -0
  181. package/dist/config/ghidraStartupTimeout.js +17 -0
  182. package/dist/config/mcpResponseBudget.js +22 -0
  183. package/dist/config/parseConfig.js +2 -1
  184. package/dist/contracts/artifactToolContracts.js +6 -0
  185. package/dist/contracts/browserCaptureToolInputSchema.js +43 -0
  186. package/dist/contracts/browserToolContracts.js +4 -3
  187. package/dist/contracts/enhancedInputs.js +5 -3
  188. package/dist/contracts/enhancedToolContracts.js +3 -3
  189. package/dist/contracts/errorSchemas.js +8 -1
  190. package/dist/contracts/evm/evmToolContracts.js +20 -0
  191. package/dist/contracts/hopperMemoryContracts.js +2 -5
  192. package/dist/contracts/investigationExamples.js +2 -2
  193. package/dist/contracts/javascript/electronToolContracts.js +1 -1
  194. package/dist/contracts/managed/managedToolContracts.js +8 -6
  195. package/dist/contracts/native/binaryDiagnosticsToolContracts.js +42 -0
  196. package/dist/contracts/native/nativeToolContracts.js +21 -3
  197. package/dist/contracts/officialToolContracts.js +26 -24
  198. package/dist/contracts/process/processCaptureExample.js +2 -0
  199. package/dist/contracts/promptContracts.js +3 -3
  200. package/dist/contracts/sessionLifecycleInputs.js +18 -5
  201. package/dist/contracts/sessionStatusContract.js +8 -2
  202. package/dist/contracts/sessionToolContracts.js +8 -3
  203. package/dist/contracts/sessionToolSchemas.js +8 -4
  204. package/dist/contracts/toolContractExamples.js +1 -2
  205. package/dist/contracts/toolContractHelpers.js +4 -1
  206. package/dist/contracts/toolContracts.js +6 -0
  207. package/dist/contracts/toolEffects.js +30 -1
  208. package/dist/contracts/toolOutputSchemaGroups.js +33 -28
  209. package/dist/contracts/toolOutputSchemaPrimitives.js +19 -1
  210. package/dist/contracts/toolSchemaMetadata.js +69 -10
  211. package/dist/contracts/webNetworkCaptureToolContracts.js +24 -0
  212. package/dist/domain/analysisErrorBase.js +22 -2
  213. package/dist/domain/analysisErrorCore.js +61 -5
  214. package/dist/domain/analysisErrorPresentation.js +95 -12
  215. package/dist/domain/analysisErrorProjection.js +148 -19
  216. package/dist/domain/analysisSnapshot.js +166 -2
  217. package/dist/domain/android/androidAnalysis.js +2 -4
  218. package/dist/domain/android/androidApplication.js +17 -9
  219. package/dist/domain/apple/appleApplication.js +41 -14
  220. package/dist/domain/apple/dyldEnvironment.js +73 -0
  221. package/dist/domain/apple/dyldPaths.js +81 -0
  222. package/dist/domain/apple/dylibResolution.js +478 -0
  223. package/dist/domain/apple/dylibResolutionFindings.js +77 -0
  224. package/dist/domain/apple/interfaceBuilderGraph.js +25 -13
  225. package/dist/domain/apple/interfaceBuilderKeyedArchive.js +13 -3
  226. package/dist/domain/apple/keyedArchive.js +9 -1
  227. package/dist/domain/apple/machoContainer.js +54 -0
  228. package/dist/domain/apple/plistNumbers.js +76 -0
  229. package/dist/domain/artifactIdentity.js +29 -0
  230. package/dist/domain/artifactInventoryEvidence.js +19 -24
  231. package/dist/domain/artifactPathSyntax.js +1 -1
  232. package/dist/domain/bridgeCandidateProjection.js +71 -0
  233. package/dist/domain/browserCompleteness.js +1 -0
  234. package/dist/domain/browserObservation.js +1 -1
  235. package/dist/domain/browserObservationError.js +24 -5
  236. package/dist/domain/browserObservationSchemas.js +13 -0
  237. package/dist/domain/browserScenarioValues.js +5 -2
  238. package/dist/domain/bundleComparison.js +3 -2
  239. package/dist/domain/callPathSchemas.js +1 -1
  240. package/dist/domain/canonicalDigest.js +13 -1
  241. package/dist/domain/canonicalJsonDigestSteps.js +133 -0
  242. package/dist/domain/canonicalOrdering.js +9 -5
  243. package/dist/domain/changedBehavior.js +9 -9
  244. package/dist/domain/comparisonSourceEvidence.js +40 -0
  245. package/dist/domain/comparisonStatus.js +2 -30
  246. package/dist/domain/configurationErrors.js +1 -1
  247. package/dist/domain/conformanceTrustGate.js +0 -16
  248. package/dist/domain/evidence.js +78 -11
  249. package/dist/domain/evidenceBundle.js +42 -1
  250. package/dist/domain/evidenceErrors.js +12 -1
  251. package/dist/domain/evm/evmInterface.js +63 -0
  252. package/dist/domain/explicitSensitiveFailure.js +108 -0
  253. package/dist/domain/explicitSensitiveValues.js +10 -0
  254. package/dist/domain/firmware/firmwareAnalysis.js +10 -4
  255. package/dist/domain/hopperErrors.js +23 -2
  256. package/dist/domain/hopperValues.js +51 -8
  257. package/dist/domain/immutableJson.js +114 -0
  258. package/dist/domain/inputIssueProjection.js +3 -0
  259. package/dist/domain/javascript/electronActiveObservation.js +37 -6
  260. package/dist/domain/javascript/electronStaticAnalysisValues.js +6 -12
  261. package/dist/domain/javascript/htmlArtifactReferences.js +40 -0
  262. package/dist/domain/javascript/javascriptApplicationAnalysis.js +71 -23
  263. package/dist/domain/javascript/javascriptApplicationGraph.js +13 -0
  264. package/dist/domain/javascript/javascriptAstValues.js +20 -0
  265. package/dist/domain/javascript/javascriptExportShapeComparison.js +21 -5
  266. package/dist/domain/javascript/javascriptExportShapeVariants.js +0 -10
  267. package/dist/domain/javascript/javascriptRecovery.js +3 -8
  268. package/dist/domain/javascript/javascriptSemanticAnalysis.js +97 -2
  269. package/dist/domain/javascript/javascriptSemanticCoverage.js +6 -5
  270. package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +9 -17
  271. package/dist/domain/javascript/javascriptSemanticDataEffects.js +22 -5
  272. package/dist/domain/javascript/javascriptSemanticGraph.js +34 -5
  273. package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +1 -0
  274. package/dist/domain/javascript/javascriptSemanticPrimitives.js +25 -17
  275. package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -4
  276. package/dist/domain/javascript/javascriptSemanticResourceLimits.js +77 -0
  277. package/dist/domain/javascript/javascriptSemanticValues.js +83 -11
  278. package/dist/domain/javascript/javascriptSourceParser.js +6 -2
  279. package/dist/domain/javascript/javascriptStaticAnalysis.js +22 -17
  280. package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -3
  281. package/dist/domain/javascript/javascriptStaticAnalysisCalls.js +14 -4
  282. package/dist/domain/javascript/javascriptStaticAnalysisFindings.js +66 -7
  283. package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +28 -16
  284. package/dist/domain/javascript/javascriptStaticAnalysisState.js +3 -2
  285. package/dist/domain/jsonSerialization.js +109 -0
  286. package/dist/domain/jsonValue.js +91 -3
  287. package/dist/domain/localPath.js +8 -0
  288. package/dist/domain/managed/managedApplicationGraph.js +10 -10
  289. package/dist/domain/managed/managedInspectionEvidence.js +16 -0
  290. package/dist/domain/managed/managedMemberComparisonMatch.js +5 -9
  291. package/dist/domain/managed/managedNativeVerification.js +3 -9
  292. package/dist/domain/native/binaryLayout.js +357 -0
  293. package/dist/domain/native/fileOffsetPartialObservation.js +1 -0
  294. package/dist/domain/native/nativeCallObservation.js +186 -0
  295. package/dist/domain/native/nativeCallPartialObservation.js +33 -0
  296. package/dist/domain/native/objcSwiftMetadata.js +0 -39
  297. package/dist/domain/native/recordedCrash.js +266 -0
  298. package/dist/domain/native/recordedCrashNoteCoverage.js +73 -0
  299. package/dist/domain/{processCapture.js → process/processCapture.js} +143 -2
  300. package/dist/domain/{processCaptureExample.js → process/processCaptureExample.js} +5 -0
  301. package/dist/domain/process/processCaptureParsing.js +54 -0
  302. package/dist/domain/{processCaptureValidation.js → process/processCaptureValidation.js} +18 -2
  303. package/dist/domain/{processComparison.js → process/processComparison.js} +39 -5
  304. package/dist/domain/{processObservation.js → process/processObservation.js} +1 -1
  305. package/dist/domain/{processScenario.js → process/processScenario.js} +11 -10
  306. package/dist/domain/{processTraceSpecification.js → process/processTraceSpecification.js} +1 -1
  307. package/dist/domain/propertyListKeys.js +1 -1
  308. package/dist/domain/propertyListXmlText.js +19 -0
  309. package/dist/domain/providerAdapterError.js +1 -1
  310. package/dist/domain/providerOperationHealth.js +54 -0
  311. package/dist/domain/providerSelectionError.js +4 -2
  312. package/dist/domain/reconstructionVerification.js +9 -46
  313. package/dist/domain/reconstructionVerificationSchemas.js +3 -3
  314. package/dist/domain/residualUnknown.js +3 -2
  315. package/dist/domain/staticRuntimeCorrelation.js +9 -46
  316. package/dist/domain/webBundleAnalysis.js +20 -8
  317. package/dist/domain/webBundleAnalyzerInspection.js +13 -8
  318. package/dist/domain/webBundleAnalyzerResult.js +41 -2
  319. package/dist/domain/webCaptureDiff.js +1 -0
  320. package/dist/domain/webNetworkCapture.js +118 -0
  321. package/dist/domain/webNetworkCaptureCoordinates.js +58 -0
  322. package/dist/domain/webRuntime.js +19 -5
  323. package/dist/domain/webSourceLocation.js +1 -0
  324. package/dist/dotnet/ManagedExceptionRegionValidation.js +41 -0
  325. package/dist/dotnet/ManagedMemberInspector.js +4 -2
  326. package/dist/dotnet/ManagedMemberInspectorCore.js +38 -32
  327. package/dist/dotnet/ManagedMemberInstructionDecoder.js +23 -7
  328. package/dist/dotnet/ManagedMemberRows.js +14 -3
  329. package/dist/dotnet/ManagedMetadataHeaps.js +20 -2
  330. package/dist/dotnet/ManagedMetadataInventory.js +38 -28
  331. package/dist/dotnet/ManagedMetadataInventoryRows.js +24 -10
  332. package/dist/dotnet/ManagedMethodBodyReader.js +7 -1
  333. package/dist/dotnet/ManagedNativeBoundaryHelpers.js +15 -3
  334. package/dist/dotnet/ManagedNativeBoundaryInspector.js +3 -1
  335. package/dist/dotnet/ManagedPeReader.js +11 -0
  336. package/dist/evm/EvmBytecodeCarrier.js +21 -0
  337. package/dist/evm/EvmWorkerLimits.js +40 -0
  338. package/dist/evm/EvmoleFailures.js +126 -0
  339. package/dist/evm/EvmoleInterfaceAdapter.js +53 -0
  340. package/dist/evm/EvmoleInterfaceProvider.js +273 -0
  341. package/dist/evm/EvmoleInterfaceWorker.js +87 -0
  342. package/dist/evm/EvmoleRelease.js +16 -0
  343. package/dist/firmware/FirmwareCommand.js +1 -0
  344. package/dist/firmware/FirmwareFiles.js +1 -1
  345. package/dist/generatedPackageMetadata.js +2 -2
  346. package/dist/ghidra/GhidraAnalysisProfile.js +5 -0
  347. package/dist/ghidra/GhidraClient.js +47 -14
  348. package/dist/ghidra/GhidraDiagnostics.js +7 -7
  349. package/dist/ghidra/GhidraFunctionValues.js +10 -7
  350. package/dist/ghidra/GhidraInstallation.js +18 -21
  351. package/dist/ghidra/GhidraInventoryValues.js +14 -4
  352. package/dist/ghidra/GhidraJavaLaunch.js +62 -0
  353. package/dist/ghidra/GhidraLauncher.js +34 -16
  354. package/dist/ghidra/GhidraProvider.js +2 -2
  355. package/dist/ghidra/GhidraProviderCapabilities.js +15 -3
  356. package/dist/ghidra/GhidraProviderClient.js +23 -12
  357. package/dist/ghidra/GhidraSessionError.js +11 -7
  358. package/dist/ghidra/GhidraTargetSnapshot.js +47 -12
  359. package/dist/ghidra/GhidraTransport.js +20 -0
  360. package/dist/hopper/BridgeLauncher.js +33 -11
  361. package/dist/hopper/HopperAnalysisProfile.js +62 -4
  362. package/dist/hopper/HopperCleanup.js +15 -3
  363. package/dist/hopper/HopperClient.js +222 -14
  364. package/dist/hopper/HopperFileOffset.js +237 -0
  365. package/dist/hopper/HopperMachOImage.js +196 -0
  366. package/dist/hopper/HopperOperationStage.js +6 -0
  367. package/dist/hopper/HopperProvider.js +63 -9
  368. package/dist/hopper/HopperProviderCapabilities.js +19 -1
  369. package/dist/hopper/HopperRegexSearch.js +137 -0
  370. package/dist/hopper/HopperRegexWorker.js +27 -0
  371. package/dist/hopper/HopperRequestQueue.js +68 -19
  372. package/dist/hopper/HopperTargetLease.js +3 -2
  373. package/dist/hopper/LinuxPrivateDisplayProbe.js +4 -2
  374. package/dist/inspector/JavaScriptRuntimeScope.js +9 -1
  375. package/dist/inspector/V8InspectorCaptureProjection.js +8 -3
  376. package/dist/inspector/V8InspectorProvider.js +47 -11
  377. package/dist/javascript/recovery/WakaruCommand.js +3 -0
  378. package/dist/javascript/sourceMaps/DecodedSourceMap.js +47 -0
  379. package/dist/javascript/sourceMaps/SourceMapCommand.js +17 -0
  380. package/dist/javascript/sourceMaps/SourceMapFormat.js +79 -31
  381. package/dist/javascript/sourceMaps/TraceSourceMap.js +14 -28
  382. package/dist/mcpDoctor.js +62 -2
  383. package/dist/native/AppleDispatchCoverage.js +47 -6
  384. package/dist/native/AppleDispatchDecodeFacts.js +6 -0
  385. package/dist/native/AppleDispatchMetadata.js +6 -3
  386. package/dist/native/AppleMachoFixups.js +48 -24
  387. package/dist/native/AppleMachoSelection.js +32 -16
  388. package/dist/native/AppleObjcCategories.js +6 -2
  389. package/dist/native/AppleObjcDispatchFacets.js +5 -2
  390. package/dist/native/AppleObjcProperties.js +2 -1
  391. package/dist/native/AppleSwiftDispatchFacets.js +27 -21
  392. package/dist/native/AppleSwiftVtables.js +21 -15
  393. package/dist/native/CommandRunner.js +82 -84
  394. package/dist/native/LldbCallTracer.js +541 -0
  395. package/dist/native/LldbRetainedObservations.js +178 -0
  396. package/dist/native/NativeCallObservation.js +194 -0
  397. package/dist/native/NativeMacOSProvider.js +117 -20
  398. package/dist/native/NativeMacOSProviderMetadata.js +8 -3
  399. package/dist/native/SignatureTargetBinding.js +155 -0
  400. package/dist/native/parsers/lipo.js +71 -1
  401. package/dist/native/pwndbg/PwndbgCoreContext.js +180 -0
  402. package/dist/native/pwntools/PwntoolsDecoder.js +203 -0
  403. package/dist/native/pwntools/PwntoolsFailures.js +180 -0
  404. package/dist/native/pwntools/PwntoolsLayoutProvider.js +36 -0
  405. package/dist/native/pwntools/PwntoolsRecordedCrashProvider.js +75 -0
  406. package/dist/native/pwntools/PwntoolsRelease.js +19 -0
  407. package/dist/native/pwntools/PwntoolsResourceLimits.js +76 -0
  408. package/dist/native/pwntools/RecordedCrashSourceBindings.js +46 -0
  409. package/dist/native/pwntools/RecordedCrashStructureBindings.js +103 -0
  410. package/dist/process/DarwinProcessRunTokenReader.js +293 -0
  411. package/dist/process/ExecFileOutput.js +20 -0
  412. package/dist/process/OwnedCommand.js +118 -0
  413. package/dist/process/ProcessOwnership.js +431 -51
  414. package/dist/process/ProcessOwnershipObservation.js +209 -27
  415. package/dist/process/ProviderProcess.js +68 -10
  416. package/dist/{application → process/capture}/ProcessCaptureCapability.js +15 -0
  417. package/dist/{application → process/capture}/ProcessCaptureError.js +18 -2
  418. package/dist/process/capture/ProcessCaptureLifecycle.js +681 -0
  419. package/dist/{application → process/capture}/ProcessHarness.js +195 -29
  420. package/dist/{application → process/capture}/ProcessSampling.js +2 -2
  421. package/dist/server/EvidenceMcpServer.js +146 -0
  422. package/dist/server/createServer.js +37 -8
  423. package/dist/server/promptCompletion.js +10 -3
  424. package/dist/server/registerAndroidTools.js +2 -4
  425. package/dist/server/registerApplicationTools/helpers.js +2 -4
  426. package/dist/server/registerArtifactComparisonTool.js +11 -7
  427. package/dist/server/registerBinaryDiagnosticsTools.js +15 -0
  428. package/dist/server/registerBrowserScenarioTool.js +2 -4
  429. package/dist/server/registerBrowserTools.js +2 -4
  430. package/dist/server/registerBundleComparisonTool.js +2 -3
  431. package/dist/server/registerCloseLifecycleTool.js +8 -18
  432. package/dist/server/registerElectronTools.js +2 -4
  433. package/dist/server/registerEnhancedTools.js +18 -59
  434. package/dist/server/registerEvidenceTools.js +3 -5
  435. package/dist/server/registerEvmTools.js +15 -0
  436. package/dist/server/registerFirmwareTools.js +2 -4
  437. package/dist/server/registerFunctionComparisonTool.js +10 -6
  438. package/dist/server/registerInvestigationTools.js +7 -7
  439. package/dist/server/registerJavaScriptRecoveryTool.js +2 -4
  440. package/dist/server/registerJavaScriptRuntimeObservationTools.js +2 -4
  441. package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +2 -4
  442. package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +2 -4
  443. package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +2 -4
  444. package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +2 -4
  445. package/dist/server/registerOfficialTools.js +2 -4
  446. package/dist/server/registerProcessComparisonTool.js +72 -46
  447. package/dist/server/registerRecordedCrashTools.js +15 -0
  448. package/dist/server/registerSessionRecordTools.js +5 -6
  449. package/dist/server/registerSessionStatusTool.js +17 -3
  450. package/dist/server/registerSessionTools.js +13 -5
  451. package/dist/server/registerWebModuleTool.js +2 -4
  452. package/dist/server/registerWebNetworkCaptureTool.js +26 -0
  453. package/dist/server/registerWebRuntimeTools.js +3 -7
  454. package/dist/server/registerWebScriptTool.js +2 -4
  455. package/dist/server/registerWebSourceLocationTool.js +2 -4
  456. package/dist/server/runDerivedOperation.js +15 -3
  457. package/dist/server/sessionAvailabilityPolicy.js +3 -1
  458. package/dist/server/sessionToolPolicies.js +1 -1
  459. package/dist/server/toolRegistrationOptions.js +2 -2
  460. package/dist/server/toolResult.js +63 -11
  461. package/dist/server/toolResultEncoding.js +33 -0
  462. package/install.sh +1 -1
  463. package/native/windows/build/manifest.json +2 -2
  464. package/native/windows/build/rea-windows-x64.node +0 -0
  465. package/package.json +42 -9
  466. package/scripts/electron-active-hook-boundaries.cjs +18 -20
  467. package/scripts/electron-active-hook.cjs +241 -37
  468. package/scripts/rea.mjs +11 -3
  469. package/skills/reverse-engineer-anything/SKILL.md +32 -4
  470. package/skills/reverse-engineer-anything/references/javascript-applications.md +8 -1
  471. package/skills/reverse-engineer-anything/references/native-and-artifacts.md +29 -0
  472. package/third_party/README.md +60 -0
  473. package/third_party/evmole/LICENSE +21 -0
  474. package/third_party/evmole/README.md +22 -0
  475. package/third_party/pwndbg/LICENSE.md +21 -0
  476. package/third_party/pwndbg/README.md +23 -0
  477. package/third_party/pwntools/README.md +40 -0
  478. package/dist/application/AuthorizedArtifactInventory.js +0 -7
  479. package/dist/application/ProcessCaptureLifecycle.js +0 -299
  480. package/dist/application/StoreFileLock.js +0 -124
  481. package/dist/contracts/processCaptureExample.js +0 -2
  482. package/dist/domain/bytecodeProvider.js +0 -178
  483. package/dist/domain/customProtocolCapture.js +0 -137
  484. package/dist/domain/eventProcessTree.js +0 -225
  485. package/dist/domain/mobileApplicationInvestigation.js +0 -159
  486. package/dist/domain/packageAnalysis.js +0 -123
  487. package/dist/domain/peInspection.js +0 -197
  488. package/dist/domain/processCaptureParsing.js +0 -21
  489. package/dist/domain/protocolCapture.js +0 -217
  490. package/dist/domain/runtimeIdentification.js +0 -212
  491. package/dist/generatedMcpToolCatalog.js +0 -37
  492. package/dist/ghidra/GhidraDefaults.js +0 -2
  493. /package/dist/application/{ArtifactExtractionDestination.js → artifacts/ArtifactExtractionDestination.js} +0 -0
  494. /package/dist/{application/ArtifactInventory → artifacts/inventory}/policy.js +0 -0
  495. /package/dist/{application/ArtifactInventory → artifacts/inventory}/types.js +0 -0
  496. /package/dist/domain/{processEvidenceProvider.js → process/processEvidenceProvider.js} +0 -0
  497. /package/dist/domain/{processTraceComparison.js → process/processTraceComparison.js} +0 -0
  498. /package/dist/domain/{processTraceDimensionProjection.js → process/processTraceDimensionProjection.js} +0 -0
  499. /package/dist/domain/{processTraceEvaluation.js → process/processTraceEvaluation.js} +0 -0
  500. /package/dist/{application → process/capture}/FilesystemSnapshot.js +0 -0
  501. /package/dist/{application → process/capture}/ProcessCaptureEnvironment.js +0 -0
  502. /package/dist/{application → process/capture}/ProcessCaptureJournal.js +0 -0
  503. /package/dist/{application → process/capture}/ProcessFilesystemEffects.js +0 -0
  504. /package/dist/{application → process/capture}/ProcessNormalization.js +0 -0
  505. /package/dist/{application → process/capture}/ProcessScenarioRuntimeValidation.js +0 -0
  506. /package/dist/{application → process/capture}/ProcessTimer.js +0 -0
  507. /package/dist/{application → process/capture}/TerminalRenderer.js +0 -0
@@ -0,0 +1,237 @@
1
+ import { createHash } from "node:crypto";
2
+ import { constants } from "node:fs";
3
+ import { open } from "node:fs/promises";
4
+ import { z } from "zod";
5
+ import { AnalysisAccessDeniedError, AnalysisArtifactChangedError, AnalysisCancelledError, AnalysisCapabilityUnavailableError, AnalysisOutputError, } from "../domain/analysisErrorCore.js";
6
+ import { BinaryTargetError } from "../domain/configurationErrors.js";
7
+ import { readFatSliceDeclarations, validateFatSlice, } from "../domain/apple/machoContainer.js";
8
+ import { err, ok } from "../domain/result.js";
9
+ const OPERATION = "address_to_file_offset";
10
+ const MAX_FAT_ARCHITECTURES = 128;
11
+ const PREFIX_BYTES = 8 + MAX_FAT_ARCHITECTURES * 32;
12
+ const observationSchema = z.strictObject({
13
+ address: z.string().regex(/^0x[0-9a-f]+$/u),
14
+ provider_file_offset: z
15
+ .number()
16
+ .int()
17
+ .nonnegative()
18
+ .max(Number.MAX_SAFE_INTEGER),
19
+ provider_source_path: z.string().nullable(),
20
+ provider_image_header_hex: z
21
+ .string()
22
+ .regex(/^[a-f0-9]{24}$/u)
23
+ .nullable(),
24
+ });
25
+ /** Bind native image-relative offsets to coordinates in the admitted source bytes. */
26
+ export async function mapHopperFileOffset(target, value, signal) {
27
+ const parsed = observationSchema.safeParse(value);
28
+ if (!parsed.success)
29
+ return err(new AnalysisOutputError(OPERATION, "Hopper's native file mapping observation is malformed"));
30
+ const observation = parsed.data;
31
+ const partial = (reason) => ({
32
+ operation: OPERATION,
33
+ ...observation,
34
+ original_file_offset: { available: false, reason },
35
+ });
36
+ const unavailable = (reason) => err(new AnalysisCapabilityUnavailableError("hopper", OPERATION, reason, {
37
+ partialObservation: partial(reason),
38
+ }));
39
+ if (target.kind !== "executable")
40
+ return unavailable("The selected database digest does not identify its original executable bytes. Open that executable to verify original-file coordinates; read_bytes still exposes the database's native bytes.");
41
+ if (signal?.aborted)
42
+ return err(new AnalysisCancelledError(OPERATION, {
43
+ partialObservation: partial("Source verification was cancelled"),
44
+ }));
45
+ try {
46
+ const captured = await snapshotFromPath(target.path, signal);
47
+ if (!captured.ok)
48
+ return err(new AnalysisArtifactChangedError(OPERATION, target.path, captured.error, {
49
+ partialObservation: partial(captured.error),
50
+ }));
51
+ const snapshot = captured.value;
52
+ if (signal?.aborted)
53
+ return err(new AnalysisCancelledError(OPERATION, {
54
+ partialObservation: partial("Source verification was cancelled"),
55
+ }));
56
+ if (snapshot.sha256 !== target.sha256) {
57
+ const reason = `Source ${target.path} differs from the admitted artifact: expected SHA-256 ${target.sha256}, observed ${snapshot.sha256}. Reopen the changed source for a new analysis identity.`;
58
+ return err(new AnalysisArtifactChangedError(OPERATION, target.path, reason, {
59
+ partialObservation: partial(reason),
60
+ }));
61
+ }
62
+ const mapped = originalOffset(snapshot, observation);
63
+ if (!mapped.ok)
64
+ return unavailable(mapped.error);
65
+ return ok({
66
+ address: observation.address,
67
+ file_offset: mapped.value + observation.provider_file_offset,
68
+ provider_file_offset: observation.provider_file_offset,
69
+ image_base_file_offset: mapped.value,
70
+ source_path: target.path,
71
+ });
72
+ }
73
+ catch (cause) {
74
+ if (signal?.aborted)
75
+ return err(new AnalysisCancelledError(OPERATION, {
76
+ cause,
77
+ partialObservation: partial("Source verification was cancelled"),
78
+ }));
79
+ const reason = `Cannot verify original source bytes: ${cause instanceof Error ? cause.message : String(cause)}`;
80
+ const code = typeof cause === "object" && cause !== null && "code" in cause
81
+ ? cause.code
82
+ : undefined;
83
+ if (code === "EACCES" || code === "EPERM")
84
+ return err(new AnalysisAccessDeniedError(OPERATION, target.path, code, {
85
+ cause,
86
+ partialObservation: partial(reason),
87
+ }));
88
+ return err(new BinaryTargetError(target.path, reason, {
89
+ cause,
90
+ partialObservation: partial(reason),
91
+ }));
92
+ }
93
+ }
94
+ async function snapshotFromPath(path, signal) {
95
+ const file = await open(path, constants.O_RDONLY | constants.O_NONBLOCK);
96
+ try {
97
+ if (!(await file.stat()).isFile())
98
+ return err(`Source ${path} is no longer a regular file. Restore the admitted executable or reopen a regular source.`);
99
+ return ok(await readSourceSnapshot(file, signal));
100
+ }
101
+ finally {
102
+ await file.close();
103
+ }
104
+ }
105
+ function fatLayout(prefix) {
106
+ const magic = prefix.length < 4 ? 0 : prefix.readUInt32BE(0);
107
+ if (![0xcafebabe, 0xbebafeca, 0xcafebabf, 0xbfbafeca].includes(magic))
108
+ return ok(null);
109
+ if (prefix.length < 8)
110
+ return err("The original FAT header is truncated");
111
+ const littleEndian = magic === 0xbebafeca || magic === 0xbfbafeca;
112
+ const wide = magic === 0xcafebabf || magic === 0xbfbafeca;
113
+ const count = littleEndian ? prefix.readUInt32LE(4) : prefix.readUInt32BE(4);
114
+ if (count === 0 || count > MAX_FAT_ARCHITECTURES)
115
+ return err("FAT architecture count is outside the supported 1..128 range");
116
+ const tableEnd = 8 + count * (wide ? 32 : 20);
117
+ const table = prefix.subarray(8, tableEnd);
118
+ const parsed = readFatSliceDeclarations(table, { count, wide, littleEndian });
119
+ if (parsed.status !== "parsed")
120
+ return err(parsed.reason);
121
+ if (wide) {
122
+ for (const slice of parsed.slices)
123
+ if ((littleEndian
124
+ ? table.readUInt32LE(slice.index * 32 + 28)
125
+ : table.readUInt32BE(slice.index * 32 + 28)) !== 0)
126
+ return err(`FAT64 architecture ${slice.index} has a nonzero reserved field`);
127
+ }
128
+ return ok({ slices: parsed.slices, tableEnd });
129
+ }
130
+ async function readSourceSnapshot(file, signal) {
131
+ const prefix = Buffer.alloc(PREFIX_BYTES);
132
+ const hash = createHash("sha256");
133
+ let size = 0;
134
+ let layout;
135
+ const headers = new Map();
136
+ const capture = (bytes, position) => {
137
+ if (layout?.ok !== true || layout.value === null)
138
+ return;
139
+ for (const slice of layout.value.slices) {
140
+ const start = Math.max(position, slice.offset);
141
+ const end = Math.min(position + bytes.length, slice.offset + 12);
142
+ if (end <= start)
143
+ continue;
144
+ let header = headers.get(slice.index);
145
+ if (header === undefined) {
146
+ header = Buffer.alloc(12);
147
+ headers.set(slice.index, header);
148
+ }
149
+ bytes.copy(header, start - slice.offset, start - position, end - position);
150
+ }
151
+ };
152
+ for await (const chunk of file.createReadStream({
153
+ start: 0,
154
+ autoClose: false,
155
+ ...(signal === undefined ? {} : { signal }),
156
+ })) {
157
+ const bytes = Buffer.from(chunk);
158
+ hash.update(bytes);
159
+ if (size < prefix.length)
160
+ bytes.copy(prefix, size, 0, Math.min(bytes.length, prefix.length - size));
161
+ if (layout === undefined && size + bytes.length >= prefix.length) {
162
+ layout = fatLayout(prefix);
163
+ capture(prefix, 0);
164
+ }
165
+ capture(bytes, size);
166
+ size += bytes.length;
167
+ }
168
+ if (layout === undefined) {
169
+ layout = fatLayout(prefix.subarray(0, size));
170
+ capture(prefix.subarray(0, size), 0);
171
+ }
172
+ return { layout, headers, size, sha256: hash.digest("hex") };
173
+ }
174
+ function originalOffset(snapshot, observation) {
175
+ const { layout, size, headers } = snapshot;
176
+ if (!layout.ok)
177
+ return layout;
178
+ if (layout.value === null)
179
+ return observation.provider_file_offset < size
180
+ ? ok(0)
181
+ : err("Provider mapping lies outside the admitted executable bytes");
182
+ const header = observation.provider_image_header_hex === null
183
+ ? null
184
+ : Buffer.from(observation.provider_image_header_hex, "hex");
185
+ const loadedMagic = header?.readUInt32BE(0);
186
+ if (header === null ||
187
+ loadedMagic === undefined ||
188
+ ![0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe].includes(loadedMagic))
189
+ return err("Hopper did not expose the loaded Mach-O header needed to identify its FAT slice");
190
+ const little = loadedMagic === 0xcefaedfe || loadedMagic === 0xcffaedfe;
191
+ const cpu = little ? header.readUInt32LE(4) : header.readUInt32BE(4);
192
+ const subtype = little ? header.readUInt32LE(8) : header.readUInt32BE(8);
193
+ const matches = [];
194
+ const ranges = [...layout.value.slices].sort((a, b) => a.offset - b.offset);
195
+ for (let index = 1; index < ranges.length; index++) {
196
+ const previous = ranges[index - 1];
197
+ const current = ranges[index];
198
+ if (previous !== undefined &&
199
+ current !== undefined &&
200
+ current.offset < previous.offset + previous.size)
201
+ return err("Original FAT slices overlap");
202
+ }
203
+ for (const slice of layout.value.slices) {
204
+ const reason = validateFatSlice(slice, size, layout.value.tableEnd);
205
+ if (reason !== null)
206
+ return err(reason);
207
+ const embedded = headers.get(slice.index);
208
+ if (slice.size < 12 || embedded === undefined)
209
+ return err(`FAT architecture ${slice.index} has a truncated Mach-O header`);
210
+ const embeddedMagic = embedded.readUInt32BE(0);
211
+ if (![0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe].includes(embeddedMagic))
212
+ return err(`FAT architecture ${slice.index} does not contain a Mach-O image`);
213
+ const embeddedLittle = embeddedMagic === 0xcefaedfe || embeddedMagic === 0xcffaedfe;
214
+ const identityError = validateFatSlice(slice, size, layout.value.tableEnd, {
215
+ cpuType: embeddedLittle
216
+ ? embedded.readUInt32LE(4)
217
+ : embedded.readUInt32BE(4),
218
+ cpuSubtype: embeddedLittle
219
+ ? embedded.readUInt32LE(8)
220
+ : embedded.readUInt32BE(8),
221
+ });
222
+ if (identityError !== null)
223
+ return err(identityError);
224
+ if (slice.cpuType === cpu && slice.cpuSubtype === subtype)
225
+ matches.push(slice);
226
+ }
227
+ const selected = matches.length === 1 ? matches[0] : undefined;
228
+ if (selected === undefined)
229
+ return err(`Original FAT slice matching Hopper's loaded header is ${matches.length === 0 ? "missing" : "ambiguous"}`);
230
+ if (headers.get(selected.index)?.equals(header) !== true)
231
+ return err("Original FAT slice header disagrees with Hopper's loaded header");
232
+ if (observation.provider_file_offset >= selected.size)
233
+ return err("Provider mapping lies outside the loaded FAT slice");
234
+ if (!Number.isSafeInteger(selected.offset + observation.provider_file_offset))
235
+ return err("Original file offset exceeds the exact JSON integer range");
236
+ return ok(selected.offset);
237
+ }
@@ -0,0 +1,196 @@
1
+ import { createHash } from "node:crypto";
2
+ import { open } from "node:fs/promises";
3
+ import { z } from "zod";
4
+ import { BinaryTargetError } from "../domain/configurationErrors.js";
5
+ import { AnalysisCancelledError } from "../domain/analysisErrorCore.js";
6
+ import { readFatSliceDeclarations, validateFatSlice, } from "../domain/apple/machoContainer.js";
7
+ import { HopperCancelledError, HopperStartError, } from "../domain/hopperErrors.js";
8
+ import { err, ok } from "../domain/result.js";
9
+ /** Stable source coordinates committed before preparing an owned thin image. */
10
+ export const hopperMachOImageSchema = z.strictObject({
11
+ method: z.literal("fat64_thin_slice"),
12
+ architecture_count: z.number().int().min(1).max(128),
13
+ container_table_sha256: z.string().regex(/^[a-f0-9]{64}$/u),
14
+ source_offset: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
15
+ byte_length: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
16
+ cpu_type: z.number().int().nonnegative(),
17
+ cpu_subtype: z.number().int().nonnegative(),
18
+ });
19
+ /** Validate the selected FAT64 slice without depending on Apple's lipo tool. */
20
+ export const resolveHopperMachOImage = async (target, signal) => {
21
+ const invalid = (reason) => err(new BinaryTargetError(target.path, reason));
22
+ if (signal?.aborted)
23
+ return err(new AnalysisCancelledError("open_binary"));
24
+ let file;
25
+ try {
26
+ file = await open(target.path, "r");
27
+ }
28
+ catch (cause) {
29
+ return invalid(`Cannot read FAT64 source for Hopper image preparation: ${cause instanceof Error ? cause.message : String(cause)}`);
30
+ }
31
+ try {
32
+ const read = async (offset, length) => {
33
+ const bytes = Buffer.alloc(length);
34
+ const { bytesRead } = await file.read(bytes, 0, length, offset);
35
+ return bytes.subarray(0, bytesRead);
36
+ };
37
+ const header = await read(0, 8);
38
+ const magic = header.length === 8 ? header.readUInt32BE(0) : 0;
39
+ if (magic !== 0xcafebabf && magic !== 0xbfbafeca)
40
+ return invalid("FAT64 source header changed before Hopper image preparation");
41
+ const littleEndian = magic === 0xbfbafeca;
42
+ const count = littleEndian
43
+ ? header.readUInt32LE(4)
44
+ : header.readUInt32BE(4);
45
+ const size = (await file.stat()).size;
46
+ const tableEnd = 8 + count * 32;
47
+ if (count === 0 || count > 128 || tableEnd > size)
48
+ return invalid("FAT64 architecture table is truncated or exceeds the supported 128 entries");
49
+ const table = await read(8, count * 32);
50
+ const parsed = readFatSliceDeclarations(table, {
51
+ count,
52
+ wide: true,
53
+ littleEndian,
54
+ });
55
+ if (parsed.status === "malformed")
56
+ return invalid(parsed.reason);
57
+ const cpuTypes = { x86: 7, x86_64: 0x1000007, arm: 12, arm64: 0x100000c };
58
+ const matches = [];
59
+ const ranges = [];
60
+ for (const slice of parsed.slices) {
61
+ if (signal?.aborted)
62
+ return err(new AnalysisCancelledError("open_binary"));
63
+ const rangeError = validateFatSlice(slice, size, tableEnd);
64
+ if (rangeError !== null)
65
+ return invalid(rangeError);
66
+ const reserved = littleEndian
67
+ ? table.readUInt32LE(slice.index * 32 + 28)
68
+ : table.readUInt32BE(slice.index * 32 + 28);
69
+ if (reserved !== 0)
70
+ return invalid(`FAT64 architecture ${slice.index} has a nonzero reserved field`);
71
+ if (slice.size < 12)
72
+ return invalid(`FAT64 architecture ${slice.index} has a truncated Mach-O header`);
73
+ const embedded = await read(slice.offset, 12);
74
+ if (embedded.length !== 12)
75
+ return invalid(`FAT64 architecture ${slice.index} became truncated`);
76
+ const thinMagic = embedded.readUInt32BE(0);
77
+ if (![0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe].includes(thinMagic))
78
+ return invalid(`FAT64 architecture ${slice.index} does not contain a Mach-O image`);
79
+ const little = thinMagic === 0xcefaedfe || thinMagic === 0xcffaedfe;
80
+ const identity = {
81
+ cpuType: little ? embedded.readUInt32LE(4) : embedded.readUInt32BE(4),
82
+ cpuSubtype: little
83
+ ? embedded.readUInt32LE(8)
84
+ : embedded.readUInt32BE(8),
85
+ };
86
+ const identityError = validateFatSlice(slice, size, tableEnd, identity);
87
+ if (identityError !== null)
88
+ return invalid(identityError);
89
+ ranges.push(slice);
90
+ if (slice.cpuType === cpuTypes[target.architecture])
91
+ matches.push(slice);
92
+ }
93
+ ranges.sort((a, b) => a.offset - b.offset);
94
+ for (let index = 1; index < ranges.length; index++) {
95
+ const previous = ranges[index - 1];
96
+ const current = ranges[index];
97
+ if (previous !== undefined &&
98
+ current !== undefined &&
99
+ current.offset < previous.offset + previous.size)
100
+ return invalid("FAT64 slices overlap");
101
+ }
102
+ const selected = matches.length === 1 ? matches[0] : undefined;
103
+ if (selected === undefined)
104
+ return invalid(`FAT64 selection for ${target.architecture} is ${matches.length === 0 ? "missing" : "ambiguous"}; extract the exact architecture into a thin image before opening it`);
105
+ return ok({
106
+ method: "fat64_thin_slice",
107
+ architecture_count: count,
108
+ container_table_sha256: createHash("sha256")
109
+ .update(header)
110
+ .update(table)
111
+ .digest("hex"),
112
+ source_offset: selected.offset,
113
+ byte_length: selected.size,
114
+ cpu_type: selected.cpuType,
115
+ cpu_subtype: selected.cpuSubtype,
116
+ });
117
+ }
118
+ catch (cause) {
119
+ return invalid(`Cannot validate FAT64 image: ${cause instanceof Error ? cause.message : String(cause)}`);
120
+ }
121
+ finally {
122
+ await file.close();
123
+ }
124
+ };
125
+ /** Copy a selected slice and verify the entire original source in the same pass. */
126
+ export const prepareHopperMachOImage = async (sourcePath, sourceSha256, image, destination, signal) => {
127
+ if (signal?.aborted)
128
+ return err(new HopperCancelledError());
129
+ try {
130
+ const source = await open(sourcePath, "r");
131
+ try {
132
+ const output = await open(destination, "wx", 0o600);
133
+ try {
134
+ const hash = createHash("sha256");
135
+ const tableHash = createHash("sha256");
136
+ const tableEnd = 8 + image.architecture_count * 32;
137
+ const thinHeader = [];
138
+ let position = 0;
139
+ let copied = 0;
140
+ for await (const chunk of source.createReadStream({
141
+ autoClose: false,
142
+ })) {
143
+ if (signal?.aborted)
144
+ return err(new HopperCancelledError());
145
+ const bytes = Buffer.from(chunk);
146
+ hash.update(bytes);
147
+ if (position < tableEnd)
148
+ tableHash.update(bytes.subarray(0, Math.min(bytes.length, tableEnd - position)));
149
+ const start = Math.max(0, image.source_offset - position);
150
+ const end = Math.min(bytes.length, image.source_offset + image.byte_length - position);
151
+ if (end > start) {
152
+ if (copied < 12)
153
+ thinHeader.push(bytes.subarray(start, Math.min(end, start + 12 - copied)));
154
+ await output.writeFile(bytes.subarray(start, end));
155
+ copied += end - start;
156
+ }
157
+ position += bytes.length;
158
+ }
159
+ const observed = hash.digest("hex");
160
+ const header = Buffer.concat(thinHeader);
161
+ const magic = header.length === 12 ? header.readUInt32BE(0) : 0;
162
+ const little = magic === 0xcefaedfe || magic === 0xcffaedfe;
163
+ const headerMatches = header.length === 12 &&
164
+ [0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe].includes(magic) &&
165
+ (little ? header.readUInt32LE(4) : header.readUInt32BE(4)) ===
166
+ image.cpu_type &&
167
+ (little ? header.readUInt32LE(8) : header.readUInt32BE(8)) ===
168
+ image.cpu_subtype;
169
+ if (tableHash.digest("hex") !== image.container_table_sha256 ||
170
+ !headerMatches)
171
+ return err(new HopperStartError({
172
+ userMessage: `FAT64 source ${sourcePath} no longer agrees with its committed architecture table or selected Mach-O header. Open the stable source again.`,
173
+ }));
174
+ if (observed !== sourceSha256 || copied !== image.byte_length)
175
+ return err(new HopperStartError({
176
+ userMessage: `FAT64 source ${sourcePath} changed before launch: expected SHA-256 ${sourceSha256}, observed ${observed}; copied ${copied} of ${image.byte_length} selected bytes. Open the stable source again.`,
177
+ }));
178
+ return ok(destination);
179
+ }
180
+ finally {
181
+ await output.close();
182
+ }
183
+ }
184
+ finally {
185
+ await source.close();
186
+ }
187
+ }
188
+ catch (cause) {
189
+ return signal?.aborted
190
+ ? err(new HopperCancelledError())
191
+ : err(new HopperStartError({
192
+ cause,
193
+ userMessage: `Cannot prepare the selected FAT64 image from ${sourcePath}: ${cause instanceof Error ? cause.message : String(cause)}`,
194
+ }));
195
+ }
196
+ };
@@ -0,0 +1,6 @@
1
+ /** Classify Hopper wire operations at their provider boundary. */
2
+ export const hopperOperationStage = (operation) => {
3
+ if (operation === "health")
4
+ return "connection";
5
+ return operation === "procedure_pseudo_code" ? "decompilation" : "analysis";
6
+ };
@@ -5,7 +5,10 @@ import { AnalysisCapabilityUnavailableError } from "../domain/analysisErrorCore.
5
5
  import { err } from "../domain/result.js";
6
6
  import { HopperApplicationLauncher } from "./BridgeLauncher.js";
7
7
  import { hopperLoaderArgsForTarget, resolveHopperAnalysisProfile, } from "./HopperAnalysisProfile.js";
8
+ import { mapHopperFileOffset } from "./HopperFileOffset.js";
9
+ import { HopperRegexSearch } from "./HopperRegexSearch.js";
8
10
  import { HopperClient } from "./HopperClient.js";
11
+ import { hopperMachOImageSchema } from "./HopperMachOImage.js";
9
12
  import { CAPABILITIES, HOPPER_PROVIDER_IDENTITY, } from "./HopperProviderCapabilities.js";
10
13
  export { HOPPER_PROVIDER_IDENTITY, HOPPER_OPERATIONS, } from "./HopperProviderCapabilities.js";
11
14
  const IDENTITY = HOPPER_PROVIDER_IDENTITY;
@@ -111,7 +114,22 @@ export class HopperProvider {
111
114
  execute: (operation) => Promise.resolve(err(new AnalysisCapabilityUnavailableError(IDENTITY.id, operation, `Hopper cannot open ${target.kind} targets directly. Inventory or extract the artifact first.`))),
112
115
  close: () => Promise.resolve(),
113
116
  };
114
- const derivedLoaderArgs = hopperLoaderArgsForTarget(target);
117
+ const preparation = profile?.parameters.prepared_image;
118
+ const parsedImage = preparation === undefined
119
+ ? undefined
120
+ : hopperMachOImageSchema.safeParse(preparation);
121
+ if (parsedImage?.success === false)
122
+ return {
123
+ execute: (operation) => Promise.resolve(err(new AnalysisCapabilityUnavailableError(IDENTITY.id, operation, "Hopper prepared-image profile is malformed; resolve the analysis profile again."))),
124
+ close: () => Promise.resolve(),
125
+ };
126
+ const preparedImage = parsedImage?.data;
127
+ const container = preparedImage === undefined
128
+ ? profile?.parameters.macho_container
129
+ : "thin";
130
+ const derivedLoaderArgs = hopperLoaderArgsForTarget(target, container === "thin" || container === "fat32" || container === "fat64"
131
+ ? container
132
+ : undefined);
115
133
  if (!derivedLoaderArgs.ok)
116
134
  return {
117
135
  execute: () => Promise.resolve(err(derivedLoaderArgs.error)),
@@ -123,6 +141,14 @@ export class HopperProvider {
123
141
  launcherPath: this.config.hopperLauncherPath,
124
142
  targetPath: target.path,
125
143
  targetKind: target.kind,
144
+ ...(preparedImage === undefined
145
+ ? {}
146
+ : {
147
+ preparedImage: {
148
+ image: preparedImage,
149
+ sourceSha256: target.sha256,
150
+ },
151
+ }),
126
152
  loaderArgs: this.config.hopperLoaderArgs.length > 0
127
153
  ? this.config.hopperLoaderArgs
128
154
  : derivedLoaderArgs.value,
@@ -138,25 +164,46 @@ export class HopperProvider {
138
164
  logger: this.logger.child({ layer: "bridge" }),
139
165
  onDiagnostic: (diagnostic) => this.logger.info(diagnostic, "Hopper bridge reported a diagnostic"),
140
166
  });
167
+ const regexSearch = new HopperRegexSearch(client);
141
168
  return {
142
169
  execute: async (operation, parameters, options) => {
143
- const result = await client.callTool(operation, parameters, options);
144
- return result.ok
170
+ const result = (operation === "search_strings" ||
171
+ operation === "search_procedures") &&
172
+ parameters.mode === "regex"
173
+ ? await regexSearch.execute(operation, parameters, options)
174
+ : await client.callTool(operation, parameters, options);
175
+ if (!result.ok)
176
+ return result;
177
+ const mapped = operation === "address_to_file_offset"
178
+ ? await mapHopperFileOffset(target, result.value, options?.signal)
179
+ : result;
180
+ return mapped.ok
145
181
  ? {
146
182
  ok: true,
147
- value: createAnalysisExecution(result.value, executionProvider, {
183
+ value: createAnalysisExecution(mapped.value, executionProvider, {
184
+ rawResult: result.value,
148
185
  ...(profile === undefined ? {} : { analysisProfile: profile }),
149
186
  limitations: [
150
- "Results depend on Hopper's completed static analysis.",
187
+ ...(preparedImage === undefined
188
+ ? []
189
+ : [
190
+ "REA loaded a verified thin Mach-O slice from the original FAT64 source. Identity and file offsets refer to the original file. The owned temporary image and its Hopper document close together, including on MCP shutdown.",
191
+ ]),
192
+ ...(CAPABILITIES.find((descriptor) => descriptor.operation === operation)?.limitations ?? []),
193
+ ...(operation === "read_bytes"
194
+ ? [
195
+ "Hopper byte reads stop at the containing segment's exclusive end; a readable prefix is returned with complete=false when the requested range crosses it.",
196
+ ]
197
+ : []),
151
198
  ...(operation === "procedure_references"
152
199
  ? [
153
- "Hopper's public Python API does not expose flow classification for calls without resolved targets; unresolved_calls is empty and its coverage is unknown.",
200
+ "Native CallReference classifications and unresolved targets are preserved. Detailed reference flags and coverage beyond reported CallReference objects remain unknown.",
154
201
  ]
155
202
  : []),
156
203
  ],
157
204
  }),
158
205
  }
159
- : result;
206
+ : mapped;
160
207
  },
161
208
  runtimeLineageSnapshots: () => {
162
209
  const observation = client.runtimeLineage();
@@ -181,8 +228,15 @@ export class HopperProvider {
181
228
  },
182
229
  ];
183
230
  },
184
- closeWithOutcome: (options) => client.closeWithOutcome(options),
185
- close: () => client.close(),
231
+ operationHealthSnapshot: () => client.operationHealth(),
232
+ closeWithOutcome: async (options) => {
233
+ await regexSearch.close();
234
+ return client.closeWithOutcome(options);
235
+ },
236
+ close: async () => {
237
+ await regexSearch.close();
238
+ await client.close();
239
+ },
186
240
  };
187
241
  }
188
242
  }
@@ -38,7 +38,6 @@ export const HOPPER_OPERATIONS = Object.freeze([
38
38
  "set_addresses_names",
39
39
  "set_bookmark",
40
40
  "set_comment",
41
- "set_current_document",
42
41
  "set_inline_comment",
43
42
  "unset_bookmark",
44
43
  "xrefs",
@@ -69,5 +68,24 @@ export const CAPABILITIES = Object.freeze(HOPPER_OPERATIONS.map((operation) => O
69
68
  }),
70
69
  limitations: Object.freeze([
71
70
  "Results depend on Hopper's completed static analysis.",
71
+ ...(operation === "address_to_file_offset"
72
+ ? [
73
+ "Original-file coordinates require source bytes matching the selected executable digest. A changed, unavailable, or database-only source retains native mapping facts in partial error evidence.",
74
+ ]
75
+ : []),
76
+ ...(operation === "search_strings" || operation === "search_procedures"
77
+ ? [
78
+ "Regex mode uses ECMAScript Unicode semantics in a supervised worker with a five-second matching deadline. Cancellation or deadline failure stops matching without blocking Hopper; literal mode retains native casefold semantics.",
79
+ ]
80
+ : []),
81
+ ...(operation === "list_strings" ||
82
+ operation === "search_strings" ||
83
+ operation === "analyze_function"
84
+ ? [
85
+ "String values cover native typed objects. Hopper may split long literals into adjacent unterminated fragments; string searches match each object independently.",
86
+ "Undecodable typed objects retain native display text with an explicit decoding unknown; these values do not establish decoded source literals.",
87
+ "Reported string encodings are inferred from typed bytes and native display; the original source's intended encoding is unknown.",
88
+ ]
89
+ : []),
72
90
  ]),
73
91
  })));