@jshookmcp/jshook 0.3.0 → 0.3.1

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 (321) hide show
  1. package/README.md +25 -50
  2. package/README.zh.md +25 -48
  3. package/dist/AntiCheatDetector-CGVGNfy5.mjs +1 -0
  4. package/dist/CacheAdapters-CdAxBmVW.mjs +1 -0
  5. package/dist/CodeInjector-BlgyqTOk.mjs +1 -0
  6. package/dist/ConsoleMonitor-Dkqc0HNi.mjs +490 -0
  7. package/dist/DOMInspector-BYY_EJ0C.mjs +95 -0
  8. package/dist/DarwinAPI-DC4HGGLl.mjs +1 -0
  9. package/dist/DetailedDataManager-BniBJlVv.mjs +1 -0
  10. package/dist/EventBus-DgciURGg.mjs +1 -0
  11. package/dist/EvidenceGraphBridge-BIfgB7HP.mjs +1 -0
  12. package/dist/ExtensionManager-erMpqcLk.mjs +1 -0
  13. package/dist/FingerprintManager-N7BZqjxP.mjs +1 -0
  14. package/dist/HardwareBreakpoint-OcJqNFVc.mjs +1 -0
  15. package/dist/HeapAnalyzer-CqAxZzeS.mjs +1 -0
  16. package/dist/{HookGeneratorBuilders.core.generators.storage-CTbB4Lcx.mjs → HookGeneratorBuilders.core.generators.storage-Bf1fbrNK.mjs} +66 -101
  17. package/dist/InstrumentationSession-DxXs0sCp.mjs +1 -0
  18. package/dist/MCPServer.search.handlers.domain-DVbWL1bT.mjs +1 -0
  19. package/dist/MemoryController-BaqstM5w.mjs +2 -0
  20. package/dist/MemoryScanSession-CaxAjZJf.mjs +1 -0
  21. package/dist/MemoryScanner-BLYnMJy6.mjs +1 -0
  22. package/dist/NativeMemoryManager.impl-CI554XbY.mjs +1 -0
  23. package/dist/NativeMemoryManager.utils-DM4NC3FE.mjs +1 -0
  24. package/dist/PEAnalyzer-DJyaJTQJ.mjs +1 -0
  25. package/dist/PageController-D9jVkH0i.mjs +1 -0
  26. package/dist/PointerChainEngine-5nF9eNlu.mjs +1 -0
  27. package/dist/PrerequisiteError-Bl3dK8XA.mjs +1 -0
  28. package/dist/ProcessRegistry-Hf12LlR9.mjs +1 -0
  29. package/dist/ResponseBuilder-B2lu4KEl.mjs +1 -0
  30. package/dist/ReverseEvidenceGraph-B931HeoW.mjs +2 -0
  31. package/dist/ScriptManager-fgqiALgj.mjs +7 -0
  32. package/dist/Speedhack-l6s8L2Qw.mjs +1 -0
  33. package/dist/StealthVerifier-Dhbj4B4P.mjs +1 -0
  34. package/dist/StructureAnalyzer-A-WamfYE.mjs +2 -0
  35. package/dist/ToolCatalog-D_IKl1Hu.mjs +1 -0
  36. package/dist/ToolError-DWU_z7gp.mjs +1 -0
  37. package/dist/ToolProbe-xsfALmN3.mjs +1 -0
  38. package/dist/ToolRegistry-B0Zs-phN.mjs +1 -0
  39. package/dist/ToolRouter.policy-CFHoN_Lw.mjs +4 -0
  40. package/dist/TraceRecorder-Dd8jLXpi.mjs +272 -0
  41. package/dist/VersionDetector-DMoUWyNm.mjs +9 -0
  42. package/dist/Win32API-Bhi5xFBe.mjs +1 -0
  43. package/dist/Win32Debug-CQteFL4F.mjs +1 -0
  44. package/dist/WorkflowEngine-CxEp2WXH.mjs +1 -0
  45. package/dist/analysis-BuR-NgX8.mjs +5 -0
  46. package/dist/{antidebug-BRKeyt27.mjs → antidebug-BOTZH6-0.mjs} +8 -259
  47. package/dist/artifactRetention-NBdncOEW.mjs +1 -0
  48. package/dist/artifacts-B5xQuEa_.mjs +1 -0
  49. package/dist/authorization-schema-B40obG1A.mjs +1 -0
  50. package/dist/betterSqlite3-CGaxz4AX.mjs +1 -0
  51. package/dist/binary-instrument-Cf9qqLlM.mjs +7 -0
  52. package/dist/bind-helpers-BlAOQrFQ.mjs +1 -0
  53. package/dist/boringssl-inspector-BST5vtKx.mjs +2 -0
  54. package/dist/browser-C4Le3xqA.mjs +11 -0
  55. package/dist/capabilities-DbYCv-HF.mjs +1 -0
  56. package/dist/chunk-C_pMuVsO.mjs +1 -0
  57. package/dist/collector-CKO8RPK8.mjs +1 -0
  58. package/dist/concurrency-CcK46d0h.mjs +1 -0
  59. package/dist/constants-Cp6hBrrx.mjs +1 -0
  60. package/dist/coordination-BbijHEHH.mjs +1 -0
  61. package/dist/debugger-CRJq_krh.mjs +1 -0
  62. package/dist/definitions-BGobEDQa.mjs +1 -0
  63. package/dist/definitions-BGwNSkVm.mjs +1 -0
  64. package/dist/definitions-BbxOUiP-.mjs +1 -0
  65. package/dist/definitions-CCP9gphV.mjs +1 -0
  66. package/dist/definitions-CIO9O-Sw.mjs +1 -0
  67. package/dist/definitions-CYFbewnd.mjs +1 -0
  68. package/dist/definitions-CdWEuIkI.mjs +1 -0
  69. package/dist/definitions-CoQFbggH.mjs +1 -0
  70. package/dist/definitions-CuJRsJ6N.mjs +1 -0
  71. package/dist/definitions-DI9YXsJk.mjs +1 -0
  72. package/dist/definitions-DJklW2sS.mjs +1 -0
  73. package/dist/definitions-DZ8uKusP.mjs +1 -0
  74. package/dist/definitions-Dds_zrWx.mjs +1 -0
  75. package/dist/definitions-Dgrg7f3D.mjs +1 -0
  76. package/dist/definitions-DtE0XLrT.mjs +1 -0
  77. package/dist/definitions-LaYTuwQd.mjs +26 -0
  78. package/dist/definitions-NoVp_9Pm.mjs +1 -0
  79. package/dist/definitions-OvGsfxdt.mjs +1 -0
  80. package/dist/definitions-jXPaVy4P.mjs +1 -0
  81. package/dist/encoding-DGcr6Aj_.mjs +2 -0
  82. package/dist/ensure-browser-core-Buls24LQ.mjs +1 -0
  83. package/dist/evidence-graph-bridge-B0yhGPcs.mjs +1 -0
  84. package/dist/factory-Cx_1LorX.mjs +1 -0
  85. package/dist/flat-target-session-CO5g78k3.mjs +1 -0
  86. package/dist/formatAddress-C7j2fDlM.mjs +1 -0
  87. package/dist/graphql-HLf3MS8H.mjs +62 -0
  88. package/dist/handlers-BLMa4X7l.mjs +54 -0
  89. package/dist/handlers-BP12ZsWc.mjs +4 -0
  90. package/dist/handlers-BZoPla6E.mjs +1 -0
  91. package/dist/handlers-BggKiVx9.mjs +2 -0
  92. package/dist/handlers-D3iev8g1.mjs +1 -0
  93. package/dist/handlers-D49r1-1P.mjs +1 -0
  94. package/dist/handlers-DCE45Ww8.mjs +2 -0
  95. package/dist/handlers-DW5AbYs5.mjs +5 -0
  96. package/dist/handlers-De5u62Ga2.mjs +1 -0
  97. package/dist/handlers-DmQzIc44.mjs +31 -0
  98. package/dist/handlers-DnJRGp7t.mjs +302 -0
  99. package/dist/handlers-Dv_runVv.mjs +2 -0
  100. package/dist/handlers-S9Ws0IGy.mjs +2 -0
  101. package/dist/{handlers-Dz9PYsCa.mjs → handlers-pVNpaw4A.mjs} +118 -904
  102. package/dist/handlers.impl-CD2_kOcC.mjs +1 -0
  103. package/dist/hooks-DDKppogd.mjs +600 -0
  104. package/dist/index.mjs +12 -5235
  105. package/dist/logger-sBC6IdRT.mjs +1 -0
  106. package/dist/maintenance-CutEO84j.mjs +1 -0
  107. package/dist/manifest-BFGxlDRh.mjs +123 -0
  108. package/dist/manifest-BPuE6oH2.mjs +1 -0
  109. package/dist/manifest-BXry5N09.mjs +1 -0
  110. package/dist/manifest-BeP_zJGb2.mjs +1 -0
  111. package/dist/manifest-C0g67k6U.mjs +1 -0
  112. package/dist/manifest-C1nZkTkO.mjs +1 -0
  113. package/dist/manifest-C7qV1z7F.mjs +1 -0
  114. package/dist/manifest-CDeUZGUZ.mjs +1 -0
  115. package/dist/manifest-CDiCtaQT.mjs +1 -0
  116. package/dist/manifest-CFn0359q2.mjs +1 -0
  117. package/dist/manifest-CGq4NpqH2.mjs +1 -0
  118. package/dist/manifest-CJMGt7Qy.mjs +1 -0
  119. package/dist/manifest-CRIJq4Hs.mjs +1 -0
  120. package/dist/manifest-C_hEIjSx.mjs +1 -0
  121. package/dist/manifest-CeQmtQOY.mjs +1 -0
  122. package/dist/manifest-Cq0j7GZt.mjs +1 -0
  123. package/dist/manifest-CtPmHAdn.mjs +1 -0
  124. package/dist/manifest-Cx2IVMUY.mjs +1 -0
  125. package/dist/manifest-D16xPXro.mjs +1 -0
  126. package/dist/manifest-D44TaRJU.mjs +1 -0
  127. package/dist/manifest-D610kxZr.mjs +2 -0
  128. package/dist/manifest-DC-SMF6b.mjs +1 -0
  129. package/dist/manifest-DD3rtxvV.mjs +1 -0
  130. package/dist/manifest-DKUorv5M.mjs +1 -0
  131. package/dist/manifest-DMJlcsTR.mjs +1 -0
  132. package/dist/manifest-DWUUWBz0.mjs +1 -0
  133. package/dist/manifest-De-6Wf2R.mjs +1 -0
  134. package/dist/manifest-Dgh0uDW-.mjs +1 -0
  135. package/dist/manifest-Dm0o3i2U.mjs +1 -0
  136. package/dist/manifest-DsVh7Y4U.mjs +1 -0
  137. package/dist/manifest-DtEFSRaq.mjs +1 -0
  138. package/dist/manifest-H-EpAyZQ.mjs +1 -0
  139. package/dist/manifest-ais9Afrw.mjs +1 -0
  140. package/dist/manifest-tmb54wmA.mjs +1 -0
  141. package/dist/manifest-yu2xiQqe.mjs +1 -0
  142. package/dist/manifest-zrbrpKCC.mjs +1 -0
  143. package/dist/matchesWildcardPattern-BGqLSmEs.mjs +1 -0
  144. package/dist/modules-p-PUNv9r.mjs +332 -0
  145. package/dist/mojo-ipc-VGlv3Qyp.mjs +9 -0
  146. package/dist/network-BjZ1Y-GB.mjs +7 -0
  147. package/dist/outputPaths-BonGThuc.mjs +2 -0
  148. package/dist/parse-args-Cuk7-xUt.mjs +1 -0
  149. package/dist/platform-C446Lf97.mjs +93 -0
  150. package/dist/playwright-cdp-fallback-BwVR-_T3.mjs +1 -0
  151. package/dist/process-C9f2A5zk.mjs +962 -0
  152. package/dist/proxy-CvRepxgV.mjs +1 -0
  153. package/dist/registry-DUHIPE-v.mjs +1 -0
  154. package/dist/response-C7rKQst4.mjs +1 -0
  155. package/dist/search-defaults-D2bY-rzH.mjs +1 -0
  156. package/dist/server/plugin-api.mjs +1 -293
  157. package/dist/shared-state-board-Cyg-xh_k.mjs +1 -0
  158. package/dist/sourcemap-D6Q1UuAp.mjs +1 -0
  159. package/dist/ssrf-policy-T96MR3r6.mjs +1 -0
  160. package/dist/streaming-CTX58tbb.mjs +1 -0
  161. package/dist/tool-builder-CI9914Tf.mjs +1 -0
  162. package/dist/transform-Cv9P2vVD.mjs +103 -0
  163. package/dist/types-CuyefmGT.mjs +1 -0
  164. package/dist/types-DtThH00r.mjs +1 -0
  165. package/dist/wasm-DaJa8J0V.mjs +174 -0
  166. package/dist/webcrack-CsLLJIs9.mjs +46 -0
  167. package/dist/workflow-CYIXtrWD.mjs +101 -0
  168. package/package.json +50 -78
  169. package/dist/AntiCheatDetector-CqGDXmfc.mjs +0 -350
  170. package/dist/CacheAdapters-jJFy20G-.mjs +0 -80
  171. package/dist/CodeInjector-BdjRfNx7.mjs +0 -150
  172. package/dist/ConsoleMonitor-DykL3IAw.mjs +0 -2269
  173. package/dist/DarwinAPI-ETyy0xyo.mjs +0 -363
  174. package/dist/DetailedDataManager-HT49OrvF.mjs +0 -217
  175. package/dist/EventBus-DFKvADm3.mjs +0 -141
  176. package/dist/EvidenceGraphBridge-318Oi0Lf.mjs +0 -153
  177. package/dist/ExtensionManager-BDMsY2Dz.mjs +0 -721
  178. package/dist/FingerprintManager-BN4UQWnX.mjs +0 -96
  179. package/dist/HardwareBreakpoint-Cc2AFq1Y.mjs +0 -239
  180. package/dist/HeapAnalyzer-DruMgsgj.mjs +0 -284
  181. package/dist/InstrumentationSession-DLH0vd-z.mjs +0 -244
  182. package/dist/MemoryController-CMtviNW_.mjs +0 -167
  183. package/dist/MemoryScanSession-ITgb_NMi.mjs +0 -278
  184. package/dist/MemoryScanner-CiL7Z3ey.mjs +0 -428
  185. package/dist/NativeMemoryManager.impl-D9Lkovvn.mjs +0 -485
  186. package/dist/NativeMemoryManager.utils-BBlAixF5.mjs +0 -165
  187. package/dist/PEAnalyzer-DMQ44gen.mjs +0 -385
  188. package/dist/PageController-BPJNqqBN.mjs +0 -431
  189. package/dist/PointerChainEngine-K7wN8Z-w.mjs +0 -325
  190. package/dist/PrerequisiteError-TuyZIs6n.mjs +0 -20
  191. package/dist/ProcessRegistry-zGg12QbE.mjs +0 -74
  192. package/dist/ResponseBuilder-CJXWmWNw.mjs +0 -143
  193. package/dist/ReverseEvidenceGraph-C02-gXOh.mjs +0 -269
  194. package/dist/ScriptManager-ZuWD-0Jg.mjs +0 -3003
  195. package/dist/Speedhack-D-z0umeT.mjs +0 -156
  196. package/dist/StealthVerifier-BWmPgQsv.mjs +0 -135
  197. package/dist/StructureAnalyzer-Cav5AVSL.mjs +0 -429
  198. package/dist/ToolCatalog-5OJdMiF0.mjs +0 -582
  199. package/dist/ToolError-jh9whhMd.mjs +0 -15
  200. package/dist/ToolProbe-DbCFGyrg.mjs +0 -45
  201. package/dist/ToolRegistry-B9krbTtI.mjs +0 -180
  202. package/dist/ToolRouter.policy-BGDAGyeH.mjs +0 -344
  203. package/dist/TraceRecorder-B41Z5XBj.mjs +0 -1286
  204. package/dist/VersionDetector-K3V4vGsw.mjs +0 -104
  205. package/dist/Win32API-C2kjj0ze.mjs +0 -346
  206. package/dist/Win32Debug-CKrGOTpo.mjs +0 -274
  207. package/dist/WorkflowEngine-DJ6M4opp.mjs +0 -569
  208. package/dist/analysis-BHeJW2Nb.mjs +0 -1234
  209. package/dist/artifactRetention-CPXkUJXp.mjs +0 -598
  210. package/dist/artifacts-DkfosXH3.mjs +0 -59
  211. package/dist/authorization-schema-DRqyJMSk.mjs +0 -31
  212. package/dist/betterSqlite3-DLSBZodi.mjs +0 -74
  213. package/dist/binary-instrument--V3MAhJ4.mjs +0 -971
  214. package/dist/bind-helpers-ClV34xdn.mjs +0 -42
  215. package/dist/boringssl-inspector-Bo_LOLaS.mjs +0 -180
  216. package/dist/browser-Dx3_S2cG.mjs +0 -4369
  217. package/dist/capabilities-CcHlvWgK.mjs +0 -33
  218. package/dist/chunk-CjcI7cDX.mjs +0 -15
  219. package/dist/concurrency-Drev_Vz9.mjs +0 -41
  220. package/dist/constants-CDZLOoVv.mjs +0 -534
  221. package/dist/coordination-DgItD9DL.mjs +0 -259
  222. package/dist/debugger-RS3RSAqs.mjs +0 -1288
  223. package/dist/definitions-BEoYofW5.mjs +0 -47
  224. package/dist/definitions-BRaefg3u.mjs +0 -365
  225. package/dist/definitions-BbkvZkiv.mjs +0 -96
  226. package/dist/definitions-BtWSHJ3o.mjs +0 -17
  227. package/dist/definitions-C1gCHO0i.mjs +0 -43
  228. package/dist/definitions-CDOg_b-l.mjs +0 -138
  229. package/dist/definitions-CVPD9hzZ.mjs +0 -54
  230. package/dist/definitions-Cea8Lgl7.mjs +0 -94
  231. package/dist/definitions-DAgIyjxM.mjs +0 -10
  232. package/dist/definitions-DJA27nsL.mjs +0 -66
  233. package/dist/definitions-DKPFU3LW.mjs +0 -25
  234. package/dist/definitions-DPRpZQ96.mjs +0 -47
  235. package/dist/definitions-DUE5gmdn.mjs +0 -18
  236. package/dist/definitions-DYVjOtxa.mjs +0 -26
  237. package/dist/definitions-DcYLVLCo.mjs +0 -37
  238. package/dist/definitions-Pp5LI2H4.mjs +0 -27
  239. package/dist/definitions-j9KdHVNR.mjs +0 -14
  240. package/dist/definitions-uzkjBwa7.mjs +0 -258
  241. package/dist/definitions-va-AnLuQ.mjs +0 -28
  242. package/dist/encoding-DJeqHmpd.mjs +0 -1079
  243. package/dist/evidence-graph-bridge-DcYizFk2.mjs +0 -136
  244. package/dist/factory-C90tBff6.mjs +0 -575
  245. package/dist/flat-target-session-Dgax2Cy3.mjs +0 -29
  246. package/dist/formatAddress-nnMvEohD.mjs +0 -17
  247. package/dist/graphql-CoHrhweh.mjs +0 -1197
  248. package/dist/handlers-4jmR0nMs.mjs +0 -898
  249. package/dist/handlers-BAHPxcch.mjs +0 -789
  250. package/dist/handlers-BOs9b907.mjs +0 -2600
  251. package/dist/handlers-BWXEy6ef.mjs +0 -917
  252. package/dist/handlers-Bndn6QvE.mjs +0 -111
  253. package/dist/handlers-BqC4bD4s.mjs +0 -681
  254. package/dist/handlers-BtYq60bM2.mjs +0 -276
  255. package/dist/handlers-BzgcB4iv.mjs +0 -799
  256. package/dist/handlers-CRyRWj2b.mjs +0 -859
  257. package/dist/handlers-CVv2H1uq.mjs +0 -592
  258. package/dist/handlers-Dl5a7JS4.mjs +0 -572
  259. package/dist/handlers-Dx2d7jt7.mjs +0 -2537
  260. package/dist/handlers-HujRKC3b.mjs +0 -661
  261. package/dist/handlers.impl-XWXkQfyi.mjs +0 -807
  262. package/dist/hooks-B1B8NRHL.mjs +0 -898
  263. package/dist/logger-Dh_xb7_2.mjs +0 -93
  264. package/dist/maintenance-PRMkLVRW.mjs +0 -835
  265. package/dist/manifest-67Bok-Si.mjs +0 -58
  266. package/dist/manifest-6lNTMZAB2.mjs +0 -87
  267. package/dist/manifest-B2duEHiH.mjs +0 -90
  268. package/dist/manifest-B6EY9Vm8.mjs +0 -57
  269. package/dist/manifest-B6nKSbyY.mjs +0 -95
  270. package/dist/manifest-BL8AQNPF.mjs +0 -106
  271. package/dist/manifest-BSZvJJmV.mjs +0 -47
  272. package/dist/manifest-BU7qzUyX.mjs +0 -418
  273. package/dist/manifest-Bl62e8WK.mjs +0 -49
  274. package/dist/manifest-Bo5cXjdt.mjs +0 -82
  275. package/dist/manifest-BpS4gtUK.mjs +0 -1347
  276. package/dist/manifest-Bv65_e2W.mjs +0 -101
  277. package/dist/manifest-BytNIF4Z.mjs +0 -117
  278. package/dist/manifest-C-xtsjS3.mjs +0 -81
  279. package/dist/manifest-CDYl7OhA.mjs +0 -66
  280. package/dist/manifest-CRZ3xmkD.mjs +0 -61
  281. package/dist/manifest-CoW6u4Tp.mjs +0 -132
  282. package/dist/manifest-Cq5zN_8A.mjs +0 -50
  283. package/dist/manifest-D7YZM_2e.mjs +0 -194
  284. package/dist/manifest-DE_VrAeQ.mjs +0 -314
  285. package/dist/manifest-DGsXSCpT.mjs +0 -39
  286. package/dist/manifest-DJ2vfEuW.mjs +0 -156
  287. package/dist/manifest-DPXDYhEu.mjs +0 -80
  288. package/dist/manifest-Dd4fQb0a.mjs +0 -322
  289. package/dist/manifest-Deq6opGg.mjs +0 -223
  290. package/dist/manifest-DfJTafJK.mjs +0 -37
  291. package/dist/manifest-DgOdgN_j.mjs +0 -50
  292. package/dist/manifest-DlbMW4v4.mjs +0 -47
  293. package/dist/manifest-DmVfbH0w.mjs +0 -374
  294. package/dist/manifest-Dog6Ddjr.mjs +0 -109
  295. package/dist/manifest-DvgU5FWb.mjs +0 -58
  296. package/dist/manifest-HsfDBs7j.mjs +0 -50
  297. package/dist/manifest-I8oQHvCG.mjs +0 -186
  298. package/dist/manifest-NvH_a-av.mjs +0 -786
  299. package/dist/manifest-cEJU1v0Z.mjs +0 -129
  300. package/dist/manifest-wOl5XLB12.mjs +0 -112
  301. package/dist/modules-tZozf0LQ.mjs +0 -10635
  302. package/dist/mojo-ipc-DXNEXEqb.mjs +0 -640
  303. package/dist/network-CPVvwvFg.mjs +0 -3852
  304. package/dist/outputPaths-um7lCRY3.mjs +0 -1141
  305. package/dist/parse-args-B4cY5Vx5.mjs +0 -39
  306. package/dist/platform-CYeFoTWp.mjs +0 -2161
  307. package/dist/process-BTbgcVc6.mjs +0 -1306
  308. package/dist/proxy-r8YN6nP1.mjs +0 -192
  309. package/dist/registry-Bl8ZQW61.mjs +0 -34
  310. package/dist/response-CWhh2aLo.mjs +0 -34
  311. package/dist/shared-state-board-BoZnSoj-.mjs +0 -586
  312. package/dist/sourcemap-BIDHUVXy.mjs +0 -934
  313. package/dist/ssrf-policy-Dsqd-DTX.mjs +0 -166
  314. package/dist/streaming-Dal6utPp.mjs +0 -725
  315. package/dist/tool-builder-BHJp32mV.mjs +0 -186
  316. package/dist/transform-DRVgGG90.mjs +0 -1011
  317. package/dist/types-Bx92KJfT.mjs +0 -4
  318. package/dist/types-DDBWs9UP.mjs +0 -37
  319. package/dist/wasm-BYx5UOeG.mjs +0 -1044
  320. package/dist/webcrack-Be0_FccV.mjs +0 -747
  321. package/dist/workflow-BpuKEtvn.mjs +0 -725
@@ -1,971 +0,0 @@
1
- import { t as __exportAll } from "./chunk-CjcI7cDX.mjs";
2
- import { t as logger } from "./logger-Dh_xb7_2.mjs";
3
- import { Q as FRIDA_TIMEOUT_MS, et as GHIDRA_TIMEOUT_MS, xr as UNIDBG_TIMEOUT_MS } from "./constants-CDZLOoVv.mjs";
4
- import { t as probeCommand } from "./ToolProbe-DbCFGyrg.mjs";
5
- import { tmpdir } from "node:os";
6
- import { randomUUID } from "node:crypto";
7
- import { basename, dirname, join } from "node:path";
8
- import { access, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
9
- import { execFile } from "node:child_process";
10
- //#region src/modules/binary-instrument/FridaSession.ts
11
- const FRIDA_MAX_BUFFER_BYTES = 5 * 1024 * 1024;
12
- var FridaSession = class {
13
- sessions = /* @__PURE__ */ new Map();
14
- activeSessionId;
15
- fridaProbe;
16
- probePromise;
17
- async attach(target) {
18
- const availability = await this.getAvailability();
19
- if (!availability.available) throw new Error(availability.reason ?? "Frida CLI is not available");
20
- const probe = await this.runFridaCommand(target, "console.log(\"__frida_attach_ok__\");");
21
- if (probe.error) throw new Error(probe.error);
22
- const sessionId = randomUUID();
23
- const record = {
24
- id: sessionId,
25
- target,
26
- pid: this.resolvePid(target),
27
- status: "attached",
28
- attachedAt: (/* @__PURE__ */ new Date()).toISOString()
29
- };
30
- this.sessions.set(sessionId, record);
31
- this.activeSessionId = sessionId;
32
- return sessionId;
33
- }
34
- async detach() {
35
- const active = this.getActiveSessionRecord();
36
- if (!active) return;
37
- active.status = "detached";
38
- this.activeSessionId = void 0;
39
- }
40
- async executeScript(script) {
41
- const session = this.requireActiveSession();
42
- const result = await this.runFridaCommand(session.target, script);
43
- if (result.error) {
44
- session.status = "error";
45
- session.lastError = result.error;
46
- }
47
- return result;
48
- }
49
- async enumerateModules() {
50
- const session = this.requireActiveSession();
51
- const result = await this.runFridaCommand(session.target, "console.log(JSON.stringify(Process.enumerateModules()));");
52
- const parsed = this.parseModuleList(result.output);
53
- if (parsed.length > 0) return parsed;
54
- if (result.error) {
55
- session.status = "error";
56
- session.lastError = result.error;
57
- }
58
- return [];
59
- }
60
- async enumerateFunctions(moduleName) {
61
- const session = this.requireActiveSession();
62
- const safeModuleName = JSON.stringify(moduleName);
63
- const result = await this.runFridaCommand(session.target, [
64
- `const entries = Process.getModuleByName(${safeModuleName}).enumerateExports()`,
65
- ".filter(function (entry) { return entry.type === \"function\"; })",
66
- ".map(function (entry) {",
67
- " return { name: entry.name, address: String(entry.address), size: 0 };",
68
- "});",
69
- "console.log(JSON.stringify(entries));"
70
- ].join(""));
71
- const parsed = this.parseFunctionList(result.output);
72
- if (parsed.length > 0) return parsed;
73
- if (result.error) {
74
- session.status = "error";
75
- session.lastError = result.error;
76
- }
77
- return [];
78
- }
79
- async findSymbols(pattern) {
80
- const session = this.requireActiveSession();
81
- const trimmedPattern = pattern.trim();
82
- const resolvedPattern = trimmedPattern.includes(":") ? trimmedPattern : trimmedPattern.includes("!") ? `exports:${trimmedPattern}` : `exports:*!${trimmedPattern}*`;
83
- const matchPattern = JSON.stringify(resolvedPattern);
84
- const result = await this.runFridaCommand(session.target, [
85
- "const resolver = new ApiResolver(\"module\");",
86
- `const matches = resolver.enumerateMatches(${matchPattern});`,
87
- "const mapped = matches.map(function (entry) {",
88
- " const resolvedName = typeof entry.name === \"string\" ? entry.name : \"unknown\";",
89
- " const resolvedAddress = entry.address ? String(entry.address) : \"0x0\";",
90
- " return { name: resolvedName, address: resolvedAddress, demangled: resolvedName };",
91
- "});",
92
- "console.log(JSON.stringify(mapped));"
93
- ].join(""));
94
- const parsed = this.parseSymbolList(result.output);
95
- if (parsed.length > 0) return parsed;
96
- if (result.error) {
97
- session.status = "error";
98
- session.lastError = result.error;
99
- }
100
- return [];
101
- }
102
- listSessions() {
103
- return Array.from(this.sessions.values()).map((session) => ({
104
- id: session.id,
105
- target: session.target,
106
- pid: session.pid,
107
- status: session.status
108
- }));
109
- }
110
- async isAvailable() {
111
- return (await this.getAvailability()).available;
112
- }
113
- async getAvailability() {
114
- if (this.fridaProbe) return this.fridaProbe;
115
- if (!this.probePromise) this.probePromise = probeCommand("frida");
116
- const resolved = await this.probePromise;
117
- this.fridaProbe = resolved;
118
- this.probePromise = void 0;
119
- return resolved;
120
- }
121
- useSession(sessionId) {
122
- if (!this.sessions.has(sessionId)) return false;
123
- this.activeSessionId = sessionId;
124
- return true;
125
- }
126
- hasSession(sessionId) {
127
- return this.sessions.has(sessionId);
128
- }
129
- getSessionDiagnostics(sessionId) {
130
- const session = this.sessions.get(sessionId);
131
- if (!session) return;
132
- return {
133
- status: session.status,
134
- lastError: session.lastError
135
- };
136
- }
137
- getActiveSessionRecord() {
138
- if (!this.activeSessionId) return;
139
- return this.sessions.get(this.activeSessionId);
140
- }
141
- requireActiveSession() {
142
- const session = this.getActiveSessionRecord();
143
- if (!session) throw new Error("No active Frida session. Call attach() first.");
144
- return session;
145
- }
146
- resolvePid(target) {
147
- if (!/^\d+$/.test(target)) return null;
148
- const parsed = Number.parseInt(target, 10);
149
- return Number.isNaN(parsed) ? null : parsed;
150
- }
151
- async runFridaCommand(target, script) {
152
- const availability = await this.getAvailability();
153
- if (!availability.available) return {
154
- output: "",
155
- error: availability.reason ?? "Frida CLI is not available"
156
- };
157
- const command = availability.path ?? "frida";
158
- const args = [
159
- ...this.buildTargetArgs(target),
160
- "--runtime=v8",
161
- "-q",
162
- "-e",
163
- script
164
- ];
165
- try {
166
- const result = await this.execFileUtf8(command, args, FRIDA_TIMEOUT_MS);
167
- const output = result.stdout.trim();
168
- const error = result.stderr.trim();
169
- return error ? {
170
- output,
171
- error
172
- } : { output };
173
- } catch (error) {
174
- const message = error instanceof Error ? error.message : String(error);
175
- logger.warn("[binary-instrument] Frida command failed", {
176
- target,
177
- message
178
- });
179
- return {
180
- output: "",
181
- error: message
182
- };
183
- }
184
- }
185
- buildTargetArgs(target) {
186
- if (/^\d+$/.test(target)) return ["-p", target];
187
- if (target.includes("/") || target.includes("\\")) return ["-f", target];
188
- return ["-n", target];
189
- }
190
- parseModuleList(output) {
191
- const payload = this.extractJsonPayload(output);
192
- if (!Array.isArray(payload)) return [];
193
- const modules = [];
194
- for (const entry of payload) {
195
- if (!this.isRecord(entry)) continue;
196
- const name = this.readStringField(entry, "name");
197
- const path = this.readStringField(entry, "path");
198
- const base = this.normalizeHex(entry["base"]);
199
- const size = this.readNumberField(entry, "size");
200
- if (!name || !path || !base || size === void 0) continue;
201
- modules.push({
202
- name,
203
- base,
204
- size,
205
- path
206
- });
207
- }
208
- return modules;
209
- }
210
- parseFunctionList(output) {
211
- const payload = this.extractJsonPayload(output);
212
- if (!Array.isArray(payload)) return [];
213
- const functions = [];
214
- for (const entry of payload) {
215
- if (!this.isRecord(entry)) continue;
216
- const name = this.readStringField(entry, "name");
217
- const address = this.normalizeHex(entry["address"]);
218
- const size = this.readNumberField(entry, "size") ?? 0;
219
- if (!name || !address) continue;
220
- functions.push({
221
- name,
222
- address,
223
- size
224
- });
225
- }
226
- return functions;
227
- }
228
- parseSymbolList(output) {
229
- const payload = this.extractJsonPayload(output);
230
- if (!Array.isArray(payload)) return [];
231
- const symbols = [];
232
- for (const entry of payload) {
233
- if (!this.isRecord(entry)) continue;
234
- const name = this.readStringField(entry, "name");
235
- const address = this.normalizeHex(entry["address"]);
236
- const demangled = this.readStringField(entry, "demangled");
237
- if (!name || !address) continue;
238
- if (demangled) symbols.push({
239
- name,
240
- address,
241
- demangled
242
- });
243
- else symbols.push({
244
- name,
245
- address
246
- });
247
- }
248
- return symbols;
249
- }
250
- extractJsonPayload(output) {
251
- const candidates = output.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.startsWith("{") || line.startsWith("[")).toReversed();
252
- for (const line of candidates) try {
253
- return JSON.parse(line);
254
- } catch {
255
- continue;
256
- }
257
- }
258
- readStringField(record, key) {
259
- const value = record[key];
260
- return typeof value === "string" && value.length > 0 ? value : void 0;
261
- }
262
- readNumberField(record, key) {
263
- const value = record[key];
264
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
265
- }
266
- normalizeHex(value) {
267
- if (typeof value === "number" && Number.isFinite(value)) return `0x${value.toString(16)}`;
268
- if (typeof value === "string" && value.length > 0) return value.startsWith("0x") ? value : `0x${value}`;
269
- }
270
- isRecord(value) {
271
- return typeof value === "object" && value !== null;
272
- }
273
- execFileUtf8(file, args, timeoutMs) {
274
- return new Promise((resolve, reject) => {
275
- execFile(file, args, {
276
- timeout: timeoutMs,
277
- windowsHide: true,
278
- maxBuffer: FRIDA_MAX_BUFFER_BYTES,
279
- encoding: "utf8"
280
- }, (error, stdout, stderr) => {
281
- if (error) {
282
- reject(error);
283
- return;
284
- }
285
- resolve({
286
- stdout: typeof stdout === "string" ? stdout : "",
287
- stderr: typeof stderr === "string" ? stderr : ""
288
- });
289
- });
290
- });
291
- }
292
- };
293
- //#endregion
294
- //#region src/modules/binary-instrument/GhidraAnalyzer.ts
295
- const GHIDRA_MAX_BUFFER_BYTES = 16 * 1024 * 1024;
296
- var GhidraAnalyzer = class {
297
- ghidraProbe;
298
- probePromise;
299
- async analyze(binaryPath, options) {
300
- await access(binaryPath);
301
- const fileBuffer = await readFile(binaryPath);
302
- const strings = this.extractPrintableStrings(fileBuffer);
303
- const imports = this.deriveImports(strings);
304
- const exports = this.deriveExports(strings);
305
- if (!(await this.getAvailability()).available) return {
306
- functions: [],
307
- imports,
308
- exports,
309
- strings
310
- };
311
- const timeoutMs = typeof options?.timeout === "number" && Number.isFinite(options.timeout) ? options.timeout : GHIDRA_TIMEOUT_MS;
312
- const scriptDirectory = await mkdtemp(join(tmpdir(), "jshook-ghidra-script-"));
313
- const scriptPath = join(scriptDirectory, "BinaryInstrumentDump.py");
314
- try {
315
- await writeFile(scriptPath, this.buildDefaultScript(), "utf8");
316
- const output = await this.headlessAnalyze(scriptPath, binaryPath, timeoutMs);
317
- return {
318
- functions: this.parseDecompiledOutput(output),
319
- imports,
320
- exports,
321
- strings
322
- };
323
- } catch (error) {
324
- const message = error instanceof Error ? error.message : String(error);
325
- logger.warn("[binary-instrument] Ghidra analyze fallback", {
326
- binaryPath,
327
- message
328
- });
329
- return {
330
- functions: [],
331
- imports,
332
- exports,
333
- strings
334
- };
335
- } finally {
336
- await rm(scriptDirectory, {
337
- recursive: true,
338
- force: true
339
- });
340
- }
341
- }
342
- async headlessAnalyze(scriptPath, binaryPath, timeoutMs = GHIDRA_TIMEOUT_MS) {
343
- const availability = await this.getAvailability();
344
- if (!availability.available) throw new Error(availability.reason ?? "Ghidra analyzeHeadless is not available");
345
- await access(binaryPath);
346
- await access(scriptPath);
347
- const command = availability.path ?? "analyzeHeadless";
348
- const projectDirectory = await mkdtemp(join(tmpdir(), "jshook-ghidra-project-"));
349
- const projectName = "binary-instrument";
350
- try {
351
- const result = await this.execFileUtf8(command, [
352
- projectDirectory,
353
- projectName,
354
- "-import",
355
- binaryPath,
356
- "-scriptPath",
357
- dirname(scriptPath),
358
- "-postScript",
359
- basename(scriptPath)
360
- ], timeoutMs);
361
- return [result.stdout.trim(), result.stderr.trim()].filter((entry) => entry.length > 0).join("\n");
362
- } finally {
363
- await rm(projectDirectory, {
364
- recursive: true,
365
- force: true
366
- });
367
- }
368
- }
369
- parseDecompiledOutput(output) {
370
- const functions = [];
371
- const blockPattern = /FUNCTION_START\s*[\r\n]+NAME:(.+?)\s*[\r\n]+ADDRESS:(.+?)\s*[\r\n]+SIGNATURE:(.+?)\s*[\r\n]+DECOMPILED_START\s*[\r\n]+([\s\S]*?)\s*[\r\n]+DECOMPILED_END\s*[\r\n]+FUNCTION_END/g;
372
- let match = blockPattern.exec(output);
373
- while (match) {
374
- const rawName = match[1] ?? "";
375
- const rawAddress = match[2] ?? "";
376
- const rawSignature = match[3] ?? "";
377
- const rawBody = match[4] ?? "";
378
- const name = rawName.trim();
379
- const address = this.normalizeHex(rawAddress.trim());
380
- const signature = rawSignature.trim();
381
- const decompiled = rawBody.trim();
382
- if (name.length > 0 && address.length > 0 && signature.length > 0) functions.push({
383
- name,
384
- address,
385
- signature,
386
- decompiled
387
- });
388
- match = blockPattern.exec(output);
389
- }
390
- return functions;
391
- }
392
- async isAvailable() {
393
- return (await this.getAvailability()).available;
394
- }
395
- async getAvailability() {
396
- if (this.ghidraProbe) return this.ghidraProbe;
397
- if (!this.probePromise) this.probePromise = probeCommand("analyzeHeadless", ["-help"]);
398
- const resolved = await this.probePromise;
399
- this.ghidraProbe = resolved;
400
- this.probePromise = void 0;
401
- return resolved;
402
- }
403
- buildDefaultScript() {
404
- return [
405
- "# @category BinaryInstrument",
406
- "from ghidra.app.decompiler import DecompInterface",
407
- "",
408
- "program = currentProgram",
409
- "interface = DecompInterface()",
410
- "interface.openProgram(program)",
411
- "function_manager = program.getFunctionManager()",
412
- "functions = function_manager.getFunctions(True)",
413
- "",
414
- "for function in functions:",
415
- " print(\"FUNCTION_START\")",
416
- " print(\"NAME:\" + str(function.getName()))",
417
- " print(\"ADDRESS:\" + str(function.getEntryPoint()))",
418
- " try:",
419
- " signature = str(function.getSignature())",
420
- " except:",
421
- " signature = str(function.getName()) + \"()\"",
422
- " print(\"SIGNATURE:\" + signature)",
423
- " print(\"DECOMPILED_START\")",
424
- " try:",
425
- " decompiled = interface.decompileFunction(function, 30, monitor).getDecompiledFunction()",
426
- " if decompiled:",
427
- " print(str(decompiled.getC()))",
428
- " else:",
429
- " print(\"// no decompiled output\")",
430
- " except:",
431
- " print(\"// decompile failed\")",
432
- " print(\"DECOMPILED_END\")",
433
- " print(\"FUNCTION_END\")"
434
- ].join("\n");
435
- }
436
- extractPrintableStrings(buffer) {
437
- const results = [];
438
- let current = "";
439
- for (const byte of buffer.values()) {
440
- if (byte >= 32 && byte <= 126) {
441
- current += String.fromCharCode(byte);
442
- continue;
443
- }
444
- if (current.length >= 4) results.push(current);
445
- current = "";
446
- }
447
- if (current.length >= 4) results.push(current);
448
- return Array.from(new Set(results)).slice(0, 1e3);
449
- }
450
- deriveImports(strings) {
451
- return strings.filter((entry) => /(?:\.dll|\.so|\.dylib|kernel32|user32|libc|printf|malloc|LoadLibrary)/i.test(entry)).slice(0, 100);
452
- }
453
- deriveExports(strings) {
454
- return strings.filter((entry) => /^[A-Za-z_][A-Za-z0-9_@?$]{2,}$/.test(entry)).slice(0, 100);
455
- }
456
- normalizeHex(value) {
457
- return value.startsWith("0x") ? value : `0x${value}`;
458
- }
459
- execFileUtf8(file, args, timeoutMs) {
460
- return new Promise((resolve, reject) => {
461
- execFile(file, args, {
462
- timeout: timeoutMs,
463
- windowsHide: true,
464
- maxBuffer: GHIDRA_MAX_BUFFER_BYTES,
465
- encoding: "utf8"
466
- }, (error, stdout, stderr) => {
467
- if (error) {
468
- reject(error);
469
- return;
470
- }
471
- resolve({
472
- stdout: typeof stdout === "string" ? stdout : "",
473
- stderr: typeof stderr === "string" ? stderr : ""
474
- });
475
- });
476
- });
477
- }
478
- };
479
- //#endregion
480
- //#region src/modules/binary-instrument/HookCodeGenerator.ts
481
- var HookCodeGenerator = class {
482
- generateHooks(input) {
483
- const templates = [];
484
- for (const fn of input.functions) {
485
- const category = this.classifyFunction(fn, input);
486
- if (category === "unknown") continue;
487
- templates.push({
488
- functionName: fn.name,
489
- description: this.describeCategory(category, input),
490
- hookCode: this.buildHookCode(fn, category),
491
- parameters: this.buildParameters(fn)
492
- });
493
- }
494
- return templates;
495
- }
496
- exportScript(templates, format) {
497
- if (format !== "frida") throw new Error("Unsupported export format");
498
- const lines = [
499
- "// Frida hook script",
500
- "// auto-generated by HookCodeGenerator",
501
- `// Hook count: ${templates.length}`,
502
- ""
503
- ];
504
- for (const template of templates) {
505
- lines.push(`// ${template.functionName}: ${template.description}`);
506
- lines.push(template.hookCode);
507
- lines.push("");
508
- }
509
- return lines.join("\n");
510
- }
511
- classifyFunction(fn, input) {
512
- const name = fn.name.toLowerCase();
513
- const imports = input.imports.map((entry) => entry.toLowerCase());
514
- const strings = input.strings.map((entry) => entry.toLowerCase());
515
- if (fn.name.startsWith("Java_")) return "jni";
516
- if (name.includes("aes")) return "aes";
517
- if (name.includes("md5")) return "md5";
518
- if (name.includes("sha")) return "sha";
519
- if (name.includes("rsa")) return "rsa";
520
- if (name.includes("base64")) return "base64";
521
- if (name.includes("send") || name.includes("recv") || name.includes("socket") || name.includes("http")) return "network";
522
- if (name.includes("open") || name.includes("read") || name.includes("write") || name.includes("fopen")) return "file-io";
523
- if ((name.includes("decrypt") || name.includes("encrypt")) && strings.some((entry) => entry.includes("obfuscation") || entry.includes("encryption"))) return "obfuscation";
524
- if (name.includes("memcpy") || name.includes("strcpy") || name.includes("memmove") || name.includes("string")) return "string";
525
- if (imports.some((entry) => entry.includes("aes"))) return "aes";
526
- return "unknown";
527
- }
528
- describeCategory(category, input) {
529
- switch (category) {
530
- case "jni": return "JNI bridge hook for Java/native boundary inspection";
531
- case "aes": return "AES crypto hook for key/plaintext capture";
532
- case "md5": return "MD5 crypto hook for digest inspection";
533
- case "sha": return "SHA crypto hook for digest inspection";
534
- case "rsa": return "RSA crypto hook for key operation tracing";
535
- case "base64": return "Base64 transform hook for encoded payload tracing";
536
- case "network": return "Network hook for request and payload tracing";
537
- case "file-io": return "File I/O hook for filesystem access tracing";
538
- case "string": return "String operation hook for buffer tracing";
539
- case "obfuscation": return input.strings.some((entry) => entry.toLowerCase().includes("obfuscation")) ? "Potential obfuscation hook for runtime string decryption tracing" : "Potential obfuscation hook";
540
- case "unknown": return "Unknown hook";
541
- }
542
- }
543
- buildHookCode(fn, category) {
544
- if (category === "jni") return [
545
- "Java.perform(function () {",
546
- ` const target = ptr("${fn.address}");`,
547
- " Interceptor.attach(target, {",
548
- " onEnter(args) {",
549
- ` console.log("[jni] ${fn.name}");`,
550
- " },",
551
- " });",
552
- "});"
553
- ].join("\n");
554
- const extraLine = category === "aes" || category === "md5" || category === "sha" || category === "rsa" || category === "base64" ? " console.log(hexdump(args[0]));" : " console.log(\"[trace] entering\");";
555
- const targetName = fn.name.replace(/[^A-Za-z0-9_]/g, "_");
556
- return [
557
- `const target_${targetName} = ptr("${fn.address}");`,
558
- `Interceptor.attach(target_${targetName}, {`,
559
- " onEnter(args) {",
560
- ` console.log("[hook] ${fn.name}");`,
561
- extraLine,
562
- " },",
563
- "});"
564
- ].join("\n");
565
- }
566
- buildParameters(fn) {
567
- if (fn.parameters.length > 0) return fn.parameters.map((parameter, index) => ({
568
- name: parameter.name || `arg${index}`,
569
- type: parameter.type || "pointer",
570
- description: `Captured parameter ${index}`
571
- }));
572
- return [{
573
- name: "arg0",
574
- type: "pointer",
575
- description: "Captured parameter 0"
576
- }];
577
- }
578
- };
579
- //#endregion
580
- //#region src/modules/binary-instrument/ExtensionBridge.ts
581
- async function invokePlugin(ctx, config) {
582
- const available = getAvailablePlugins(ctx);
583
- const normalizedRequested = normalizePluginId(config.pluginId);
584
- const actualPluginId = resolvePluginId(normalizedRequested, available);
585
- if (!actualPluginId) return {
586
- success: false,
587
- tool: "binary-instrument",
588
- action: config.toolName,
589
- error: `Plugin ${normalizedRequested} is not installed`
590
- };
591
- const runtime = findRuntime(ctx, actualPluginId);
592
- if (!runtime?.lifecycleContext) return {
593
- success: false,
594
- tool: "binary-instrument",
595
- action: config.toolName,
596
- error: `Plugin ${actualPluginId} is installed but has no runtime`
597
- };
598
- try {
599
- const firstText = (await runtime.lifecycleContext.invokeTool(config.toolName, config.args)).content?.find((item) => item.type === "text")?.text;
600
- if (!firstText) return {
601
- success: false,
602
- tool: "binary-instrument",
603
- action: config.toolName,
604
- error: "Plugin returned no text content"
605
- };
606
- try {
607
- const parsed = JSON.parse(firstText);
608
- if (isResultRecord(parsed)) return {
609
- tool: "binary-instrument",
610
- action: config.toolName,
611
- success: readBoolean(parsed, "success") ?? true,
612
- data: parsed["data"],
613
- error: readString(parsed, "error")
614
- };
615
- } catch {
616
- return {
617
- success: true,
618
- tool: "binary-instrument",
619
- action: config.toolName,
620
- data: firstText
621
- };
622
- }
623
- return {
624
- success: true,
625
- tool: "binary-instrument",
626
- action: config.toolName,
627
- data: firstText
628
- };
629
- } catch (error) {
630
- return {
631
- success: false,
632
- tool: "binary-instrument",
633
- action: config.toolName,
634
- error: error instanceof Error ? error.message : String(error)
635
- };
636
- }
637
- }
638
- function getAvailablePlugins(ctx) {
639
- return Array.from(ctx.extensionPluginsById.keys()).map(normalizePluginId);
640
- }
641
- function normalizePluginId(pluginId) {
642
- return pluginId.replaceAll("_", "-");
643
- }
644
- function resolvePluginId(requested, installed) {
645
- const requestedWithoutPrefix = requested.replace(/^plugin-/, "");
646
- for (const installedId of installed) {
647
- const installedWithoutPrefix = installedId.replace(/^plugin-/, "");
648
- if (installedId === requested || installedWithoutPrefix === requestedWithoutPrefix) return installedId;
649
- }
650
- }
651
- function findRuntime(ctx, normalizedPluginId) {
652
- for (const [pluginId, runtime] of ctx.extensionPluginRuntimeById.entries()) if (normalizePluginId(pluginId) === normalizedPluginId) return isPluginRuntime(runtime) ? runtime : void 0;
653
- }
654
- function isPluginRuntime(value) {
655
- return typeof value === "object" && value !== null;
656
- }
657
- function isResultRecord(value) {
658
- return typeof value === "object" && value !== null;
659
- }
660
- function readBoolean(record, key) {
661
- const value = record[key];
662
- return typeof value === "boolean" ? value : void 0;
663
- }
664
- function readString(record, key) {
665
- const value = record[key];
666
- return typeof value === "string" ? value : void 0;
667
- }
668
- //#endregion
669
- //#region src/modules/binary-instrument/HookGenerator.ts
670
- var HookGenerator = class {
671
- generateFridaHookScript(symbols, options) {
672
- const includeArgs = options?.includeArgs ?? true;
673
- const includeRetAddr = options?.includeRetAddr ?? false;
674
- const lines = [
675
- "'use strict';",
676
- "",
677
- "function resolveTarget(name) {",
678
- " try {",
679
- " const exported = Module.findExportByName(null, name);",
680
- " if (exported) {",
681
- " return exported;",
682
- " }",
683
- " } catch (error) {}",
684
- " try {",
685
- " const symbol = DebugSymbol.fromName(name);",
686
- " if (symbol && symbol.address) {",
687
- " return symbol.address;",
688
- " }",
689
- " } catch (error) {}",
690
- " return null;",
691
- "}",
692
- "",
693
- "const installedHooks = [];"
694
- ];
695
- for (let index = 0; index < symbols.length; index += 1) {
696
- const descriptor = this.toDescriptor(symbols[index]);
697
- const varName = `target_${index}`;
698
- const label = descriptor.demangled ?? descriptor.name;
699
- const addressLine = descriptor.address ? `const ${varName} = ptr("${this.escapeForDoubleQuotes(descriptor.address)}");` : `const ${varName} = resolveTarget("${this.escapeForDoubleQuotes(descriptor.name)}");`;
700
- lines.push(addressLine);
701
- lines.push(`if (${varName}) {`);
702
- lines.push(` Interceptor.attach(${varName}, {`);
703
- lines.push(" onEnter(args) {");
704
- if (includeRetAddr) lines.push(` console.log("[binary-instrument] enter ${this.escapeForDoubleQuotes(label)} ret=" + this.returnAddress);`);
705
- else lines.push(` console.log("[binary-instrument] enter ${this.escapeForDoubleQuotes(label)}");`);
706
- if (includeArgs) {
707
- lines.push(" const renderedArgs = [];");
708
- lines.push(" for (let i = 0; i < 6; i += 1) {");
709
- lines.push(" try {");
710
- lines.push(" renderedArgs.push(String(args[i]));");
711
- lines.push(" } catch (error) {");
712
- lines.push(" renderedArgs.push(\"<unreadable>\");");
713
- lines.push(" }");
714
- lines.push(" }");
715
- lines.push(" console.log(\"[binary-instrument] args \" + JSON.stringify(renderedArgs));");
716
- }
717
- lines.push(" },");
718
- lines.push(" onLeave(retval) {");
719
- lines.push(` console.log("[binary-instrument] leave ${this.escapeForDoubleQuotes(label)} retval=" + retval);`);
720
- lines.push(" },");
721
- lines.push(" });");
722
- lines.push(` installedHooks.push({ name: "${this.escapeForDoubleQuotes(label)}", address: String(${varName}) });`);
723
- lines.push("} else {");
724
- lines.push(` console.log("[binary-instrument] unresolved ${this.escapeForDoubleQuotes(label)}");`);
725
- lines.push("}");
726
- lines.push("");
727
- }
728
- lines.push("console.log(\"[binary-instrument] hooks=\" + JSON.stringify(installedHooks));");
729
- return lines.join("\n");
730
- }
731
- generateInterceptorScript(targetFuncs) {
732
- return this.generateFridaHookScript(targetFuncs, {
733
- includeArgs: true,
734
- includeRetAddr: false
735
- });
736
- }
737
- toDescriptor(symbol) {
738
- if (typeof symbol === "string") return { name: symbol };
739
- return symbol;
740
- }
741
- escapeForDoubleQuotes(value) {
742
- return value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"");
743
- }
744
- };
745
- //#endregion
746
- //#region src/modules/binary-instrument/UnidbgRunner.ts
747
- const UNIDBG_MAX_BUFFER_BYTES = 8 * 1024 * 1024;
748
- var UnidbgRunner = class {
749
- sessions = /* @__PURE__ */ new Map();
750
- close() {
751
- for (const session of this.sessions.values()) if (session.childProcess) try {
752
- process.kill(session.childProcess.pid, "SIGTERM");
753
- } catch {}
754
- this.sessions.clear();
755
- }
756
- /**
757
- * Launch a .so library in the Unidbg emulator via JVM subprocess.
758
- * Returns a sessionId for subsequent call/trace operations.
759
- */
760
- async launch(soPath, arch = "arm", jarPath) {
761
- const resolvedJar = jarPath ?? process.env["UNIDBG_JAR"];
762
- if (!resolvedJar) throw new Error("UNIDBG_JAR is not configured. Set the UNIDBG_JAR env var or pass jarPath.");
763
- try {
764
- await access(resolvedJar);
765
- } catch {
766
- throw new Error(`Unidbg JAR not found: ${resolvedJar}`);
767
- }
768
- try {
769
- await access(soPath);
770
- } catch {
771
- throw new Error(`Shared library not found: ${soPath}`);
772
- }
773
- const sessionId = randomUUID();
774
- const command = this.getJavaCommand();
775
- const args = [
776
- "-jar",
777
- resolvedJar,
778
- "--so",
779
- soPath,
780
- "--arch",
781
- arch,
782
- "--server"
783
- ];
784
- try {
785
- const result = await this.execFileUtf8(command, args, UNIDBG_TIMEOUT_MS);
786
- const sessionInfo = this.parseLaunchOutput(result.stdout, sessionId);
787
- const session = {
788
- id: sessionInfo.id,
789
- soPath,
790
- arch,
791
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
792
- childProcess: sessionInfo.pid ? { pid: sessionInfo.pid } : void 0
793
- };
794
- this.sessions.set(sessionId, session);
795
- return {
796
- sessionId,
797
- soPath,
798
- arch
799
- };
800
- } catch (error) {
801
- const message = error instanceof Error ? error.message : String(error);
802
- logger.warn("[binary-instrument] Unidbg launch failed, registering stub session", {
803
- soPath,
804
- message
805
- });
806
- const session = {
807
- id: sessionId,
808
- soPath,
809
- arch,
810
- startedAt: (/* @__PURE__ */ new Date()).toISOString()
811
- };
812
- this.sessions.set(sessionId, session);
813
- return {
814
- sessionId,
815
- soPath,
816
- arch
817
- };
818
- }
819
- }
820
- async callFunction(sessionId, functionName, args = {}) {
821
- if (!this.sessions.get(sessionId)) throw new Error(`No unidbg session found for ${sessionId}`);
822
- const jarPath = process.env["UNIDBG_JAR"];
823
- if (!jarPath) return {
824
- sessionId,
825
- functionName,
826
- args,
827
- returnValue: "0x0",
828
- stdout: "",
829
- stderr: "",
830
- trace: ["mock-unidbg-unavailable"],
831
- _note: "Unidbg emulation requires UNIDBG_JAR to be configured"
832
- };
833
- const command = this.getJavaCommand();
834
- const callArgs = [
835
- "-jar",
836
- jarPath,
837
- "--session",
838
- sessionId,
839
- "--call",
840
- functionName,
841
- "--args",
842
- JSON.stringify(args)
843
- ];
844
- try {
845
- const result = await this.execFileUtf8(command, callArgs, UNIDBG_TIMEOUT_MS);
846
- return {
847
- sessionId,
848
- functionName,
849
- args,
850
- returnValue: this.extractReturnValue(result.stdout),
851
- stdout: result.stdout.trim(),
852
- stderr: result.stderr.trim(),
853
- trace: []
854
- };
855
- } catch (error) {
856
- return {
857
- sessionId,
858
- functionName,
859
- args,
860
- returnValue: "0x0",
861
- stdout: "",
862
- stderr: error instanceof Error ? error.message : String(error),
863
- trace: ["error"]
864
- };
865
- }
866
- }
867
- async trace(sessionId) {
868
- if (!this.sessions.get(sessionId)) throw new Error(`No unidbg session found for ${sessionId}`);
869
- const jarPath = process.env["UNIDBG_JAR"];
870
- if (!jarPath) return {
871
- sessionId,
872
- trace: ["mock-unidbg-unavailable"],
873
- _note: "Unidbg tracing requires UNIDBG_JAR to be configured"
874
- };
875
- const command = this.getJavaCommand();
876
- const traceArgs = [
877
- "-jar",
878
- jarPath,
879
- "--session",
880
- sessionId,
881
- "--trace"
882
- ];
883
- try {
884
- const result = await this.execFileUtf8(command, traceArgs, UNIDBG_TIMEOUT_MS);
885
- return {
886
- sessionId,
887
- trace: this.parseTraceOutput(result.stdout),
888
- instructionCount: this.countInstructions(result.stdout)
889
- };
890
- } catch (error) {
891
- return {
892
- sessionId,
893
- trace: ["error"],
894
- error: error instanceof Error ? error.message : String(error)
895
- };
896
- }
897
- }
898
- /**
899
- * Get info about an active Unidbg session.
900
- */
901
- getSessionInfo(sessionId) {
902
- return this.sessions.get(sessionId);
903
- }
904
- /**
905
- * List all active Unidbg sessions.
906
- */
907
- listSessions() {
908
- return Array.from(this.sessions.values()).map((s) => ({
909
- id: s.id,
910
- soPath: s.soPath,
911
- arch: s.arch,
912
- startedAt: s.startedAt
913
- }));
914
- }
915
- getJavaCommand() {
916
- return process.env["JAVA_HOME"] ? `${process.env["JAVA_HOME"]}/bin/java` : "java";
917
- }
918
- parseLaunchOutput(stdout, fallbackId) {
919
- const lines = stdout.split(/\r?\n/).filter((l) => l.trim().length > 0);
920
- for (const line of lines.toReversed()) try {
921
- const parsed = JSON.parse(line);
922
- if (typeof parsed["id"] === "string") return {
923
- id: parsed["id"],
924
- pid: typeof parsed["pid"] === "number" ? parsed["pid"] : null
925
- };
926
- } catch {}
927
- return {
928
- id: fallbackId,
929
- pid: null
930
- };
931
- }
932
- extractReturnValue(stdout) {
933
- const match = /return[=:\s]+(0x[0-9a-fA-F]+|-?\d+)/.exec(stdout);
934
- if (match?.[1]) return match[1];
935
- return "0x0";
936
- }
937
- parseTraceOutput(stdout) {
938
- return stdout.split(/\r?\n/).filter((line) => line.trim().length > 0 && !line.startsWith("{")).slice(0, 1e4);
939
- }
940
- countInstructions(stdout) {
941
- return stdout.split(/\r?\n/).filter((line) => line.trim().length > 0 && !line.startsWith("{") && /\b(ldr|str|mov|bl|b|add|sub)\b/i.test(line)).length;
942
- }
943
- async execFileUtf8(file, args, timeoutMs) {
944
- return new Promise((resolve, reject) => {
945
- execFile(file, args, {
946
- timeout: timeoutMs,
947
- windowsHide: true,
948
- maxBuffer: UNIDBG_MAX_BUFFER_BYTES,
949
- encoding: "utf8"
950
- }, (error, stdout, stderr) => {
951
- if (error) {
952
- reject(error);
953
- return;
954
- }
955
- resolve({
956
- stdout: typeof stdout === "string" ? stdout : "",
957
- stderr: typeof stderr === "string" ? stderr : "",
958
- exitCode: 0
959
- });
960
- });
961
- });
962
- }
963
- };
964
- //#endregion
965
- //#region src/modules/binary-instrument/index.ts
966
- var binary_instrument_exports = /* @__PURE__ */ __exportAll({
967
- GhidraAnalyzer: () => GhidraAnalyzer,
968
- HookGenerator: () => HookGenerator
969
- });
970
- //#endregion
971
- export { invokePlugin as a, FridaSession as c, getAvailablePlugins as i, UnidbgRunner as n, HookCodeGenerator as o, HookGenerator as r, GhidraAnalyzer as s, binary_instrument_exports as t };