@jshookmcp/jshook 0.2.9 → 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 (316) 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-CtcdK78Q.mjs → HookGeneratorBuilders.core.generators.storage-Bf1fbrNK.mjs} +66 -174
  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-CqDTB_uk.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-Bl8zkwz1.mjs → handlers-pVNpaw4A.mjs} +144 -841
  102. package/dist/handlers.impl-CD2_kOcC.mjs +1 -0
  103. package/dist/hooks-DDKppogd.mjs +600 -0
  104. package/dist/index.mjs +12 -5225
  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 +12 -7
  169. package/dist/AntiCheatDetector-BNk-EoBt.mjs +0 -244
  170. package/dist/CacheAdapters-CDe5WPSV.mjs +0 -80
  171. package/dist/CodeInjector-Cq8q01kp.mjs +0 -150
  172. package/dist/ConsoleMonitor-CPVQW1Y-.mjs +0 -2201
  173. package/dist/DarwinAPI-BNPxu0RH.mjs +0 -363
  174. package/dist/DetailedDataManager-BQQcxh64.mjs +0 -217
  175. package/dist/EventBus-DgPmwpeu.mjs +0 -141
  176. package/dist/EvidenceGraphBridge-SFesNera.mjs +0 -153
  177. package/dist/ExtensionManager-CWYgw0YW.mjs +0 -714
  178. package/dist/FingerprintManager-gzWtkKuf.mjs +0 -96
  179. package/dist/HardwareBreakpoint-B9gZCdFP.mjs +0 -239
  180. package/dist/HeapAnalyzer-BLDH0dCv.mjs +0 -284
  181. package/dist/InstrumentationSession-CvPC7Jwy.mjs +0 -244
  182. package/dist/MemoryController-CbVdCIJF.mjs +0 -167
  183. package/dist/MemoryScanSession-BsDZbLYm.mjs +0 -278
  184. package/dist/MemoryScanner-Bcpml6II.mjs +0 -425
  185. package/dist/NativeMemoryManager.impl-dZtA1ZGn.mjs +0 -482
  186. package/dist/NativeMemoryManager.utils-B-FjA2mJ.mjs +0 -165
  187. package/dist/PEAnalyzer-D1lzJ_VG.mjs +0 -385
  188. package/dist/PageController-Bqm2kZ_X.mjs +0 -417
  189. package/dist/PointerChainEngine-BOhyVsjx.mjs +0 -322
  190. package/dist/PrerequisiteError-Dl33Svkz.mjs +0 -20
  191. package/dist/ResponseBuilder-D3iFYx2N.mjs +0 -143
  192. package/dist/ReverseEvidenceGraph-Dlsk94LC.mjs +0 -269
  193. package/dist/ScriptManager-aHHq0X7U.mjs +0 -3000
  194. package/dist/Speedhack-CqdIFlQl.mjs +0 -156
  195. package/dist/StealthVerifier-Bo4T3bz8.mjs +0 -135
  196. package/dist/StructureAnalyzer-DhFaPvRO.mjs +0 -426
  197. package/dist/ToolCatalog-C0JGZoOm.mjs +0 -582
  198. package/dist/ToolError-jh9whhMd.mjs +0 -15
  199. package/dist/ToolProbe-oC7aPrkv.mjs +0 -45
  200. package/dist/ToolRegistry-BjaF4oNz.mjs +0 -131
  201. package/dist/ToolRouter.policy-BWV67ZK-.mjs +0 -304
  202. package/dist/TraceRecorder-DgxyVbdQ.mjs +0 -519
  203. package/dist/VersionDetector-CwVLVdDM.mjs +0 -104
  204. package/dist/Win32API-CePkipZY.mjs +0 -340
  205. package/dist/Win32Debug-BvKs-gxc.mjs +0 -274
  206. package/dist/WorkflowEngine-CuvkZtWu.mjs +0 -598
  207. package/dist/analysis-CL9uACt9.mjs +0 -463
  208. package/dist/artifactRetention-CFEprwPw.mjs +0 -591
  209. package/dist/artifacts-Bk2-_uPq.mjs +0 -59
  210. package/dist/betterSqlite3-0pqusHHH.mjs +0 -74
  211. package/dist/binary-instrument-CXfpx6fT.mjs +0 -979
  212. package/dist/bind-helpers-xFfRF-qm.mjs +0 -22
  213. package/dist/boringssl-inspector-BH2D3VKc.mjs +0 -180
  214. package/dist/browser-BpOr5PEx.mjs +0 -4082
  215. package/dist/chunk-CjcI7cDX.mjs +0 -15
  216. package/dist/concurrency-Bt0yv1kJ.mjs +0 -41
  217. package/dist/constants-B0OANIBL.mjs +0 -519
  218. package/dist/coordination-qUbyF8KU.mjs +0 -259
  219. package/dist/debugger-gnKxRSN0.mjs +0 -1271
  220. package/dist/definitions-6M-eejaT.mjs +0 -53
  221. package/dist/definitions-B18eyf0B.mjs +0 -18
  222. package/dist/definitions-B3QdlrHv.mjs +0 -34
  223. package/dist/definitions-B4rAvHNZ.mjs +0 -63
  224. package/dist/definitions-BB_4jnmy.mjs +0 -37
  225. package/dist/definitions-BMfYXoNC.mjs +0 -43
  226. package/dist/definitions-Beid2EB3.mjs +0 -27
  227. package/dist/definitions-C1UvM5Iy.mjs +0 -126
  228. package/dist/definitions-CXEI7QC72.mjs +0 -216
  229. package/dist/definitions-C_4r7Fo-2.mjs +0 -14
  230. package/dist/definitions-CkFDALoa.mjs +0 -26
  231. package/dist/definitions-Cke7zEb8.mjs +0 -94
  232. package/dist/definitions-ClJLzsJQ.mjs +0 -25
  233. package/dist/definitions-Cq-zroAU.mjs +0 -28
  234. package/dist/definitions-Cy3Sl6gV.mjs +0 -34
  235. package/dist/definitions-D3VsGcvz.mjs +0 -47
  236. package/dist/definitions-DVGfrn7y.mjs +0 -96
  237. package/dist/definitions-LKpC3-nL.mjs +0 -9
  238. package/dist/definitions-bAhHQJq9.mjs +0 -359
  239. package/dist/encoding-Bvz5jLRv.mjs +0 -1065
  240. package/dist/evidence-graph-bridge-C_fv9PuC.mjs +0 -135
  241. package/dist/factory-DxlGh9Xf.mjs +0 -575
  242. package/dist/formatAddress-DVkj9kpI.mjs +0 -17
  243. package/dist/graphql-DYWzJ29s.mjs +0 -1026
  244. package/dist/handlers-9sAbfIg-.mjs +0 -2552
  245. package/dist/handlers-C67ktuRN.mjs +0 -710
  246. package/dist/handlers-C87g8oCe.mjs +0 -276
  247. package/dist/handlers-CTsDAO6p.mjs +0 -681
  248. package/dist/handlers-Cgyg6c0U.mjs +0 -645
  249. package/dist/handlers-D6j6yka7.mjs +0 -2124
  250. package/dist/handlers-DdFzXLvF.mjs +0 -446
  251. package/dist/handlers-DeLOCd5m.mjs +0 -799
  252. package/dist/handlers-DlCJN4Td.mjs +0 -757
  253. package/dist/handlers-DxGIq15_2.mjs +0 -917
  254. package/dist/handlers-U6L4xhuF.mjs +0 -585
  255. package/dist/handlers-tB9Mp9ZK.mjs +0 -84
  256. package/dist/handlers-tiy7EIBp.mjs +0 -572
  257. package/dist/handlers.impl-DS0d9fUw.mjs +0 -761
  258. package/dist/hooks-CzCWByww.mjs +0 -898
  259. package/dist/logger-Dh_xb7_2.mjs +0 -93
  260. package/dist/maintenance-P7ePRXQC.mjs +0 -830
  261. package/dist/manifest-2ToTpjv8.mjs +0 -106
  262. package/dist/manifest-3g71z6Bg.mjs +0 -79
  263. package/dist/manifest-82baTv4U.mjs +0 -45
  264. package/dist/manifest-B3QVVeBS.mjs +0 -82
  265. package/dist/manifest-BB2J8IMJ.mjs +0 -149
  266. package/dist/manifest-BKbgbSiY.mjs +0 -60
  267. package/dist/manifest-Bcf-TJzH.mjs +0 -848
  268. package/dist/manifest-BmtZzQiQ2.mjs +0 -45
  269. package/dist/manifest-Bnd7kqEY.mjs +0 -55
  270. package/dist/manifest-BqQX6OQC2.mjs +0 -65
  271. package/dist/manifest-BqrQ4Tpj.mjs +0 -81
  272. package/dist/manifest-Br4RPFt5.mjs +0 -370
  273. package/dist/manifest-C5qDjysN.mjs +0 -107
  274. package/dist/manifest-C9RT5nk32.mjs +0 -34
  275. package/dist/manifest-CAhOuvSl.mjs +0 -204
  276. package/dist/manifest-CBYWCUBJ.mjs +0 -51
  277. package/dist/manifest-CFADCRa1.mjs +0 -37
  278. package/dist/manifest-CQVhavRF.mjs +0 -114
  279. package/dist/manifest-CT7zZBV1.mjs +0 -48
  280. package/dist/manifest-CV12bcrF.mjs +0 -121
  281. package/dist/manifest-CXsRWjjI.mjs +0 -224
  282. package/dist/manifest-CZLUCfG02.mjs +0 -95
  283. package/dist/manifest-D6phHKFd.mjs +0 -131
  284. package/dist/manifest-DCyjf4n2.mjs +0 -294
  285. package/dist/manifest-DHsnKgP6.mjs +0 -60
  286. package/dist/manifest-Df_dliIe.mjs +0 -55
  287. package/dist/manifest-Dh8WBmEW.mjs +0 -129
  288. package/dist/manifest-DhKRAT8_.mjs +0 -92
  289. package/dist/manifest-DlpTj4ic2.mjs +0 -193
  290. package/dist/manifest-DrbmZcFl2.mjs +0 -253
  291. package/dist/manifest-DuwHjUa5.mjs +0 -70
  292. package/dist/manifest-DzwvxPJX.mjs +0 -38
  293. package/dist/manifest-NXctwWQq.mjs +0 -68
  294. package/dist/manifest-Sc_0JQ13.mjs +0 -418
  295. package/dist/manifest-gZ4s_UtG.mjs +0 -96
  296. package/dist/manifest-qSleDqdO.mjs +0 -1023
  297. package/dist/modules-C184v-S9.mjs +0 -11365
  298. package/dist/mojo-ipc-B_H61Afw.mjs +0 -525
  299. package/dist/network-671Cw6hV.mjs +0 -3346
  300. package/dist/outputPaths-B1uGmrWZ.mjs +0 -1145
  301. package/dist/parse-args-BlRjqlkL.mjs +0 -39
  302. package/dist/platform-WmNn8Sxb.mjs +0 -2070
  303. package/dist/process-QcbIy5Zq.mjs +0 -1401
  304. package/dist/proxy-DqNs0bAd.mjs +0 -170
  305. package/dist/registry-D-6e18lB.mjs +0 -34
  306. package/dist/response-BQVP-xUn.mjs +0 -28
  307. package/dist/shared-state-board-DV-dpHFJ.mjs +0 -586
  308. package/dist/sourcemap-Dq8ez8vS.mjs +0 -650
  309. package/dist/ssrf-policy-ZaUfvhq7.mjs +0 -166
  310. package/dist/streaming-BUQ0VJsg.mjs +0 -725
  311. package/dist/tool-builder-DCbIC5Eo.mjs +0 -186
  312. package/dist/transform-CiYJfNX0.mjs +0 -1007
  313. package/dist/types-Bx92KJfT.mjs +0 -4
  314. package/dist/types-CPhOReNX.mjs +0 -37
  315. package/dist/wasm-DQTnHDs4.mjs +0 -531
  316. package/dist/workflow-f3xJOcjx.mjs +0 -725
@@ -1,979 +0,0 @@
1
- import { t as __exportAll } from "./chunk-CjcI7cDX.mjs";
2
- import { t as logger } from "./logger-Dh_xb7_2.mjs";
3
- import { $ as GHIDRA_TIMEOUT_MS, Z as FRIDA_TIMEOUT_MS, dr as UNIDBG_TIMEOUT_MS } from "./constants-B0OANIBL.mjs";
4
- import { t as probeCommand } from "./ToolProbe-oC7aPrkv.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 sessionId = randomUUID();
21
- const record = {
22
- id: sessionId,
23
- target,
24
- pid: this.resolvePid(target),
25
- status: "attached",
26
- attachedAt: (/* @__PURE__ */ new Date()).toISOString()
27
- };
28
- this.sessions.set(sessionId, record);
29
- this.activeSessionId = sessionId;
30
- return sessionId;
31
- }
32
- async detach() {
33
- const active = this.getActiveSessionRecord();
34
- if (!active) return;
35
- active.status = "detached";
36
- this.activeSessionId = void 0;
37
- }
38
- async executeScript(script) {
39
- const session = this.requireActiveSession();
40
- const result = await this.runFridaCommand(session.target, script);
41
- if (result.error) {
42
- session.status = "error";
43
- session.lastError = result.error;
44
- }
45
- return result;
46
- }
47
- async enumerateModules() {
48
- const session = this.requireActiveSession();
49
- const result = await this.runFridaCommand(session.target, "console.log(JSON.stringify(Process.enumerateModules()));");
50
- const parsed = this.parseModuleList(result.output);
51
- if (parsed.length > 0) return parsed;
52
- if (result.error) {
53
- session.status = "error";
54
- session.lastError = result.error;
55
- }
56
- return [this.createFallbackModule(session.target)];
57
- }
58
- async enumerateFunctions(moduleName) {
59
- const session = this.requireActiveSession();
60
- const safeModuleName = JSON.stringify(moduleName);
61
- const result = await this.runFridaCommand(session.target, [
62
- `const entries = Module.enumerateExportsSync(${safeModuleName})`,
63
- ".filter(function (entry) { return entry.type === \"function\"; })",
64
- ".map(function (entry) {",
65
- " return { name: entry.name, address: String(entry.address), size: 0 };",
66
- "});",
67
- "console.log(JSON.stringify(entries));"
68
- ].join(""));
69
- const parsed = this.parseFunctionList(result.output);
70
- if (parsed.length > 0) return parsed;
71
- if (result.error) {
72
- session.status = "error";
73
- session.lastError = result.error;
74
- }
75
- return [{
76
- name: `${moduleName}!<unknown>`,
77
- address: "0x0",
78
- size: 0
79
- }];
80
- }
81
- async findSymbols(pattern) {
82
- const session = this.requireActiveSession();
83
- const matchPattern = JSON.stringify(`exports:!*${pattern}*`);
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
- name: pattern,
102
- address: "0x0",
103
- demangled: pattern
104
- }];
105
- }
106
- listSessions() {
107
- return Array.from(this.sessions.values()).map((session) => ({
108
- id: session.id,
109
- target: session.target,
110
- pid: session.pid,
111
- status: session.status
112
- }));
113
- }
114
- async isAvailable() {
115
- return (await this.getAvailability()).available;
116
- }
117
- async getAvailability() {
118
- if (this.fridaProbe) return this.fridaProbe;
119
- if (!this.probePromise) this.probePromise = probeCommand("frida");
120
- const resolved = await this.probePromise;
121
- this.fridaProbe = resolved;
122
- this.probePromise = void 0;
123
- return resolved;
124
- }
125
- useSession(sessionId) {
126
- if (!this.sessions.has(sessionId)) return false;
127
- this.activeSessionId = sessionId;
128
- return true;
129
- }
130
- hasSession(sessionId) {
131
- return this.sessions.has(sessionId);
132
- }
133
- getActiveSessionRecord() {
134
- if (!this.activeSessionId) return;
135
- return this.sessions.get(this.activeSessionId);
136
- }
137
- requireActiveSession() {
138
- const session = this.getActiveSessionRecord();
139
- if (!session) throw new Error("No active Frida session. Call attach() first.");
140
- return session;
141
- }
142
- resolvePid(target) {
143
- if (!/^\d+$/.test(target)) return null;
144
- const parsed = Number.parseInt(target, 10);
145
- return Number.isNaN(parsed) ? null : parsed;
146
- }
147
- async runFridaCommand(target, script) {
148
- const availability = await this.getAvailability();
149
- if (!availability.available) return {
150
- output: "",
151
- error: availability.reason ?? "Frida CLI is not available"
152
- };
153
- const command = availability.path ?? "frida";
154
- const args = [
155
- ...this.buildTargetArgs(target),
156
- "--runtime=v8",
157
- "-q",
158
- "-e",
159
- script
160
- ];
161
- try {
162
- const result = await this.execFileUtf8(command, args, FRIDA_TIMEOUT_MS);
163
- const output = result.stdout.trim();
164
- const error = result.stderr.trim();
165
- return error ? {
166
- output,
167
- error
168
- } : { output };
169
- } catch (error) {
170
- const message = error instanceof Error ? error.message : String(error);
171
- logger.warn("[binary-instrument] Frida command failed", {
172
- target,
173
- message
174
- });
175
- return {
176
- output: "",
177
- error: message
178
- };
179
- }
180
- }
181
- buildTargetArgs(target) {
182
- if (/^\d+$/.test(target)) return ["-p", target];
183
- if (target.includes("/") || target.includes("\\")) return ["-f", target];
184
- return ["-n", target];
185
- }
186
- createFallbackModule(target) {
187
- return {
188
- name: this.extractSimpleName(target),
189
- base: "0x0",
190
- size: 0,
191
- path: target
192
- };
193
- }
194
- extractSimpleName(target) {
195
- const lastPart = target.split(/[\\/]/).filter((part) => part.length > 0).at(-1);
196
- return lastPart && lastPart.length > 0 ? lastPart : target;
197
- }
198
- parseModuleList(output) {
199
- const payload = this.extractJsonPayload(output);
200
- if (!Array.isArray(payload)) return [];
201
- const modules = [];
202
- for (const entry of payload) {
203
- if (!this.isRecord(entry)) continue;
204
- const name = this.readStringField(entry, "name");
205
- const path = this.readStringField(entry, "path");
206
- const base = this.normalizeHex(entry["base"]);
207
- const size = this.readNumberField(entry, "size");
208
- if (!name || !path || !base || size === void 0) continue;
209
- modules.push({
210
- name,
211
- base,
212
- size,
213
- path
214
- });
215
- }
216
- return modules;
217
- }
218
- parseFunctionList(output) {
219
- const payload = this.extractJsonPayload(output);
220
- if (!Array.isArray(payload)) return [];
221
- const functions = [];
222
- for (const entry of payload) {
223
- if (!this.isRecord(entry)) continue;
224
- const name = this.readStringField(entry, "name");
225
- const address = this.normalizeHex(entry["address"]);
226
- const size = this.readNumberField(entry, "size") ?? 0;
227
- if (!name || !address) continue;
228
- functions.push({
229
- name,
230
- address,
231
- size
232
- });
233
- }
234
- return functions;
235
- }
236
- parseSymbolList(output) {
237
- const payload = this.extractJsonPayload(output);
238
- if (!Array.isArray(payload)) return [];
239
- const symbols = [];
240
- for (const entry of payload) {
241
- if (!this.isRecord(entry)) continue;
242
- const name = this.readStringField(entry, "name");
243
- const address = this.normalizeHex(entry["address"]);
244
- const demangled = this.readStringField(entry, "demangled");
245
- if (!name || !address) continue;
246
- if (demangled) symbols.push({
247
- name,
248
- address,
249
- demangled
250
- });
251
- else symbols.push({
252
- name,
253
- address
254
- });
255
- }
256
- return symbols;
257
- }
258
- extractJsonPayload(output) {
259
- const candidates = output.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.startsWith("{") || line.startsWith("[")).toReversed();
260
- for (const line of candidates) try {
261
- return JSON.parse(line);
262
- } catch {
263
- continue;
264
- }
265
- }
266
- readStringField(record, key) {
267
- const value = record[key];
268
- return typeof value === "string" && value.length > 0 ? value : void 0;
269
- }
270
- readNumberField(record, key) {
271
- const value = record[key];
272
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
273
- }
274
- normalizeHex(value) {
275
- if (typeof value === "number" && Number.isFinite(value)) return `0x${value.toString(16)}`;
276
- if (typeof value === "string" && value.length > 0) return value.startsWith("0x") ? value : `0x${value}`;
277
- }
278
- isRecord(value) {
279
- return typeof value === "object" && value !== null;
280
- }
281
- execFileUtf8(file, args, timeoutMs) {
282
- return new Promise((resolve, reject) => {
283
- execFile(file, args, {
284
- timeout: timeoutMs,
285
- windowsHide: true,
286
- maxBuffer: FRIDA_MAX_BUFFER_BYTES,
287
- encoding: "utf8"
288
- }, (error, stdout, stderr) => {
289
- if (error) {
290
- reject(error);
291
- return;
292
- }
293
- resolve({
294
- stdout: typeof stdout === "string" ? stdout : "",
295
- stderr: typeof stderr === "string" ? stderr : ""
296
- });
297
- });
298
- });
299
- }
300
- };
301
- //#endregion
302
- //#region src/modules/binary-instrument/GhidraAnalyzer.ts
303
- const GHIDRA_MAX_BUFFER_BYTES = 16 * 1024 * 1024;
304
- var GhidraAnalyzer = class {
305
- ghidraProbe;
306
- probePromise;
307
- async analyze(binaryPath, options) {
308
- await access(binaryPath);
309
- const fileBuffer = await readFile(binaryPath);
310
- const strings = this.extractPrintableStrings(fileBuffer);
311
- const imports = this.deriveImports(strings);
312
- const exports = this.deriveExports(strings);
313
- if (!(await this.getAvailability()).available) return {
314
- functions: [],
315
- imports,
316
- exports,
317
- strings
318
- };
319
- const timeoutMs = typeof options?.timeout === "number" && Number.isFinite(options.timeout) ? options.timeout : GHIDRA_TIMEOUT_MS;
320
- const scriptDirectory = await mkdtemp(join(tmpdir(), "jshook-ghidra-script-"));
321
- const scriptPath = join(scriptDirectory, "BinaryInstrumentDump.py");
322
- try {
323
- await writeFile(scriptPath, this.buildDefaultScript(), "utf8");
324
- const output = await this.headlessAnalyze(scriptPath, binaryPath, timeoutMs);
325
- return {
326
- functions: this.parseDecompiledOutput(output),
327
- imports,
328
- exports,
329
- strings
330
- };
331
- } catch (error) {
332
- const message = error instanceof Error ? error.message : String(error);
333
- logger.warn("[binary-instrument] Ghidra analyze fallback", {
334
- binaryPath,
335
- message
336
- });
337
- return {
338
- functions: [],
339
- imports,
340
- exports,
341
- strings
342
- };
343
- } finally {
344
- await rm(scriptDirectory, {
345
- recursive: true,
346
- force: true
347
- });
348
- }
349
- }
350
- async headlessAnalyze(scriptPath, binaryPath, timeoutMs = GHIDRA_TIMEOUT_MS) {
351
- const availability = await this.getAvailability();
352
- if (!availability.available) throw new Error(availability.reason ?? "Ghidra analyzeHeadless is not available");
353
- await access(binaryPath);
354
- await access(scriptPath);
355
- const command = availability.path ?? "analyzeHeadless";
356
- const projectDirectory = await mkdtemp(join(tmpdir(), "jshook-ghidra-project-"));
357
- const projectName = "binary-instrument";
358
- try {
359
- const result = await this.execFileUtf8(command, [
360
- projectDirectory,
361
- projectName,
362
- "-import",
363
- binaryPath,
364
- "-scriptPath",
365
- dirname(scriptPath),
366
- "-postScript",
367
- basename(scriptPath)
368
- ], timeoutMs);
369
- return [result.stdout.trim(), result.stderr.trim()].filter((entry) => entry.length > 0).join("\n");
370
- } finally {
371
- await rm(projectDirectory, {
372
- recursive: true,
373
- force: true
374
- });
375
- }
376
- }
377
- parseDecompiledOutput(output) {
378
- const functions = [];
379
- 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;
380
- let match = blockPattern.exec(output);
381
- while (match) {
382
- const rawName = match[1] ?? "";
383
- const rawAddress = match[2] ?? "";
384
- const rawSignature = match[3] ?? "";
385
- const rawBody = match[4] ?? "";
386
- const name = rawName.trim();
387
- const address = this.normalizeHex(rawAddress.trim());
388
- const signature = rawSignature.trim();
389
- const decompiled = rawBody.trim();
390
- if (name.length > 0 && address.length > 0 && signature.length > 0) functions.push({
391
- name,
392
- address,
393
- signature,
394
- decompiled
395
- });
396
- match = blockPattern.exec(output);
397
- }
398
- return functions;
399
- }
400
- async isAvailable() {
401
- return (await this.getAvailability()).available;
402
- }
403
- async getAvailability() {
404
- if (this.ghidraProbe) return this.ghidraProbe;
405
- if (!this.probePromise) this.probePromise = probeCommand("analyzeHeadless", ["-help"]);
406
- const resolved = await this.probePromise;
407
- this.ghidraProbe = resolved;
408
- this.probePromise = void 0;
409
- return resolved;
410
- }
411
- buildDefaultScript() {
412
- return [
413
- "# @category BinaryInstrument",
414
- "from ghidra.app.decompiler import DecompInterface",
415
- "",
416
- "program = currentProgram",
417
- "interface = DecompInterface()",
418
- "interface.openProgram(program)",
419
- "function_manager = program.getFunctionManager()",
420
- "functions = function_manager.getFunctions(True)",
421
- "",
422
- "for function in functions:",
423
- " print(\"FUNCTION_START\")",
424
- " print(\"NAME:\" + str(function.getName()))",
425
- " print(\"ADDRESS:\" + str(function.getEntryPoint()))",
426
- " try:",
427
- " signature = str(function.getSignature())",
428
- " except:",
429
- " signature = str(function.getName()) + \"()\"",
430
- " print(\"SIGNATURE:\" + signature)",
431
- " print(\"DECOMPILED_START\")",
432
- " try:",
433
- " decompiled = interface.decompileFunction(function, 30, monitor).getDecompiledFunction()",
434
- " if decompiled:",
435
- " print(str(decompiled.getC()))",
436
- " else:",
437
- " print(\"// no decompiled output\")",
438
- " except:",
439
- " print(\"// decompile failed\")",
440
- " print(\"DECOMPILED_END\")",
441
- " print(\"FUNCTION_END\")"
442
- ].join("\n");
443
- }
444
- extractPrintableStrings(buffer) {
445
- const results = [];
446
- let current = "";
447
- for (const byte of buffer.values()) {
448
- if (byte >= 32 && byte <= 126) {
449
- current += String.fromCharCode(byte);
450
- continue;
451
- }
452
- if (current.length >= 4) results.push(current);
453
- current = "";
454
- }
455
- if (current.length >= 4) results.push(current);
456
- return Array.from(new Set(results)).slice(0, 1e3);
457
- }
458
- deriveImports(strings) {
459
- return strings.filter((entry) => /(?:\.dll|\.so|\.dylib|kernel32|user32|libc|printf|malloc|LoadLibrary)/i.test(entry)).slice(0, 100);
460
- }
461
- deriveExports(strings) {
462
- return strings.filter((entry) => /^[A-Za-z_][A-Za-z0-9_@?$]{2,}$/.test(entry)).slice(0, 100);
463
- }
464
- normalizeHex(value) {
465
- return value.startsWith("0x") ? value : `0x${value}`;
466
- }
467
- execFileUtf8(file, args, timeoutMs) {
468
- return new Promise((resolve, reject) => {
469
- execFile(file, args, {
470
- timeout: timeoutMs,
471
- windowsHide: true,
472
- maxBuffer: GHIDRA_MAX_BUFFER_BYTES,
473
- encoding: "utf8"
474
- }, (error, stdout, stderr) => {
475
- if (error) {
476
- reject(error);
477
- return;
478
- }
479
- resolve({
480
- stdout: typeof stdout === "string" ? stdout : "",
481
- stderr: typeof stderr === "string" ? stderr : ""
482
- });
483
- });
484
- });
485
- }
486
- };
487
- //#endregion
488
- //#region src/modules/binary-instrument/HookCodeGenerator.ts
489
- var HookCodeGenerator = class {
490
- generateHooks(input) {
491
- const templates = [];
492
- for (const fn of input.functions) {
493
- const category = this.classifyFunction(fn, input);
494
- if (category === "unknown") continue;
495
- templates.push({
496
- functionName: fn.name,
497
- description: this.describeCategory(category, input),
498
- hookCode: this.buildHookCode(fn, category),
499
- parameters: this.buildParameters(fn)
500
- });
501
- }
502
- return templates;
503
- }
504
- exportScript(templates, format) {
505
- if (format !== "frida") throw new Error("Unsupported export format");
506
- const lines = [
507
- "// Frida hook script",
508
- "// auto-generated by HookCodeGenerator",
509
- `// Hook count: ${templates.length}`,
510
- ""
511
- ];
512
- for (const template of templates) {
513
- lines.push(`// ${template.functionName}: ${template.description}`);
514
- lines.push(template.hookCode);
515
- lines.push("");
516
- }
517
- return lines.join("\n");
518
- }
519
- classifyFunction(fn, input) {
520
- const name = fn.name.toLowerCase();
521
- const imports = input.imports.map((entry) => entry.toLowerCase());
522
- const strings = input.strings.map((entry) => entry.toLowerCase());
523
- if (fn.name.startsWith("Java_")) return "jni";
524
- if (name.includes("aes")) return "aes";
525
- if (name.includes("md5")) return "md5";
526
- if (name.includes("sha")) return "sha";
527
- if (name.includes("rsa")) return "rsa";
528
- if (name.includes("base64")) return "base64";
529
- if (name.includes("send") || name.includes("recv") || name.includes("socket") || name.includes("http")) return "network";
530
- if (name.includes("open") || name.includes("read") || name.includes("write") || name.includes("fopen")) return "file-io";
531
- if ((name.includes("decrypt") || name.includes("encrypt")) && strings.some((entry) => entry.includes("obfuscation") || entry.includes("encryption"))) return "obfuscation";
532
- if (name.includes("memcpy") || name.includes("strcpy") || name.includes("memmove") || name.includes("string")) return "string";
533
- if (imports.some((entry) => entry.includes("aes"))) return "aes";
534
- return "unknown";
535
- }
536
- describeCategory(category, input) {
537
- switch (category) {
538
- case "jni": return "JNI bridge hook for Java/native boundary inspection";
539
- case "aes": return "AES crypto hook for key/plaintext capture";
540
- case "md5": return "MD5 crypto hook for digest inspection";
541
- case "sha": return "SHA crypto hook for digest inspection";
542
- case "rsa": return "RSA crypto hook for key operation tracing";
543
- case "base64": return "Base64 transform hook for encoded payload tracing";
544
- case "network": return "Network hook for request and payload tracing";
545
- case "file-io": return "File I/O hook for filesystem access tracing";
546
- case "string": return "String operation hook for buffer tracing";
547
- case "obfuscation": return input.strings.some((entry) => entry.toLowerCase().includes("obfuscation")) ? "Potential obfuscation hook for runtime string decryption tracing" : "Potential obfuscation hook";
548
- case "unknown": return "Unknown hook";
549
- }
550
- }
551
- buildHookCode(fn, category) {
552
- if (category === "jni") return [
553
- "Java.perform(function () {",
554
- ` const target = ptr("${fn.address}");`,
555
- " Interceptor.attach(target, {",
556
- " onEnter(args) {",
557
- ` console.log("[jni] ${fn.name}");`,
558
- " },",
559
- " });",
560
- "});"
561
- ].join("\n");
562
- const extraLine = category === "aes" || category === "md5" || category === "sha" || category === "rsa" || category === "base64" ? " console.log(hexdump(args[0]));" : " console.log(\"[trace] entering\");";
563
- const targetName = fn.name.replace(/[^A-Za-z0-9_]/g, "_");
564
- return [
565
- `const target_${targetName} = ptr("${fn.address}");`,
566
- `Interceptor.attach(target_${targetName}, {`,
567
- " onEnter(args) {",
568
- ` console.log("[hook] ${fn.name}");`,
569
- extraLine,
570
- " },",
571
- "});"
572
- ].join("\n");
573
- }
574
- buildParameters(fn) {
575
- if (fn.parameters.length > 0) return fn.parameters.map((parameter, index) => ({
576
- name: parameter.name || `arg${index}`,
577
- type: parameter.type || "pointer",
578
- description: `Captured parameter ${index}`
579
- }));
580
- return [{
581
- name: "arg0",
582
- type: "pointer",
583
- description: "Captured parameter 0"
584
- }];
585
- }
586
- };
587
- //#endregion
588
- //#region src/modules/binary-instrument/ExtensionBridge.ts
589
- async function invokePlugin(ctx, config) {
590
- const available = getAvailablePlugins(ctx);
591
- const normalizedRequested = normalizePluginId(config.pluginId);
592
- const actualPluginId = resolvePluginId(normalizedRequested, available);
593
- if (!actualPluginId) return {
594
- success: false,
595
- tool: "binary-instrument",
596
- action: config.toolName,
597
- error: `Plugin ${normalizedRequested} is not installed`
598
- };
599
- const runtime = findRuntime(ctx, actualPluginId);
600
- if (!runtime?.lifecycleContext) return {
601
- success: false,
602
- tool: "binary-instrument",
603
- action: config.toolName,
604
- error: `Plugin ${actualPluginId} is installed but has no runtime`
605
- };
606
- try {
607
- const firstText = (await runtime.lifecycleContext.invokeTool(config.toolName, config.args)).content?.find((item) => item.type === "text")?.text;
608
- if (!firstText) return {
609
- success: false,
610
- tool: "binary-instrument",
611
- action: config.toolName,
612
- error: "Plugin returned no text content"
613
- };
614
- try {
615
- const parsed = JSON.parse(firstText);
616
- if (isResultRecord(parsed)) return {
617
- tool: "binary-instrument",
618
- action: config.toolName,
619
- success: readBoolean(parsed, "success") ?? true,
620
- data: parsed["data"],
621
- error: readString(parsed, "error")
622
- };
623
- } catch {
624
- return {
625
- success: true,
626
- tool: "binary-instrument",
627
- action: config.toolName,
628
- data: firstText
629
- };
630
- }
631
- return {
632
- success: true,
633
- tool: "binary-instrument",
634
- action: config.toolName,
635
- data: firstText
636
- };
637
- } catch (error) {
638
- return {
639
- success: false,
640
- tool: "binary-instrument",
641
- action: config.toolName,
642
- error: error instanceof Error ? error.message : String(error)
643
- };
644
- }
645
- }
646
- function getAvailablePlugins(ctx) {
647
- return Array.from(ctx.extensionPluginsById.keys()).map(normalizePluginId);
648
- }
649
- function normalizePluginId(pluginId) {
650
- return pluginId.replaceAll("_", "-");
651
- }
652
- function resolvePluginId(requested, installed) {
653
- const requestedWithoutPrefix = requested.replace(/^plugin-/, "");
654
- for (const installedId of installed) {
655
- const installedWithoutPrefix = installedId.replace(/^plugin-/, "");
656
- if (installedId === requested || installedWithoutPrefix === requestedWithoutPrefix) return installedId;
657
- }
658
- }
659
- function findRuntime(ctx, normalizedPluginId) {
660
- for (const [pluginId, runtime] of ctx.extensionPluginRuntimeById.entries()) if (normalizePluginId(pluginId) === normalizedPluginId) return isPluginRuntime(runtime) ? runtime : void 0;
661
- }
662
- function isPluginRuntime(value) {
663
- return typeof value === "object" && value !== null;
664
- }
665
- function isResultRecord(value) {
666
- return typeof value === "object" && value !== null;
667
- }
668
- function readBoolean(record, key) {
669
- const value = record[key];
670
- return typeof value === "boolean" ? value : void 0;
671
- }
672
- function readString(record, key) {
673
- const value = record[key];
674
- return typeof value === "string" ? value : void 0;
675
- }
676
- //#endregion
677
- //#region src/modules/binary-instrument/HookGenerator.ts
678
- var HookGenerator = class {
679
- generateFridaHookScript(symbols, options) {
680
- const includeArgs = options?.includeArgs ?? true;
681
- const includeRetAddr = options?.includeRetAddr ?? false;
682
- const lines = [
683
- "'use strict';",
684
- "",
685
- "function resolveTarget(name) {",
686
- " try {",
687
- " const exported = Module.findExportByName(null, name);",
688
- " if (exported) {",
689
- " return exported;",
690
- " }",
691
- " } catch (error) {}",
692
- " try {",
693
- " const symbol = DebugSymbol.fromName(name);",
694
- " if (symbol && symbol.address) {",
695
- " return symbol.address;",
696
- " }",
697
- " } catch (error) {}",
698
- " return null;",
699
- "}",
700
- "",
701
- "const installedHooks = [];"
702
- ];
703
- for (let index = 0; index < symbols.length; index += 1) {
704
- const descriptor = this.toDescriptor(symbols[index]);
705
- const varName = `target_${index}`;
706
- const label = descriptor.demangled ?? descriptor.name;
707
- const addressLine = descriptor.address ? `const ${varName} = ptr("${this.escapeForDoubleQuotes(descriptor.address)}");` : `const ${varName} = resolveTarget("${this.escapeForDoubleQuotes(descriptor.name)}");`;
708
- lines.push(addressLine);
709
- lines.push(`if (${varName}) {`);
710
- lines.push(` Interceptor.attach(${varName}, {`);
711
- lines.push(" onEnter(args) {");
712
- if (includeRetAddr) lines.push(` console.log("[binary-instrument] enter ${this.escapeForDoubleQuotes(label)} ret=" + this.returnAddress);`);
713
- else lines.push(` console.log("[binary-instrument] enter ${this.escapeForDoubleQuotes(label)}");`);
714
- if (includeArgs) {
715
- lines.push(" const renderedArgs = [];");
716
- lines.push(" for (let i = 0; i < 6; i += 1) {");
717
- lines.push(" try {");
718
- lines.push(" renderedArgs.push(String(args[i]));");
719
- lines.push(" } catch (error) {");
720
- lines.push(" renderedArgs.push(\"<unreadable>\");");
721
- lines.push(" }");
722
- lines.push(" }");
723
- lines.push(" console.log(\"[binary-instrument] args \" + JSON.stringify(renderedArgs));");
724
- }
725
- lines.push(" },");
726
- lines.push(" onLeave(retval) {");
727
- lines.push(` console.log("[binary-instrument] leave ${this.escapeForDoubleQuotes(label)} retval=" + retval);`);
728
- lines.push(" },");
729
- lines.push(" });");
730
- lines.push(` installedHooks.push({ name: "${this.escapeForDoubleQuotes(label)}", address: String(${varName}) });`);
731
- lines.push("} else {");
732
- lines.push(` console.log("[binary-instrument] unresolved ${this.escapeForDoubleQuotes(label)}");`);
733
- lines.push("}");
734
- lines.push("");
735
- }
736
- lines.push("console.log(\"[binary-instrument] hooks=\" + JSON.stringify(installedHooks));");
737
- return lines.join("\n");
738
- }
739
- generateInterceptorScript(targetFuncs) {
740
- return this.generateFridaHookScript(targetFuncs, {
741
- includeArgs: true,
742
- includeRetAddr: false
743
- });
744
- }
745
- toDescriptor(symbol) {
746
- if (typeof symbol === "string") return { name: symbol };
747
- return symbol;
748
- }
749
- escapeForDoubleQuotes(value) {
750
- return value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"");
751
- }
752
- };
753
- //#endregion
754
- //#region src/modules/binary-instrument/UnidbgRunner.ts
755
- const UNIDBG_MAX_BUFFER_BYTES = 8 * 1024 * 1024;
756
- var UnidbgRunner = class {
757
- sessions = /* @__PURE__ */ new Map();
758
- close() {
759
- for (const session of this.sessions.values()) if (session.childProcess) try {
760
- process.kill(session.childProcess.pid, "SIGTERM");
761
- } catch {}
762
- this.sessions.clear();
763
- }
764
- /**
765
- * Launch a .so library in the Unidbg emulator via JVM subprocess.
766
- * Returns a sessionId for subsequent call/trace operations.
767
- */
768
- async launch(soPath, arch = "arm", jarPath) {
769
- const resolvedJar = jarPath ?? process.env["UNIDBG_JAR"];
770
- if (!resolvedJar) throw new Error("UNIDBG_JAR is not configured. Set the UNIDBG_JAR env var or pass jarPath.");
771
- try {
772
- await access(resolvedJar);
773
- } catch {
774
- throw new Error(`Unidbg JAR not found: ${resolvedJar}`);
775
- }
776
- try {
777
- await access(soPath);
778
- } catch {
779
- throw new Error(`Shared library not found: ${soPath}`);
780
- }
781
- const sessionId = randomUUID();
782
- const command = this.getJavaCommand();
783
- const args = [
784
- "-jar",
785
- resolvedJar,
786
- "--so",
787
- soPath,
788
- "--arch",
789
- arch,
790
- "--server"
791
- ];
792
- try {
793
- const result = await this.execFileUtf8(command, args, UNIDBG_TIMEOUT_MS);
794
- const sessionInfo = this.parseLaunchOutput(result.stdout, sessionId);
795
- const session = {
796
- id: sessionInfo.id,
797
- soPath,
798
- arch,
799
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
800
- childProcess: sessionInfo.pid ? { pid: sessionInfo.pid } : void 0
801
- };
802
- this.sessions.set(sessionId, session);
803
- return {
804
- sessionId,
805
- soPath,
806
- arch
807
- };
808
- } catch (error) {
809
- const message = error instanceof Error ? error.message : String(error);
810
- logger.warn("[binary-instrument] Unidbg launch failed, registering stub session", {
811
- soPath,
812
- message
813
- });
814
- const session = {
815
- id: sessionId,
816
- soPath,
817
- arch,
818
- startedAt: (/* @__PURE__ */ new Date()).toISOString()
819
- };
820
- this.sessions.set(sessionId, session);
821
- return {
822
- sessionId,
823
- soPath,
824
- arch
825
- };
826
- }
827
- }
828
- async callFunction(sessionId, functionName, args = {}) {
829
- if (!this.sessions.get(sessionId)) throw new Error(`No unidbg session found for ${sessionId}`);
830
- const jarPath = process.env["UNIDBG_JAR"];
831
- if (!jarPath) return {
832
- sessionId,
833
- functionName,
834
- args,
835
- returnValue: "0x0",
836
- stdout: "",
837
- stderr: "",
838
- trace: ["mock-unidbg-unavailable"],
839
- _note: "Unidbg emulation requires UNIDBG_JAR to be configured"
840
- };
841
- const command = this.getJavaCommand();
842
- const callArgs = [
843
- "-jar",
844
- jarPath,
845
- "--session",
846
- sessionId,
847
- "--call",
848
- functionName,
849
- "--args",
850
- JSON.stringify(args)
851
- ];
852
- try {
853
- const result = await this.execFileUtf8(command, callArgs, UNIDBG_TIMEOUT_MS);
854
- return {
855
- sessionId,
856
- functionName,
857
- args,
858
- returnValue: this.extractReturnValue(result.stdout),
859
- stdout: result.stdout.trim(),
860
- stderr: result.stderr.trim(),
861
- trace: []
862
- };
863
- } catch (error) {
864
- return {
865
- sessionId,
866
- functionName,
867
- args,
868
- returnValue: "0x0",
869
- stdout: "",
870
- stderr: error instanceof Error ? error.message : String(error),
871
- trace: ["error"]
872
- };
873
- }
874
- }
875
- async trace(sessionId) {
876
- if (!this.sessions.get(sessionId)) throw new Error(`No unidbg session found for ${sessionId}`);
877
- const jarPath = process.env["UNIDBG_JAR"];
878
- if (!jarPath) return {
879
- sessionId,
880
- trace: ["mock-unidbg-unavailable"],
881
- _note: "Unidbg tracing requires UNIDBG_JAR to be configured"
882
- };
883
- const command = this.getJavaCommand();
884
- const traceArgs = [
885
- "-jar",
886
- jarPath,
887
- "--session",
888
- sessionId,
889
- "--trace"
890
- ];
891
- try {
892
- const result = await this.execFileUtf8(command, traceArgs, UNIDBG_TIMEOUT_MS);
893
- return {
894
- sessionId,
895
- trace: this.parseTraceOutput(result.stdout),
896
- instructionCount: this.countInstructions(result.stdout)
897
- };
898
- } catch (error) {
899
- return {
900
- sessionId,
901
- trace: ["error"],
902
- error: error instanceof Error ? error.message : String(error)
903
- };
904
- }
905
- }
906
- /**
907
- * Get info about an active Unidbg session.
908
- */
909
- getSessionInfo(sessionId) {
910
- return this.sessions.get(sessionId);
911
- }
912
- /**
913
- * List all active Unidbg sessions.
914
- */
915
- listSessions() {
916
- return Array.from(this.sessions.values()).map((s) => ({
917
- id: s.id,
918
- soPath: s.soPath,
919
- arch: s.arch,
920
- startedAt: s.startedAt
921
- }));
922
- }
923
- getJavaCommand() {
924
- return process.env["JAVA_HOME"] ? `${process.env["JAVA_HOME"]}/bin/java` : "java";
925
- }
926
- parseLaunchOutput(stdout, fallbackId) {
927
- const lines = stdout.split(/\r?\n/).filter((l) => l.trim().length > 0);
928
- for (const line of lines.toReversed()) try {
929
- const parsed = JSON.parse(line);
930
- if (typeof parsed["id"] === "string") return {
931
- id: parsed["id"],
932
- pid: typeof parsed["pid"] === "number" ? parsed["pid"] : null
933
- };
934
- } catch {}
935
- return {
936
- id: fallbackId,
937
- pid: null
938
- };
939
- }
940
- extractReturnValue(stdout) {
941
- const match = /return[=:\s]+(0x[0-9a-fA-F]+|-?\d+)/.exec(stdout);
942
- if (match?.[1]) return match[1];
943
- return "0x0";
944
- }
945
- parseTraceOutput(stdout) {
946
- return stdout.split(/\r?\n/).filter((line) => line.trim().length > 0 && !line.startsWith("{")).slice(0, 1e4);
947
- }
948
- countInstructions(stdout) {
949
- 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;
950
- }
951
- async execFileUtf8(file, args, timeoutMs) {
952
- return new Promise((resolve, reject) => {
953
- execFile(file, args, {
954
- timeout: timeoutMs,
955
- windowsHide: true,
956
- maxBuffer: UNIDBG_MAX_BUFFER_BYTES,
957
- encoding: "utf8"
958
- }, (error, stdout, stderr) => {
959
- if (error) {
960
- reject(error);
961
- return;
962
- }
963
- resolve({
964
- stdout: typeof stdout === "string" ? stdout : "",
965
- stderr: typeof stderr === "string" ? stderr : "",
966
- exitCode: 0
967
- });
968
- });
969
- });
970
- }
971
- };
972
- //#endregion
973
- //#region src/modules/binary-instrument/index.ts
974
- var binary_instrument_exports = /* @__PURE__ */ __exportAll({
975
- GhidraAnalyzer: () => GhidraAnalyzer,
976
- HookGenerator: () => HookGenerator
977
- });
978
- //#endregion
979
- 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 };