@ai-jshook/mcp 0.1.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 (271) hide show
  1. package/.env.example +38 -0
  2. package/CLAUDE.md +170 -0
  3. package/README.md +564 -0
  4. package/bun.lock +1484 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +57 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/modules/analyzer/AISummarizer.d.ts +41 -0
  10. package/dist/modules/analyzer/AISummarizer.d.ts.map +1 -0
  11. package/dist/modules/analyzer/AISummarizer.js +186 -0
  12. package/dist/modules/analyzer/AISummarizer.js.map +1 -0
  13. package/dist/modules/analyzer/CodeAnalyzer.d.ts +28 -0
  14. package/dist/modules/analyzer/CodeAnalyzer.d.ts.map +1 -0
  15. package/dist/modules/analyzer/CodeAnalyzer.js +1287 -0
  16. package/dist/modules/analyzer/CodeAnalyzer.js.map +1 -0
  17. package/dist/modules/analyzer/IntelligentAnalyzer.d.ts +114 -0
  18. package/dist/modules/analyzer/IntelligentAnalyzer.d.ts.map +1 -0
  19. package/dist/modules/analyzer/IntelligentAnalyzer.js +1176 -0
  20. package/dist/modules/analyzer/IntelligentAnalyzer.js.map +1 -0
  21. package/dist/modules/browser/BrowserModeManager.d.ts +31 -0
  22. package/dist/modules/browser/BrowserModeManager.d.ts.map +1 -0
  23. package/dist/modules/browser/BrowserModeManager.js +241 -0
  24. package/dist/modules/browser/BrowserModeManager.js.map +1 -0
  25. package/dist/modules/captcha/AICaptchaDetector.d.ts +32 -0
  26. package/dist/modules/captcha/AICaptchaDetector.d.ts.map +1 -0
  27. package/dist/modules/captcha/AICaptchaDetector.js +387 -0
  28. package/dist/modules/captcha/AICaptchaDetector.js.map +1 -0
  29. package/dist/modules/captcha/CaptchaDetector.d.ts +28 -0
  30. package/dist/modules/captcha/CaptchaDetector.d.ts.map +1 -0
  31. package/dist/modules/captcha/CaptchaDetector.js +513 -0
  32. package/dist/modules/captcha/CaptchaDetector.js.map +1 -0
  33. package/dist/modules/collector/CodeCache.d.ts +37 -0
  34. package/dist/modules/collector/CodeCache.d.ts.map +1 -0
  35. package/dist/modules/collector/CodeCache.js +188 -0
  36. package/dist/modules/collector/CodeCache.js.map +1 -0
  37. package/dist/modules/collector/CodeCollector.d.ts +107 -0
  38. package/dist/modules/collector/CodeCollector.d.ts.map +1 -0
  39. package/dist/modules/collector/CodeCollector.js +796 -0
  40. package/dist/modules/collector/CodeCollector.js.map +1 -0
  41. package/dist/modules/collector/CodeCompressor.d.ts +65 -0
  42. package/dist/modules/collector/CodeCompressor.d.ts.map +1 -0
  43. package/dist/modules/collector/CodeCompressor.js +245 -0
  44. package/dist/modules/collector/CodeCompressor.js.map +1 -0
  45. package/dist/modules/collector/DOMInspector.d.ts +51 -0
  46. package/dist/modules/collector/DOMInspector.d.ts.map +1 -0
  47. package/dist/modules/collector/DOMInspector.js +437 -0
  48. package/dist/modules/collector/DOMInspector.js.map +1 -0
  49. package/dist/modules/collector/PageController.d.ts +79 -0
  50. package/dist/modules/collector/PageController.d.ts.map +1 -0
  51. package/dist/modules/collector/PageController.js +287 -0
  52. package/dist/modules/collector/PageController.js.map +1 -0
  53. package/dist/modules/collector/SmartCodeCollector.d.ts +38 -0
  54. package/dist/modules/collector/SmartCodeCollector.d.ts.map +1 -0
  55. package/dist/modules/collector/SmartCodeCollector.js +208 -0
  56. package/dist/modules/collector/SmartCodeCollector.js.map +1 -0
  57. package/dist/modules/collector/StreamingCollector.d.ts +46 -0
  58. package/dist/modules/collector/StreamingCollector.d.ts.map +1 -0
  59. package/dist/modules/collector/StreamingCollector.js +127 -0
  60. package/dist/modules/collector/StreamingCollector.js.map +1 -0
  61. package/dist/modules/crypto/CryptoDetector.d.ts +22 -0
  62. package/dist/modules/crypto/CryptoDetector.d.ts.map +1 -0
  63. package/dist/modules/crypto/CryptoDetector.js +168 -0
  64. package/dist/modules/crypto/CryptoDetector.js.map +1 -0
  65. package/dist/modules/crypto/CryptoDetectorEnhanced.d.ts +31 -0
  66. package/dist/modules/crypto/CryptoDetectorEnhanced.d.ts.map +1 -0
  67. package/dist/modules/crypto/CryptoDetectorEnhanced.js +269 -0
  68. package/dist/modules/crypto/CryptoDetectorEnhanced.js.map +1 -0
  69. package/dist/modules/crypto/CryptoRules.d.ts +59 -0
  70. package/dist/modules/crypto/CryptoRules.d.ts.map +1 -0
  71. package/dist/modules/crypto/CryptoRules.js +234 -0
  72. package/dist/modules/crypto/CryptoRules.js.map +1 -0
  73. package/dist/modules/debugger/BlackboxManager.d.ts +14 -0
  74. package/dist/modules/debugger/BlackboxManager.d.ts.map +1 -0
  75. package/dist/modules/debugger/BlackboxManager.js +98 -0
  76. package/dist/modules/debugger/BlackboxManager.js.map +1 -0
  77. package/dist/modules/debugger/DebuggerManager.d.ts +138 -0
  78. package/dist/modules/debugger/DebuggerManager.d.ts.map +1 -0
  79. package/dist/modules/debugger/DebuggerManager.js +777 -0
  80. package/dist/modules/debugger/DebuggerManager.js.map +1 -0
  81. package/dist/modules/debugger/EventBreakpointManager.d.ts +30 -0
  82. package/dist/modules/debugger/EventBreakpointManager.d.ts.map +1 -0
  83. package/dist/modules/debugger/EventBreakpointManager.js +125 -0
  84. package/dist/modules/debugger/EventBreakpointManager.js.map +1 -0
  85. package/dist/modules/debugger/RuntimeInspector.d.ts +54 -0
  86. package/dist/modules/debugger/RuntimeInspector.d.ts.map +1 -0
  87. package/dist/modules/debugger/RuntimeInspector.js +277 -0
  88. package/dist/modules/debugger/RuntimeInspector.js.map +1 -0
  89. package/dist/modules/debugger/ScriptManager.d.ts +94 -0
  90. package/dist/modules/debugger/ScriptManager.d.ts.map +1 -0
  91. package/dist/modules/debugger/ScriptManager.js +433 -0
  92. package/dist/modules/debugger/ScriptManager.js.map +1 -0
  93. package/dist/modules/debugger/WatchExpressionManager.d.ts +52 -0
  94. package/dist/modules/debugger/WatchExpressionManager.d.ts.map +1 -0
  95. package/dist/modules/debugger/WatchExpressionManager.js +136 -0
  96. package/dist/modules/debugger/WatchExpressionManager.js.map +1 -0
  97. package/dist/modules/debugger/XHRBreakpointManager.d.ts +21 -0
  98. package/dist/modules/debugger/XHRBreakpointManager.d.ts.map +1 -0
  99. package/dist/modules/debugger/XHRBreakpointManager.js +81 -0
  100. package/dist/modules/debugger/XHRBreakpointManager.js.map +1 -0
  101. package/dist/modules/deobfuscator/ASTOptimizer.d.ts +12 -0
  102. package/dist/modules/deobfuscator/ASTOptimizer.d.ts.map +1 -0
  103. package/dist/modules/deobfuscator/ASTOptimizer.js +234 -0
  104. package/dist/modules/deobfuscator/ASTOptimizer.js.map +1 -0
  105. package/dist/modules/deobfuscator/AdvancedDeobfuscator.d.ts +52 -0
  106. package/dist/modules/deobfuscator/AdvancedDeobfuscator.d.ts.map +1 -0
  107. package/dist/modules/deobfuscator/AdvancedDeobfuscator.js +985 -0
  108. package/dist/modules/deobfuscator/AdvancedDeobfuscator.js.map +1 -0
  109. package/dist/modules/deobfuscator/Deobfuscator.d.ts +23 -0
  110. package/dist/modules/deobfuscator/Deobfuscator.d.ts.map +1 -0
  111. package/dist/modules/deobfuscator/Deobfuscator.js +487 -0
  112. package/dist/modules/deobfuscator/Deobfuscator.js.map +1 -0
  113. package/dist/modules/deobfuscator/JSVMPDeobfuscator.d.ts +19 -0
  114. package/dist/modules/deobfuscator/JSVMPDeobfuscator.d.ts.map +1 -0
  115. package/dist/modules/deobfuscator/JSVMPDeobfuscator.js +594 -0
  116. package/dist/modules/deobfuscator/JSVMPDeobfuscator.js.map +1 -0
  117. package/dist/modules/deobfuscator/JScramberDeobfuscator.d.ts +28 -0
  118. package/dist/modules/deobfuscator/JScramberDeobfuscator.d.ts.map +1 -0
  119. package/dist/modules/deobfuscator/JScramberDeobfuscator.js +239 -0
  120. package/dist/modules/deobfuscator/JScramberDeobfuscator.js.map +1 -0
  121. package/dist/modules/deobfuscator/PackerDeobfuscator.d.ts +38 -0
  122. package/dist/modules/deobfuscator/PackerDeobfuscator.d.ts.map +1 -0
  123. package/dist/modules/deobfuscator/PackerDeobfuscator.js +191 -0
  124. package/dist/modules/deobfuscator/PackerDeobfuscator.js.map +1 -0
  125. package/dist/modules/detector/ObfuscationDetector.d.ts +35 -0
  126. package/dist/modules/detector/ObfuscationDetector.d.ts.map +1 -0
  127. package/dist/modules/detector/ObfuscationDetector.js +278 -0
  128. package/dist/modules/detector/ObfuscationDetector.js.map +1 -0
  129. package/dist/modules/emulator/AIEnvironmentAnalyzer.d.ts +32 -0
  130. package/dist/modules/emulator/AIEnvironmentAnalyzer.d.ts.map +1 -0
  131. package/dist/modules/emulator/AIEnvironmentAnalyzer.js +548 -0
  132. package/dist/modules/emulator/AIEnvironmentAnalyzer.js.map +1 -0
  133. package/dist/modules/emulator/BrowserAPIDatabase.d.ts +34 -0
  134. package/dist/modules/emulator/BrowserAPIDatabase.d.ts.map +1 -0
  135. package/dist/modules/emulator/BrowserAPIDatabase.js +326 -0
  136. package/dist/modules/emulator/BrowserAPIDatabase.js.map +1 -0
  137. package/dist/modules/emulator/BrowserEnvironmentRules.d.ts +47 -0
  138. package/dist/modules/emulator/BrowserEnvironmentRules.d.ts.map +1 -0
  139. package/dist/modules/emulator/BrowserEnvironmentRules.js +493 -0
  140. package/dist/modules/emulator/BrowserEnvironmentRules.js.map +1 -0
  141. package/dist/modules/emulator/EnvironmentEmulator.d.ts +27 -0
  142. package/dist/modules/emulator/EnvironmentEmulator.d.ts.map +1 -0
  143. package/dist/modules/emulator/EnvironmentEmulator.js +1113 -0
  144. package/dist/modules/emulator/EnvironmentEmulator.js.map +1 -0
  145. package/dist/modules/emulator/EnvironmentEmulatorEnhanced.d.ts +26 -0
  146. package/dist/modules/emulator/EnvironmentEmulatorEnhanced.d.ts.map +1 -0
  147. package/dist/modules/emulator/EnvironmentEmulatorEnhanced.js +493 -0
  148. package/dist/modules/emulator/EnvironmentEmulatorEnhanced.js.map +1 -0
  149. package/dist/modules/emulator/templates/chrome-env.d.ts +260 -0
  150. package/dist/modules/emulator/templates/chrome-env.d.ts.map +1 -0
  151. package/dist/modules/emulator/templates/chrome-env.js +253 -0
  152. package/dist/modules/emulator/templates/chrome-env.js.map +1 -0
  153. package/dist/modules/hook/AIHookGenerator.d.ts +53 -0
  154. package/dist/modules/hook/AIHookGenerator.d.ts.map +1 -0
  155. package/dist/modules/hook/AIHookGenerator.js +353 -0
  156. package/dist/modules/hook/AIHookGenerator.js.map +1 -0
  157. package/dist/modules/hook/HookManager.d.ts +67 -0
  158. package/dist/modules/hook/HookManager.d.ts.map +1 -0
  159. package/dist/modules/hook/HookManager.js +1225 -0
  160. package/dist/modules/hook/HookManager.js.map +1 -0
  161. package/dist/modules/monitor/ConsoleMonitor.d.ts +140 -0
  162. package/dist/modules/monitor/ConsoleMonitor.d.ts.map +1 -0
  163. package/dist/modules/monitor/ConsoleMonitor.js +834 -0
  164. package/dist/modules/monitor/ConsoleMonitor.js.map +1 -0
  165. package/dist/modules/monitor/PerformanceMonitor.d.ts +65 -0
  166. package/dist/modules/monitor/PerformanceMonitor.d.ts.map +1 -0
  167. package/dist/modules/monitor/PerformanceMonitor.js +175 -0
  168. package/dist/modules/monitor/PerformanceMonitor.js.map +1 -0
  169. package/dist/modules/stealth/StealthScripts2025.d.ts +17 -0
  170. package/dist/modules/stealth/StealthScripts2025.d.ts.map +1 -0
  171. package/dist/modules/stealth/StealthScripts2025.js +274 -0
  172. package/dist/modules/stealth/StealthScripts2025.js.map +1 -0
  173. package/dist/modules/symbolic/JSVMPSymbolicExecutor.d.ts +69 -0
  174. package/dist/modules/symbolic/JSVMPSymbolicExecutor.d.ts.map +1 -0
  175. package/dist/modules/symbolic/JSVMPSymbolicExecutor.js +232 -0
  176. package/dist/modules/symbolic/JSVMPSymbolicExecutor.js.map +1 -0
  177. package/dist/modules/symbolic/SymbolicExecutor.d.ts +69 -0
  178. package/dist/modules/symbolic/SymbolicExecutor.d.ts.map +1 -0
  179. package/dist/modules/symbolic/SymbolicExecutor.js +346 -0
  180. package/dist/modules/symbolic/SymbolicExecutor.js.map +1 -0
  181. package/dist/server/AIHookToolDefinitions.d.ts +3 -0
  182. package/dist/server/AIHookToolDefinitions.d.ts.map +1 -0
  183. package/dist/server/AIHookToolDefinitions.js +284 -0
  184. package/dist/server/AIHookToolDefinitions.js.map +1 -0
  185. package/dist/server/AIHookToolHandlers.d.ts +50 -0
  186. package/dist/server/AIHookToolHandlers.d.ts.map +1 -0
  187. package/dist/server/AIHookToolHandlers.js +311 -0
  188. package/dist/server/AIHookToolHandlers.js.map +1 -0
  189. package/dist/server/AdvancedToolDefinitions.d.ts +3 -0
  190. package/dist/server/AdvancedToolDefinitions.d.ts.map +1 -0
  191. package/dist/server/AdvancedToolDefinitions.js +218 -0
  192. package/dist/server/AdvancedToolDefinitions.js.map +1 -0
  193. package/dist/server/AdvancedToolHandlers.d.ts +85 -0
  194. package/dist/server/AdvancedToolHandlers.d.ts.map +1 -0
  195. package/dist/server/AdvancedToolHandlers.js +431 -0
  196. package/dist/server/AdvancedToolHandlers.js.map +1 -0
  197. package/dist/server/BrowserToolDefinitions.d.ts +3 -0
  198. package/dist/server/BrowserToolDefinitions.d.ts.map +1 -0
  199. package/dist/server/BrowserToolDefinitions.js +841 -0
  200. package/dist/server/BrowserToolDefinitions.js.map +1 -0
  201. package/dist/server/BrowserToolHandlers.d.ts +290 -0
  202. package/dist/server/BrowserToolHandlers.d.ts.map +1 -0
  203. package/dist/server/BrowserToolHandlers.js +784 -0
  204. package/dist/server/BrowserToolHandlers.js.map +1 -0
  205. package/dist/server/CacheToolDefinitions.d.ts +3 -0
  206. package/dist/server/CacheToolDefinitions.d.ts.map +1 -0
  207. package/dist/server/CacheToolDefinitions.js +166 -0
  208. package/dist/server/CacheToolDefinitions.js.map +1 -0
  209. package/dist/server/DebuggerToolDefinitions.d.ts +3 -0
  210. package/dist/server/DebuggerToolDefinitions.d.ts.map +1 -0
  211. package/dist/server/DebuggerToolDefinitions.js +600 -0
  212. package/dist/server/DebuggerToolDefinitions.js.map +1 -0
  213. package/dist/server/DebuggerToolHandlers.d.ts +230 -0
  214. package/dist/server/DebuggerToolHandlers.d.ts.map +1 -0
  215. package/dist/server/DebuggerToolHandlers.js +935 -0
  216. package/dist/server/DebuggerToolHandlers.js.map +1 -0
  217. package/dist/server/MCPServer.d.ts +55 -0
  218. package/dist/server/MCPServer.d.ts.map +1 -0
  219. package/dist/server/MCPServer.js +1344 -0
  220. package/dist/server/MCPServer.js.map +1 -0
  221. package/dist/server/TokenBudgetToolDefinitions.d.ts +3 -0
  222. package/dist/server/TokenBudgetToolDefinitions.d.ts.map +1 -0
  223. package/dist/server/TokenBudgetToolDefinitions.js +114 -0
  224. package/dist/server/TokenBudgetToolDefinitions.js.map +1 -0
  225. package/dist/services/LLMService.d.ts +41 -0
  226. package/dist/services/LLMService.d.ts.map +1 -0
  227. package/dist/services/LLMService.js +792 -0
  228. package/dist/services/LLMService.js.map +1 -0
  229. package/dist/types/index.d.ts +527 -0
  230. package/dist/types/index.d.ts.map +1 -0
  231. package/dist/types/index.js +2 -0
  232. package/dist/types/index.js.map +1 -0
  233. package/dist/utils/AdaptiveDataSerializer.d.ts +27 -0
  234. package/dist/utils/AdaptiveDataSerializer.d.ts.map +1 -0
  235. package/dist/utils/AdaptiveDataSerializer.js +215 -0
  236. package/dist/utils/AdaptiveDataSerializer.js.map +1 -0
  237. package/dist/utils/CacheAdapters.d.ts +30 -0
  238. package/dist/utils/CacheAdapters.d.ts.map +1 -0
  239. package/dist/utils/CacheAdapters.js +83 -0
  240. package/dist/utils/CacheAdapters.js.map +1 -0
  241. package/dist/utils/TokenBudgetManager.d.ts +52 -0
  242. package/dist/utils/TokenBudgetManager.d.ts.map +1 -0
  243. package/dist/utils/TokenBudgetManager.js +190 -0
  244. package/dist/utils/TokenBudgetManager.js.map +1 -0
  245. package/dist/utils/UnifiedCacheManager.d.ts +55 -0
  246. package/dist/utils/UnifiedCacheManager.d.ts.map +1 -0
  247. package/dist/utils/UnifiedCacheManager.js +207 -0
  248. package/dist/utils/UnifiedCacheManager.js.map +1 -0
  249. package/dist/utils/cache.d.ts +13 -0
  250. package/dist/utils/cache.d.ts.map +1 -0
  251. package/dist/utils/cache.js +92 -0
  252. package/dist/utils/cache.js.map +1 -0
  253. package/dist/utils/config.d.ts +7 -0
  254. package/dist/utils/config.d.ts.map +1 -0
  255. package/dist/utils/config.js +93 -0
  256. package/dist/utils/config.js.map +1 -0
  257. package/dist/utils/detailedDataManager.d.ts +60 -0
  258. package/dist/utils/detailedDataManager.d.ts.map +1 -0
  259. package/dist/utils/detailedDataManager.js +204 -0
  260. package/dist/utils/detailedDataManager.js.map +1 -0
  261. package/dist/utils/logger.d.ts +16 -0
  262. package/dist/utils/logger.d.ts.map +1 -0
  263. package/dist/utils/logger.js +47 -0
  264. package/dist/utils/logger.js.map +1 -0
  265. package/dist/utils/parallel.d.ts +40 -0
  266. package/dist/utils/parallel.d.ts.map +1 -0
  267. package/dist/utils/parallel.js +148 -0
  268. package/dist/utils/parallel.js.map +1 -0
  269. package/package.json +94 -0
  270. package/server.json +39 -0
  271. package/tsconfig.dev.json +14 -0
@@ -0,0 +1,985 @@
1
+ import { logger } from '../../utils/logger.js';
2
+ import * as parser from '@babel/parser';
3
+ import traverse from '@babel/traverse';
4
+ import generate from '@babel/generator';
5
+ import * as t from '@babel/types';
6
+ export class AdvancedDeobfuscator {
7
+ llm;
8
+ constructor(llm) {
9
+ this.llm = llm;
10
+ }
11
+ async deobfuscate(options) {
12
+ logger.info('Starting advanced deobfuscation...');
13
+ const startTime = Date.now();
14
+ let code = options.code;
15
+ const detectedTechniques = [];
16
+ const warnings = [];
17
+ let vmDetected;
18
+ let astOptimized = false;
19
+ try {
20
+ code = this.normalizeCode(code);
21
+ if (this.detectInvisibleUnicode(code)) {
22
+ detectedTechniques.push('invisible-unicode');
23
+ logger.info('Detected: Invisible Unicode Obfuscation (2025)');
24
+ code = this.decodeInvisibleUnicode(code);
25
+ }
26
+ if (this.detectStringEncoding(code)) {
27
+ detectedTechniques.push('string-encoding');
28
+ logger.info('Detected: String Encoding');
29
+ code = this.decodeStrings(code);
30
+ }
31
+ const vmInfo = this.detectVMProtection(code);
32
+ if (vmInfo.detected) {
33
+ detectedTechniques.push('vm-protection');
34
+ logger.info(`Detected: VM Protection (${vmInfo.type})`);
35
+ vmDetected = {
36
+ type: vmInfo.type,
37
+ instructions: vmInfo.instructionCount,
38
+ deobfuscated: false,
39
+ };
40
+ if (options.aggressiveVM) {
41
+ const vmResult = await this.deobfuscateVM(code, vmInfo);
42
+ if (vmResult.success) {
43
+ code = vmResult.code;
44
+ vmDetected.deobfuscated = true;
45
+ }
46
+ else {
47
+ warnings.push('VM deobfuscation failed, code may be incomplete');
48
+ }
49
+ }
50
+ }
51
+ if (this.detectControlFlowFlattening(code)) {
52
+ detectedTechniques.push('control-flow-flattening');
53
+ logger.info('Detected: Control Flow Flattening');
54
+ code = await this.unflattenControlFlow(code);
55
+ }
56
+ if (this.detectStringArrayRotation(code)) {
57
+ detectedTechniques.push('string-array-rotation');
58
+ logger.info('Detected: String Array Rotation');
59
+ code = this.derotateStringArray(code);
60
+ }
61
+ if (this.detectDeadCodeInjection(code)) {
62
+ detectedTechniques.push('dead-code-injection');
63
+ logger.info('Detected: Dead Code Injection');
64
+ code = this.removeDeadCode(code);
65
+ }
66
+ if (this.detectOpaquePredicates(code)) {
67
+ detectedTechniques.push('opaque-predicates');
68
+ logger.info('Detected: Opaque Predicates');
69
+ code = this.removeOpaquePredicates(code);
70
+ }
71
+ if (options.useASTOptimization !== false) {
72
+ logger.info('Applying AST optimizations...');
73
+ const optimized = this.applyASTOptimizations(code);
74
+ if (optimized !== code) {
75
+ code = optimized;
76
+ astOptimized = true;
77
+ detectedTechniques.push('ast-optimized');
78
+ }
79
+ }
80
+ if (this.llm && detectedTechniques.length > 0) {
81
+ logger.info('Using LLM for final cleanup...');
82
+ const llmResult = await this.llmCleanup(code, detectedTechniques);
83
+ if (llmResult) {
84
+ code = llmResult;
85
+ }
86
+ }
87
+ const duration = Date.now() - startTime;
88
+ const confidence = this.calculateConfidence(detectedTechniques, warnings, code);
89
+ logger.success(`Advanced deobfuscation completed in ${duration}ms`);
90
+ return {
91
+ code,
92
+ detectedTechniques,
93
+ confidence,
94
+ warnings,
95
+ vmDetected,
96
+ astOptimized,
97
+ };
98
+ }
99
+ catch (error) {
100
+ logger.error('Advanced deobfuscation failed', error);
101
+ throw error;
102
+ }
103
+ }
104
+ detectInvisibleUnicode(code) {
105
+ const invisibleChars = [
106
+ '\u200B',
107
+ '\u200C',
108
+ '\u200D',
109
+ '\u2060',
110
+ '\uFEFF',
111
+ ];
112
+ return invisibleChars.some(char => code.includes(char));
113
+ }
114
+ decodeInvisibleUnicode(code) {
115
+ logger.info('Decoding invisible unicode...');
116
+ const charToBit = {
117
+ '\u200B': '0',
118
+ '\u200C': '1',
119
+ '\u200D': '00',
120
+ '\u2060': '01',
121
+ '\uFEFF': '10',
122
+ };
123
+ let decoded = code;
124
+ const invisiblePattern = /[\u200B\u200C\u200D\u2060\uFEFF]+/g;
125
+ const matches = code.match(invisiblePattern);
126
+ if (matches) {
127
+ matches.forEach(match => {
128
+ let binary = '';
129
+ for (const char of match) {
130
+ binary += charToBit[char] || '';
131
+ }
132
+ if (binary.length % 8 === 0) {
133
+ let text = '';
134
+ for (let i = 0; i < binary.length; i += 8) {
135
+ const byte = binary.substring(i, i + 8);
136
+ text += String.fromCharCode(parseInt(byte, 2));
137
+ }
138
+ decoded = decoded.replace(match, text);
139
+ }
140
+ });
141
+ }
142
+ return decoded;
143
+ }
144
+ detectVMProtection(code) {
145
+ const vmPatterns = [
146
+ /while\s*\(\s*true\s*\)\s*\{[\s\S]*?switch\s*\(/i,
147
+ /var\s+\w+\s*=\s*\[\s*\d+(?:\s*,\s*\d+){10,}\s*\]/i,
148
+ /\w+\[pc\+\+\]/i,
149
+ /stack\.push|stack\.pop/i,
150
+ ];
151
+ const matchCount = vmPatterns.filter(pattern => pattern.test(code)).length;
152
+ if (matchCount >= 2) {
153
+ return {
154
+ detected: true,
155
+ type: matchCount >= 3 ? 'custom-vm' : 'simple-vm',
156
+ instructionCount: this.countVMInstructions(code),
157
+ };
158
+ }
159
+ return { detected: false, type: 'none', instructionCount: 0 };
160
+ }
161
+ countVMInstructions(code) {
162
+ const match = code.match(/case\s+\d+:/g);
163
+ return match ? match.length : 0;
164
+ }
165
+ async deobfuscateVM(code, vmInfo) {
166
+ logger.warn('VM deobfuscation is experimental and may fail');
167
+ try {
168
+ const vmStructure = this.analyzeVMStructure(code);
169
+ if (vmStructure.hasInterpreter) {
170
+ logger.info(`Detected VM interpreter with ${vmStructure.instructionTypes.length} instruction types`);
171
+ }
172
+ const vmComponents = this.extractVMComponents(code);
173
+ if (this.llm) {
174
+ const prompt = this.buildVMDeobfuscationPrompt(code, vmInfo, vmStructure, vmComponents);
175
+ const response = await this.llm.chat([
176
+ {
177
+ role: 'system',
178
+ content: `# Role
179
+ You are a world-class expert in JavaScript VM deobfuscation and reverse engineering with expertise in:
180
+ - Virtual machine architecture and instruction set design
181
+ - Bytecode interpretation and JIT compilation
182
+ - Control flow reconstruction from VM instructions
183
+ - Stack-based and register-based VM analysis
184
+ - Obfuscation techniques used by TikTok, Shopee, and commercial protectors
185
+
186
+ # Task
187
+ Analyze VM-protected JavaScript code and reconstruct the original, readable JavaScript.
188
+
189
+ # Methodology
190
+ 1. **Identify VM Components**: Locate instruction array, interpreter loop, stack/registers
191
+ 2. **Decode Instructions**: Map VM opcodes to JavaScript operations
192
+ 3. **Reconstruct Control Flow**: Convert VM jumps/branches to if/while/for
193
+ 4. **Simplify**: Remove VM overhead and restore natural code structure
194
+ 5. **Validate**: Ensure output is syntactically valid and functionally equivalent
195
+
196
+ # Critical Requirements
197
+ - Output ONLY valid, executable JavaScript (no markdown, no explanations)
198
+ - Preserve exact program logic and side effects
199
+ - Use meaningful variable names based on context
200
+ - Add brief comments for complex patterns
201
+ - Do NOT hallucinate or guess functionality
202
+ - If uncertain, preserve original code structure
203
+
204
+ # Output Format
205
+ Return clean JavaScript code without any wrapper or formatting.`
206
+ },
207
+ { role: 'user', content: prompt },
208
+ ], {
209
+ temperature: 0.05,
210
+ maxTokens: 4000,
211
+ });
212
+ const deobfuscatedCode = this.extractCodeFromLLMResponse(response.content);
213
+ if (this.isValidJavaScript(deobfuscatedCode)) {
214
+ logger.success('VM deobfuscation succeeded via LLM');
215
+ return {
216
+ success: true,
217
+ code: deobfuscatedCode,
218
+ };
219
+ }
220
+ else {
221
+ logger.warn('LLM output is not valid JavaScript, falling back to original');
222
+ }
223
+ }
224
+ const simplifiedCode = this.simplifyVMCode(code, vmComponents);
225
+ return {
226
+ success: simplifiedCode !== code,
227
+ code: simplifiedCode
228
+ };
229
+ }
230
+ catch (error) {
231
+ logger.error('VM deobfuscation failed', error);
232
+ return { success: false, code };
233
+ }
234
+ }
235
+ analyzeVMStructure(code) {
236
+ const structure = {
237
+ hasInterpreter: false,
238
+ instructionTypes: [],
239
+ hasStack: false,
240
+ hasRegisters: false,
241
+ };
242
+ if (/while\s*\(\s*true\s*\)|for\s*\(\s*;\s*;\s*\)/.test(code)) {
243
+ structure.hasInterpreter = true;
244
+ }
245
+ const switchMatches = code.match(/case\s+0x[0-9a-f]+:/gi);
246
+ if (switchMatches && switchMatches.length > 10) {
247
+ structure.hasInterpreter = true;
248
+ structure.instructionTypes = switchMatches.map(m => m.replace(/case\s+/i, '').replace(/:/, ''));
249
+ }
250
+ if (/\.push\(|\.pop\(/.test(code)) {
251
+ structure.hasStack = true;
252
+ }
253
+ if (/r\d+\s*=|reg\[\d+\]/.test(code)) {
254
+ structure.hasRegisters = true;
255
+ }
256
+ return structure;
257
+ }
258
+ extractVMComponents(code) {
259
+ const components = {};
260
+ try {
261
+ const ast = parser.parse(code, {
262
+ sourceType: 'module',
263
+ plugins: ['jsx', 'typescript'],
264
+ });
265
+ traverse(ast, {
266
+ VariableDeclarator(path) {
267
+ if (t.isArrayExpression(path.node.init)) {
268
+ const arrayLength = path.node.init.elements.length;
269
+ if (arrayLength > 50) {
270
+ const arrayName = t.isIdentifier(path.node.id) ? path.node.id.name : 'unknown';
271
+ const firstElement = path.node.init.elements[0];
272
+ if (t.isNumericLiteral(firstElement)) {
273
+ components.instructionArray = arrayName;
274
+ }
275
+ else if (t.isStringLiteral(firstElement)) {
276
+ components.dataArray = arrayName;
277
+ }
278
+ }
279
+ }
280
+ },
281
+ FunctionDeclaration(path) {
282
+ let hasBigSwitch = false;
283
+ traverse(path.node, {
284
+ SwitchStatement(switchPath) {
285
+ if (switchPath.node.cases.length > 10) {
286
+ hasBigSwitch = true;
287
+ }
288
+ },
289
+ }, path.scope, path);
290
+ if (hasBigSwitch && t.isIdentifier(path.node.id)) {
291
+ components.interpreterFunction = path.node.id.name;
292
+ }
293
+ },
294
+ });
295
+ }
296
+ catch (error) {
297
+ logger.debug('Failed to extract VM components:', error);
298
+ }
299
+ return components;
300
+ }
301
+ buildVMDeobfuscationPrompt(code, vmInfo, vmStructure, vmComponents) {
302
+ const codeSnippet = code.length > 6000 ? code.substring(0, 6000) + '\n\n// ... (code truncated)' : code;
303
+ return `# VM Deobfuscation Analysis
304
+
305
+ ## VM Profile
306
+ - **Architecture**: ${vmInfo.type}
307
+ - **Instruction Count**: ${vmInfo.instructionCount}
308
+ - **Interpreter Loop**: ${vmStructure.hasInterpreter ? 'Detected' : 'Not detected'}
309
+ - **Stack Operations**: ${vmStructure.hasStack ? 'Present' : 'Absent'}
310
+ - **Register Usage**: ${vmStructure.hasRegisters ? 'Present' : 'Absent'}
311
+ - **Instruction Variety**: ${vmStructure.instructionTypes.length} distinct types
312
+
313
+ ## Identified Components
314
+ ${vmComponents.instructionArray ? `✓ Instruction Array: Found at ${vmComponents.instructionArray}` : '✗ Instruction Array: Not found'}
315
+ ${vmComponents.dataArray ? `✓ Data Array: Found at ${vmComponents.dataArray}` : '✗ Data Array: Not found'}
316
+ ${vmComponents.interpreterFunction ? `✓ Interpreter Function: Found at ${vmComponents.interpreterFunction}` : '✗ Interpreter Function: Not found'}
317
+
318
+ ## VM-Protected Code
319
+ \`\`\`javascript
320
+ ${codeSnippet}
321
+ \`\`\`
322
+
323
+ ## Deobfuscation Instructions (Chain-of-Thought)
324
+
325
+ ### Step 1: VM Structure Analysis
326
+ Examine the code to identify:
327
+ - Instruction array (usually a large array of numbers/strings)
328
+ - Interpreter loop (while/for loop processing instructions)
329
+ - Stack/register variables
330
+ - Opcode handlers (switch-case or if-else chains)
331
+
332
+ ### Step 2: Instruction Decoding
333
+ For each instruction type, determine:
334
+ - What JavaScript operation it represents (e.g., opcode 0x01 = addition)
335
+ - How it manipulates the stack/registers
336
+ - What side effects it has (function calls, property access, etc.)
337
+
338
+ ### Step 3: Control Flow Reconstruction
339
+ - Map VM jumps/branches to JavaScript if/while/for statements
340
+ - Identify function calls and returns
341
+ - Reconstruct try-catch blocks if present
342
+
343
+ ### Step 4: Code Generation
344
+ - Replace VM instruction sequences with equivalent JavaScript
345
+ - Use meaningful variable names based on usage context
346
+ - Remove VM overhead (interpreter loop, stack management)
347
+ - Preserve all side effects and program behavior
348
+
349
+ ### Step 5: Validation
350
+ - Ensure output is syntactically valid JavaScript
351
+ - Verify no functionality is lost
352
+ - Add comments for complex patterns
353
+
354
+ ## Example Transformation (Few-shot Learning)
355
+
356
+ **VM Code (Before)**:
357
+ \`\`\`javascript
358
+ var vm = [0x01, 0x05, 0x02, 0x03, 0x10];
359
+ var stack = [];
360
+ for(var i=0; i<vm.length; i++) {
361
+ switch(vm[i]) {
362
+ case 0x01: stack.push(5); break;
363
+ case 0x02: stack.push(3); break;
364
+ case 0x10: var b=stack.pop(), a=stack.pop(); stack.push(a+b); break;
365
+ }
366
+ }
367
+ console.log(stack[0]);
368
+ \`\`\`
369
+
370
+ **Deobfuscated Code (After)**:
371
+ \`\`\`javascript
372
+ // VM instructions decoded: PUSH 5, PUSH 3, ADD
373
+ var result = 5 + 3;
374
+ console.log(result);
375
+ \`\`\`
376
+
377
+ ## Critical Requirements
378
+ 1. Output ONLY the deobfuscated JavaScript code
379
+ 2. NO markdown code blocks, NO explanations, NO comments outside the code
380
+ 3. Code must be syntactically valid and executable
381
+ 4. Preserve exact program logic and side effects
382
+ 5. If full deobfuscation is impossible, return the best partial result
383
+
384
+ ## Output Format
385
+ Return clean JavaScript code starting immediately (no preamble).`;
386
+ }
387
+ extractCodeFromLLMResponse(response) {
388
+ let code = response.trim();
389
+ code = code.replace(/^```(?:javascript|js)?\s*\n/i, '');
390
+ code = code.replace(/\n```\s*$/i, '');
391
+ return code.trim();
392
+ }
393
+ isValidJavaScript(code) {
394
+ try {
395
+ parser.parse(code, {
396
+ sourceType: 'module',
397
+ plugins: ['jsx', 'typescript'],
398
+ });
399
+ return true;
400
+ }
401
+ catch {
402
+ return false;
403
+ }
404
+ }
405
+ simplifyVMCode(code, vmComponents) {
406
+ try {
407
+ let simplified = code;
408
+ if (vmComponents.interpreterFunction) {
409
+ const regex = new RegExp(`function\\s+${vmComponents.interpreterFunction}\\s*\\([^)]*\\)\\s*\\{[^}]*\\}`, 'g');
410
+ simplified = simplified.replace(regex, '// VM interpreter removed');
411
+ }
412
+ if (vmComponents.instructionArray) {
413
+ const regex = new RegExp(`var\\s+${vmComponents.instructionArray}\\s*=\\s*\\[[^\\]]*\\];`, 'g');
414
+ simplified = simplified.replace(regex, '// VM instruction array removed');
415
+ }
416
+ return simplified;
417
+ }
418
+ catch (error) {
419
+ logger.debug('Failed to simplify VM code:', error);
420
+ return code;
421
+ }
422
+ }
423
+ detectControlFlowFlattening(code) {
424
+ const pattern = /while\s*\(\s*!!\s*\[\s*\]\s*\)\s*\{[\s\S]*?switch\s*\(/i;
425
+ return pattern.test(code);
426
+ }
427
+ async unflattenControlFlow(code) {
428
+ logger.info('Unflattening control flow...');
429
+ if (this.llm) {
430
+ try {
431
+ const codeSnippet = code.length > 3000 ? code.substring(0, 3000) + '\n\n// ... (truncated)' : code;
432
+ const response = await this.llm.chat([
433
+ {
434
+ role: 'system',
435
+ content: `# Role
436
+ You are an expert in JavaScript control flow deobfuscation specializing in:
437
+ - Control flow flattening detection and removal
438
+ - Switch-case state machine analysis
439
+ - Dispatcher loop identification
440
+ - Control flow graph (CFG) reconstruction
441
+
442
+ # Task
443
+ Analyze control flow flattened JavaScript and reconstruct the original, natural control flow.
444
+
445
+ # Control Flow Flattening Pattern
446
+ Obfuscators replace normal if/while/for with a dispatcher loop:
447
+ \`\`\`javascript
448
+ // Flattened (obfuscated)
449
+ var state = '0';
450
+ while (true) {
451
+ switch (state) {
452
+ case '0': console.log('a'); state = '1'; break;
453
+ case '1': console.log('b'); state = '2'; break;
454
+ case '2': return;
455
+ }
456
+ }
457
+
458
+ // Original (deobfuscated)
459
+ console.log('a');
460
+ console.log('b');
461
+ return;
462
+ \`\`\`
463
+
464
+ # Requirements
465
+ - Output ONLY valid JavaScript code
466
+ - Preserve exact program logic
467
+ - Remove dispatcher loops and state variables
468
+ - Restore natural if/while/for structures
469
+ - Use meaningful variable names`
470
+ },
471
+ {
472
+ role: 'user',
473
+ content: `# Control Flow Flattened Code
474
+ \`\`\`javascript
475
+ ${codeSnippet}
476
+ \`\`\`
477
+
478
+ # Instructions
479
+ 1. Identify the dispatcher loop (while/for with switch-case)
480
+ 2. Trace state transitions to determine execution order
481
+ 3. Reconstruct original control flow (if/while/for)
482
+ 4. Remove state variables and dispatcher overhead
483
+ 5. Return ONLY the deobfuscated code (no explanations)
484
+
485
+ Output the deobfuscated JavaScript code:`
486
+ },
487
+ ], {
488
+ temperature: 0.1,
489
+ maxTokens: 3000,
490
+ });
491
+ return this.extractCodeFromLLMResponse(response.content);
492
+ }
493
+ catch (error) {
494
+ logger.warn('LLM control flow unflattening failed', error);
495
+ }
496
+ }
497
+ return code;
498
+ }
499
+ detectStringArrayRotation(code) {
500
+ return /\w+\s*=\s*\w+\s*\+\s*0x[0-9a-f]+/.test(code);
501
+ }
502
+ derotateStringArray(code) {
503
+ logger.info('Derotating string array...');
504
+ try {
505
+ const ast = parser.parse(code, {
506
+ sourceType: 'module',
507
+ plugins: ['jsx', 'typescript'],
508
+ });
509
+ let derotated = 0;
510
+ traverse(ast, {
511
+ CallExpression(path) {
512
+ if (!t.isFunctionExpression(path.node.callee) &&
513
+ !t.isArrowFunctionExpression(path.node.callee)) {
514
+ return;
515
+ }
516
+ const func = path.node.callee;
517
+ if (!t.isFunctionExpression(func) || !t.isBlockStatement(func.body)) {
518
+ return;
519
+ }
520
+ const hasWhileLoop = func.body.body.some(stmt => t.isWhileStatement(stmt));
521
+ const hasArrayRotation = JSON.stringify(func.body).includes('push') &&
522
+ JSON.stringify(func.body).includes('shift');
523
+ if (hasWhileLoop && hasArrayRotation) {
524
+ logger.debug('Found string array rotation IIFE');
525
+ path.remove();
526
+ derotated++;
527
+ }
528
+ },
529
+ });
530
+ if (derotated > 0) {
531
+ logger.info(`Removed ${derotated} string array rotation functions`);
532
+ return generate(ast, { comments: true, compact: false }).code;
533
+ }
534
+ return code;
535
+ }
536
+ catch (error) {
537
+ logger.error('Failed to derotate string array:', error);
538
+ return code;
539
+ }
540
+ }
541
+ detectDeadCodeInjection(code) {
542
+ return /if\s*\(\s*false\s*\)|if\s*\(\s*!!\s*\[\s*\]\s*\)/.test(code);
543
+ }
544
+ removeDeadCode(code) {
545
+ logger.info('Removing dead code...');
546
+ try {
547
+ const ast = parser.parse(code, {
548
+ sourceType: 'module',
549
+ plugins: ['jsx', 'typescript'],
550
+ });
551
+ let removed = 0;
552
+ traverse(ast, {
553
+ IfStatement(path) {
554
+ const test = path.node.test;
555
+ if (t.isBooleanLiteral(test) && test.value === false) {
556
+ if (path.node.alternate) {
557
+ path.replaceWith(path.node.alternate);
558
+ }
559
+ else {
560
+ path.remove();
561
+ }
562
+ removed++;
563
+ return;
564
+ }
565
+ if (t.isBooleanLiteral(test) && test.value === true) {
566
+ path.replaceWith(path.node.consequent);
567
+ removed++;
568
+ return;
569
+ }
570
+ if (t.isUnaryExpression(test) && test.operator === '!' &&
571
+ t.isUnaryExpression(test.argument) && test.argument.operator === '!' &&
572
+ t.isArrayExpression(test.argument.argument)) {
573
+ path.replaceWith(path.node.consequent);
574
+ removed++;
575
+ return;
576
+ }
577
+ },
578
+ BlockStatement(path) {
579
+ const body = path.node.body;
580
+ let foundTerminator = false;
581
+ const newBody = [];
582
+ for (const stmt of body) {
583
+ if (foundTerminator) {
584
+ removed++;
585
+ continue;
586
+ }
587
+ newBody.push(stmt);
588
+ if (t.isReturnStatement(stmt) || t.isThrowStatement(stmt)) {
589
+ foundTerminator = true;
590
+ }
591
+ }
592
+ if (newBody.length < body.length) {
593
+ path.node.body = newBody;
594
+ }
595
+ },
596
+ });
597
+ if (removed > 0) {
598
+ logger.info(`Removed ${removed} dead code blocks`);
599
+ return generate(ast, { comments: true, compact: false }).code;
600
+ }
601
+ return code;
602
+ }
603
+ catch (error) {
604
+ logger.error('Failed to remove dead code:', error);
605
+ return code;
606
+ }
607
+ }
608
+ detectOpaquePredicates(code) {
609
+ return /if\s*\(\s*\d+\s*[<>!=]+\s*\d+\s*\)/.test(code);
610
+ }
611
+ removeOpaquePredicates(code) {
612
+ logger.info('Removing opaque predicates...');
613
+ try {
614
+ const ast = parser.parse(code, {
615
+ sourceType: 'module',
616
+ plugins: ['jsx', 'typescript'],
617
+ });
618
+ let removed = 0;
619
+ traverse(ast, {
620
+ IfStatement(path) {
621
+ const test = path.node.test;
622
+ if (t.isBinaryExpression(test)) {
623
+ const left = test.left;
624
+ const right = test.right;
625
+ const operator = test.operator;
626
+ if (t.isNumericLiteral(left) && t.isNumericLiteral(right)) {
627
+ let result;
628
+ switch (operator) {
629
+ case '>':
630
+ result = left.value > right.value;
631
+ break;
632
+ case '<':
633
+ result = left.value < right.value;
634
+ break;
635
+ case '>=':
636
+ result = left.value >= right.value;
637
+ break;
638
+ case '<=':
639
+ result = left.value <= right.value;
640
+ break;
641
+ case '===':
642
+ case '==':
643
+ result = left.value === right.value;
644
+ break;
645
+ case '!==':
646
+ case '!=':
647
+ result = left.value !== right.value;
648
+ break;
649
+ }
650
+ if (result !== undefined) {
651
+ if (result) {
652
+ path.replaceWith(path.node.consequent);
653
+ }
654
+ else {
655
+ if (path.node.alternate) {
656
+ path.replaceWith(path.node.alternate);
657
+ }
658
+ else {
659
+ path.remove();
660
+ }
661
+ }
662
+ removed++;
663
+ return;
664
+ }
665
+ }
666
+ }
667
+ if (t.isBinaryExpression(test) && (test.operator === '===' || test.operator === '==')) {
668
+ const left = test.left;
669
+ const right = test.right;
670
+ if (t.isBinaryExpression(left) && left.operator === '*' &&
671
+ t.isNumericLiteral(right) && right.value === 0) {
672
+ if ((t.isNumericLiteral(left.left) && left.left.value === 0) ||
673
+ (t.isNumericLiteral(left.right) && left.right.value === 0)) {
674
+ path.replaceWith(path.node.consequent);
675
+ removed++;
676
+ return;
677
+ }
678
+ }
679
+ }
680
+ },
681
+ });
682
+ if (removed > 0) {
683
+ logger.info(`Removed ${removed} opaque predicates`);
684
+ return generate(ast, { comments: true, compact: false }).code;
685
+ }
686
+ return code;
687
+ }
688
+ catch (error) {
689
+ logger.error('Failed to remove opaque predicates:', error);
690
+ return code;
691
+ }
692
+ }
693
+ async llmCleanup(code, techniques) {
694
+ if (!this.llm)
695
+ return null;
696
+ try {
697
+ const codeSnippet = code.length > 3000 ? code.substring(0, 3000) + '\n\n// ... (code truncated)' : code;
698
+ const prompt = `# Code Cleanup Task
699
+
700
+ ## Detected Obfuscation Techniques
701
+ ${techniques.map(t => `- ${t}`).join('\n')}
702
+
703
+ ## Deobfuscated Code (needs cleanup)
704
+ \`\`\`javascript
705
+ ${codeSnippet}
706
+ \`\`\`
707
+
708
+ ## Your Task
709
+ Clean up and improve this deobfuscated JavaScript code:
710
+
711
+ 1. **Variable Naming**: Rename variables to meaningful names based on their usage
712
+ - Avoid generic names like 'a', 'b', 'temp'
713
+ - Use descriptive names like 'userConfig', 'apiEndpoint', 'responseData'
714
+
715
+ 2. **Code Structure**: Improve readability
716
+ - Remove unnecessary parentheses and brackets
717
+ - Simplify complex expressions
718
+ - Extract magic numbers to named constants
719
+
720
+ 3. **Comments**: Add brief comments for:
721
+ - Complex logic or algorithms
722
+ - Non-obvious functionality
723
+ - Important data structures
724
+
725
+ 4. **Consistency**: Ensure consistent code style
726
+ - Use consistent indentation
727
+ - Follow JavaScript best practices
728
+
729
+ ## Important Rules
730
+ - Preserve ALL original functionality
731
+ - Do NOT remove any functional code
732
+ - Do NOT change the program logic
733
+ - Output ONLY valid JavaScript code
734
+ - Do NOT add explanations outside the code
735
+
736
+ ## Output Format
737
+ Return only the cleaned JavaScript code without markdown formatting.`;
738
+ const response = await this.llm.chat([
739
+ {
740
+ role: 'system',
741
+ content: `# Role
742
+ You are an expert JavaScript code reviewer and refactoring specialist with expertise in:
743
+ - Code readability and maintainability improvement
744
+ - Semantic variable naming based on usage context
745
+ - Code smell detection and refactoring
746
+ - JavaScript best practices (ES6+, clean code principles)
747
+ - Preserving exact program functionality during refactoring
748
+
749
+ # Task
750
+ Clean up and improve deobfuscated JavaScript code while preserving 100% of its functionality.
751
+
752
+ # Refactoring Principles
753
+ 1. **Semantic Naming**: Infer variable purpose from usage patterns
754
+ - API calls → apiClient, fetchData, apiResponse
755
+ - DOM elements → userInput, submitButton, errorMessage
756
+ - Crypto operations → encryptedData, decryptionKey, hashValue
757
+ - Loops/counters → index, itemCount, currentPage
758
+
759
+ 2. **Code Simplification**: Remove obfuscation artifacts
760
+ - Unnecessary IIFEs and closures
761
+ - Redundant variable assignments
762
+ - Complex ternary chains → if-else
763
+ - Magic numbers → named constants
764
+
765
+ 3. **Structure Improvement**: Enhance readability
766
+ - Extract repeated code to functions
767
+ - Group related operations
768
+ - Consistent indentation and spacing
769
+ - Logical code organization
770
+
771
+ # Critical Constraints
772
+ - **NEVER** change program logic or behavior
773
+ - **NEVER** remove functional code (even if it looks redundant)
774
+ - **NEVER** add new functionality
775
+ - **ONLY** improve naming, structure, and readability
776
+ - Output must be syntactically valid JavaScript
777
+ - Preserve all side effects and edge cases
778
+
779
+ # Output Format
780
+ Return ONLY the cleaned JavaScript code (no markdown, no explanations).`
781
+ },
782
+ { role: 'user', content: prompt },
783
+ ], {
784
+ temperature: 0.15,
785
+ maxTokens: 3000,
786
+ });
787
+ const cleanedCode = this.extractCodeFromLLMResponse(response.content);
788
+ if (this.isValidJavaScript(cleanedCode)) {
789
+ logger.success('LLM cleanup succeeded');
790
+ return cleanedCode;
791
+ }
792
+ else {
793
+ logger.warn('LLM cleanup produced invalid JavaScript');
794
+ return null;
795
+ }
796
+ }
797
+ catch (error) {
798
+ logger.warn('LLM cleanup failed', error);
799
+ return null;
800
+ }
801
+ }
802
+ normalizeCode(code) {
803
+ code = code.replace(/\s+/g, ' ');
804
+ code = code.replace(/\/\*[\s\S]*?\*\//g, '');
805
+ code = code.replace(/\/\/.*/g, '');
806
+ return code.trim();
807
+ }
808
+ detectStringEncoding(code) {
809
+ const patterns = [
810
+ /\\x[0-9a-f]{2}/i,
811
+ /\\u[0-9a-f]{4}/i,
812
+ /String\.fromCharCode/i,
813
+ /atob\(/i,
814
+ ];
815
+ return patterns.some(p => p.test(code));
816
+ }
817
+ decodeStrings(code) {
818
+ logger.info('Decoding strings...');
819
+ try {
820
+ const ast = parser.parse(code, {
821
+ sourceType: 'module',
822
+ plugins: ['jsx', 'typescript'],
823
+ });
824
+ let decoded = 0;
825
+ traverse(ast, {
826
+ CallExpression(path) {
827
+ if (t.isMemberExpression(path.node.callee) &&
828
+ t.isIdentifier(path.node.callee.object, { name: 'String' }) &&
829
+ t.isIdentifier(path.node.callee.property, { name: 'fromCharCode' })) {
830
+ const allNumbers = path.node.arguments.every((arg) => t.isNumericLiteral(arg));
831
+ if (allNumbers) {
832
+ const charCodes = path.node.arguments.map((arg) => arg.value);
833
+ const decodedString = String.fromCharCode(...charCodes);
834
+ path.replaceWith(t.stringLiteral(decodedString));
835
+ decoded++;
836
+ }
837
+ }
838
+ },
839
+ });
840
+ if (decoded > 0) {
841
+ logger.info(`Decoded ${decoded} string expressions`);
842
+ return generate(ast, { comments: false, compact: false }).code;
843
+ }
844
+ return code;
845
+ }
846
+ catch (error) {
847
+ logger.error('Failed to decode strings:', error);
848
+ return code;
849
+ }
850
+ }
851
+ applyASTOptimizations(code) {
852
+ logger.info('Applying AST optimizations...');
853
+ try {
854
+ const ast = parser.parse(code, {
855
+ sourceType: 'module',
856
+ plugins: ['jsx', 'typescript'],
857
+ });
858
+ let optimized = 0;
859
+ traverse(ast, {
860
+ BinaryExpression(path) {
861
+ const { left, right, operator } = path.node;
862
+ if (t.isNumericLiteral(left) && t.isNumericLiteral(right)) {
863
+ let result;
864
+ switch (operator) {
865
+ case '+':
866
+ result = left.value + right.value;
867
+ break;
868
+ case '-':
869
+ result = left.value - right.value;
870
+ break;
871
+ case '*':
872
+ result = left.value * right.value;
873
+ break;
874
+ case '/':
875
+ result = left.value / right.value;
876
+ break;
877
+ case '%':
878
+ result = left.value % right.value;
879
+ break;
880
+ case '**':
881
+ result = Math.pow(left.value, right.value);
882
+ break;
883
+ }
884
+ if (result !== undefined) {
885
+ path.replaceWith(t.numericLiteral(result));
886
+ optimized++;
887
+ }
888
+ }
889
+ },
890
+ LogicalExpression(path) {
891
+ const { left, right, operator } = path.node;
892
+ if (operator === '&&' && t.isBooleanLiteral(left) && left.value === true) {
893
+ path.replaceWith(right);
894
+ optimized++;
895
+ }
896
+ if (operator === '||' && t.isBooleanLiteral(left) && left.value === false) {
897
+ path.replaceWith(right);
898
+ optimized++;
899
+ }
900
+ },
901
+ EmptyStatement(path) {
902
+ path.remove();
903
+ optimized++;
904
+ },
905
+ ConditionalExpression(path) {
906
+ const { test, consequent, alternate } = path.node;
907
+ if (t.isBooleanLiteral(test) && test.value === true) {
908
+ path.replaceWith(consequent);
909
+ optimized++;
910
+ }
911
+ if (t.isBooleanLiteral(test) && test.value === false) {
912
+ path.replaceWith(alternate);
913
+ optimized++;
914
+ }
915
+ },
916
+ });
917
+ if (optimized > 0) {
918
+ logger.info(`Applied ${optimized} AST optimizations`);
919
+ return generate(ast, { comments: true, compact: false }).code;
920
+ }
921
+ return code;
922
+ }
923
+ catch (error) {
924
+ logger.error('Failed to apply AST optimizations:', error);
925
+ return code;
926
+ }
927
+ }
928
+ calculateConfidence(techniques, warnings, code) {
929
+ let confidence = 0.3;
930
+ const techniqueBonus = Math.min(techniques.length * 0.12, 0.5);
931
+ confidence += techniqueBonus;
932
+ const warningPenalty = warnings.length * 0.08;
933
+ confidence -= warningPenalty;
934
+ const highConfidenceTechniques = [
935
+ 'invisible-unicode',
936
+ 'string-array-rotation',
937
+ 'dead-code-injection',
938
+ 'opaque-predicates',
939
+ 'string-encoding',
940
+ 'ast-optimized',
941
+ ];
942
+ const highConfidenceCount = techniques.filter(t => highConfidenceTechniques.some(ht => t.includes(ht))).length;
943
+ confidence += highConfidenceCount * 0.05;
944
+ if (techniques.some(t => t.includes('vm-protection'))) {
945
+ confidence -= 0.15;
946
+ }
947
+ if (techniques.some(t => t.includes('control-flow-flattening'))) {
948
+ confidence -= 0.05;
949
+ }
950
+ const complexity = this.estimateCodeComplexity(code);
951
+ if (complexity < 10) {
952
+ confidence += 0.1;
953
+ }
954
+ else if (complexity > 100) {
955
+ confidence -= 0.1;
956
+ }
957
+ return Math.max(0.1, Math.min(0.95, confidence));
958
+ }
959
+ estimateCodeComplexity(code) {
960
+ try {
961
+ const ast = parser.parse(code, {
962
+ sourceType: 'module',
963
+ plugins: ['jsx', 'typescript'],
964
+ });
965
+ let complexity = 0;
966
+ traverse(ast, {
967
+ FunctionDeclaration() { complexity += 2; },
968
+ FunctionExpression() { complexity += 2; },
969
+ ArrowFunctionExpression() { complexity += 2; },
970
+ IfStatement() { complexity += 1; },
971
+ SwitchStatement() { complexity += 2; },
972
+ ConditionalExpression() { complexity += 1; },
973
+ WhileStatement() { complexity += 2; },
974
+ ForStatement() { complexity += 2; },
975
+ DoWhileStatement() { complexity += 2; },
976
+ TryStatement() { complexity += 3; },
977
+ });
978
+ return complexity;
979
+ }
980
+ catch {
981
+ return 100;
982
+ }
983
+ }
984
+ }
985
+ //# sourceMappingURL=AdvancedDeobfuscator.js.map