@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.
- package/.env.example +38 -0
- package/CLAUDE.md +170 -0
- package/README.md +564 -0
- package/bun.lock +1484 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/analyzer/AISummarizer.d.ts +41 -0
- package/dist/modules/analyzer/AISummarizer.d.ts.map +1 -0
- package/dist/modules/analyzer/AISummarizer.js +186 -0
- package/dist/modules/analyzer/AISummarizer.js.map +1 -0
- package/dist/modules/analyzer/CodeAnalyzer.d.ts +28 -0
- package/dist/modules/analyzer/CodeAnalyzer.d.ts.map +1 -0
- package/dist/modules/analyzer/CodeAnalyzer.js +1287 -0
- package/dist/modules/analyzer/CodeAnalyzer.js.map +1 -0
- package/dist/modules/analyzer/IntelligentAnalyzer.d.ts +114 -0
- package/dist/modules/analyzer/IntelligentAnalyzer.d.ts.map +1 -0
- package/dist/modules/analyzer/IntelligentAnalyzer.js +1176 -0
- package/dist/modules/analyzer/IntelligentAnalyzer.js.map +1 -0
- package/dist/modules/browser/BrowserModeManager.d.ts +31 -0
- package/dist/modules/browser/BrowserModeManager.d.ts.map +1 -0
- package/dist/modules/browser/BrowserModeManager.js +241 -0
- package/dist/modules/browser/BrowserModeManager.js.map +1 -0
- package/dist/modules/captcha/AICaptchaDetector.d.ts +32 -0
- package/dist/modules/captcha/AICaptchaDetector.d.ts.map +1 -0
- package/dist/modules/captcha/AICaptchaDetector.js +387 -0
- package/dist/modules/captcha/AICaptchaDetector.js.map +1 -0
- package/dist/modules/captcha/CaptchaDetector.d.ts +28 -0
- package/dist/modules/captcha/CaptchaDetector.d.ts.map +1 -0
- package/dist/modules/captcha/CaptchaDetector.js +513 -0
- package/dist/modules/captcha/CaptchaDetector.js.map +1 -0
- package/dist/modules/collector/CodeCache.d.ts +37 -0
- package/dist/modules/collector/CodeCache.d.ts.map +1 -0
- package/dist/modules/collector/CodeCache.js +188 -0
- package/dist/modules/collector/CodeCache.js.map +1 -0
- package/dist/modules/collector/CodeCollector.d.ts +107 -0
- package/dist/modules/collector/CodeCollector.d.ts.map +1 -0
- package/dist/modules/collector/CodeCollector.js +796 -0
- package/dist/modules/collector/CodeCollector.js.map +1 -0
- package/dist/modules/collector/CodeCompressor.d.ts +65 -0
- package/dist/modules/collector/CodeCompressor.d.ts.map +1 -0
- package/dist/modules/collector/CodeCompressor.js +245 -0
- package/dist/modules/collector/CodeCompressor.js.map +1 -0
- package/dist/modules/collector/DOMInspector.d.ts +51 -0
- package/dist/modules/collector/DOMInspector.d.ts.map +1 -0
- package/dist/modules/collector/DOMInspector.js +437 -0
- package/dist/modules/collector/DOMInspector.js.map +1 -0
- package/dist/modules/collector/PageController.d.ts +79 -0
- package/dist/modules/collector/PageController.d.ts.map +1 -0
- package/dist/modules/collector/PageController.js +287 -0
- package/dist/modules/collector/PageController.js.map +1 -0
- package/dist/modules/collector/SmartCodeCollector.d.ts +38 -0
- package/dist/modules/collector/SmartCodeCollector.d.ts.map +1 -0
- package/dist/modules/collector/SmartCodeCollector.js +208 -0
- package/dist/modules/collector/SmartCodeCollector.js.map +1 -0
- package/dist/modules/collector/StreamingCollector.d.ts +46 -0
- package/dist/modules/collector/StreamingCollector.d.ts.map +1 -0
- package/dist/modules/collector/StreamingCollector.js +127 -0
- package/dist/modules/collector/StreamingCollector.js.map +1 -0
- package/dist/modules/crypto/CryptoDetector.d.ts +22 -0
- package/dist/modules/crypto/CryptoDetector.d.ts.map +1 -0
- package/dist/modules/crypto/CryptoDetector.js +168 -0
- package/dist/modules/crypto/CryptoDetector.js.map +1 -0
- package/dist/modules/crypto/CryptoDetectorEnhanced.d.ts +31 -0
- package/dist/modules/crypto/CryptoDetectorEnhanced.d.ts.map +1 -0
- package/dist/modules/crypto/CryptoDetectorEnhanced.js +269 -0
- package/dist/modules/crypto/CryptoDetectorEnhanced.js.map +1 -0
- package/dist/modules/crypto/CryptoRules.d.ts +59 -0
- package/dist/modules/crypto/CryptoRules.d.ts.map +1 -0
- package/dist/modules/crypto/CryptoRules.js +234 -0
- package/dist/modules/crypto/CryptoRules.js.map +1 -0
- package/dist/modules/debugger/BlackboxManager.d.ts +14 -0
- package/dist/modules/debugger/BlackboxManager.d.ts.map +1 -0
- package/dist/modules/debugger/BlackboxManager.js +98 -0
- package/dist/modules/debugger/BlackboxManager.js.map +1 -0
- package/dist/modules/debugger/DebuggerManager.d.ts +138 -0
- package/dist/modules/debugger/DebuggerManager.d.ts.map +1 -0
- package/dist/modules/debugger/DebuggerManager.js +777 -0
- package/dist/modules/debugger/DebuggerManager.js.map +1 -0
- package/dist/modules/debugger/EventBreakpointManager.d.ts +30 -0
- package/dist/modules/debugger/EventBreakpointManager.d.ts.map +1 -0
- package/dist/modules/debugger/EventBreakpointManager.js +125 -0
- package/dist/modules/debugger/EventBreakpointManager.js.map +1 -0
- package/dist/modules/debugger/RuntimeInspector.d.ts +54 -0
- package/dist/modules/debugger/RuntimeInspector.d.ts.map +1 -0
- package/dist/modules/debugger/RuntimeInspector.js +277 -0
- package/dist/modules/debugger/RuntimeInspector.js.map +1 -0
- package/dist/modules/debugger/ScriptManager.d.ts +94 -0
- package/dist/modules/debugger/ScriptManager.d.ts.map +1 -0
- package/dist/modules/debugger/ScriptManager.js +433 -0
- package/dist/modules/debugger/ScriptManager.js.map +1 -0
- package/dist/modules/debugger/WatchExpressionManager.d.ts +52 -0
- package/dist/modules/debugger/WatchExpressionManager.d.ts.map +1 -0
- package/dist/modules/debugger/WatchExpressionManager.js +136 -0
- package/dist/modules/debugger/WatchExpressionManager.js.map +1 -0
- package/dist/modules/debugger/XHRBreakpointManager.d.ts +21 -0
- package/dist/modules/debugger/XHRBreakpointManager.d.ts.map +1 -0
- package/dist/modules/debugger/XHRBreakpointManager.js +81 -0
- package/dist/modules/debugger/XHRBreakpointManager.js.map +1 -0
- package/dist/modules/deobfuscator/ASTOptimizer.d.ts +12 -0
- package/dist/modules/deobfuscator/ASTOptimizer.d.ts.map +1 -0
- package/dist/modules/deobfuscator/ASTOptimizer.js +234 -0
- package/dist/modules/deobfuscator/ASTOptimizer.js.map +1 -0
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.d.ts +52 -0
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.js +985 -0
- package/dist/modules/deobfuscator/AdvancedDeobfuscator.js.map +1 -0
- package/dist/modules/deobfuscator/Deobfuscator.d.ts +23 -0
- package/dist/modules/deobfuscator/Deobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/Deobfuscator.js +487 -0
- package/dist/modules/deobfuscator/Deobfuscator.js.map +1 -0
- package/dist/modules/deobfuscator/JSVMPDeobfuscator.d.ts +19 -0
- package/dist/modules/deobfuscator/JSVMPDeobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/JSVMPDeobfuscator.js +594 -0
- package/dist/modules/deobfuscator/JSVMPDeobfuscator.js.map +1 -0
- package/dist/modules/deobfuscator/JScramberDeobfuscator.d.ts +28 -0
- package/dist/modules/deobfuscator/JScramberDeobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/JScramberDeobfuscator.js +239 -0
- package/dist/modules/deobfuscator/JScramberDeobfuscator.js.map +1 -0
- package/dist/modules/deobfuscator/PackerDeobfuscator.d.ts +38 -0
- package/dist/modules/deobfuscator/PackerDeobfuscator.d.ts.map +1 -0
- package/dist/modules/deobfuscator/PackerDeobfuscator.js +191 -0
- package/dist/modules/deobfuscator/PackerDeobfuscator.js.map +1 -0
- package/dist/modules/detector/ObfuscationDetector.d.ts +35 -0
- package/dist/modules/detector/ObfuscationDetector.d.ts.map +1 -0
- package/dist/modules/detector/ObfuscationDetector.js +278 -0
- package/dist/modules/detector/ObfuscationDetector.js.map +1 -0
- package/dist/modules/emulator/AIEnvironmentAnalyzer.d.ts +32 -0
- package/dist/modules/emulator/AIEnvironmentAnalyzer.d.ts.map +1 -0
- package/dist/modules/emulator/AIEnvironmentAnalyzer.js +548 -0
- package/dist/modules/emulator/AIEnvironmentAnalyzer.js.map +1 -0
- package/dist/modules/emulator/BrowserAPIDatabase.d.ts +34 -0
- package/dist/modules/emulator/BrowserAPIDatabase.d.ts.map +1 -0
- package/dist/modules/emulator/BrowserAPIDatabase.js +326 -0
- package/dist/modules/emulator/BrowserAPIDatabase.js.map +1 -0
- package/dist/modules/emulator/BrowserEnvironmentRules.d.ts +47 -0
- package/dist/modules/emulator/BrowserEnvironmentRules.d.ts.map +1 -0
- package/dist/modules/emulator/BrowserEnvironmentRules.js +493 -0
- package/dist/modules/emulator/BrowserEnvironmentRules.js.map +1 -0
- package/dist/modules/emulator/EnvironmentEmulator.d.ts +27 -0
- package/dist/modules/emulator/EnvironmentEmulator.d.ts.map +1 -0
- package/dist/modules/emulator/EnvironmentEmulator.js +1113 -0
- package/dist/modules/emulator/EnvironmentEmulator.js.map +1 -0
- package/dist/modules/emulator/EnvironmentEmulatorEnhanced.d.ts +26 -0
- package/dist/modules/emulator/EnvironmentEmulatorEnhanced.d.ts.map +1 -0
- package/dist/modules/emulator/EnvironmentEmulatorEnhanced.js +493 -0
- package/dist/modules/emulator/EnvironmentEmulatorEnhanced.js.map +1 -0
- package/dist/modules/emulator/templates/chrome-env.d.ts +260 -0
- package/dist/modules/emulator/templates/chrome-env.d.ts.map +1 -0
- package/dist/modules/emulator/templates/chrome-env.js +253 -0
- package/dist/modules/emulator/templates/chrome-env.js.map +1 -0
- package/dist/modules/hook/AIHookGenerator.d.ts +53 -0
- package/dist/modules/hook/AIHookGenerator.d.ts.map +1 -0
- package/dist/modules/hook/AIHookGenerator.js +353 -0
- package/dist/modules/hook/AIHookGenerator.js.map +1 -0
- package/dist/modules/hook/HookManager.d.ts +67 -0
- package/dist/modules/hook/HookManager.d.ts.map +1 -0
- package/dist/modules/hook/HookManager.js +1225 -0
- package/dist/modules/hook/HookManager.js.map +1 -0
- package/dist/modules/monitor/ConsoleMonitor.d.ts +140 -0
- package/dist/modules/monitor/ConsoleMonitor.d.ts.map +1 -0
- package/dist/modules/monitor/ConsoleMonitor.js +834 -0
- package/dist/modules/monitor/ConsoleMonitor.js.map +1 -0
- package/dist/modules/monitor/PerformanceMonitor.d.ts +65 -0
- package/dist/modules/monitor/PerformanceMonitor.d.ts.map +1 -0
- package/dist/modules/monitor/PerformanceMonitor.js +175 -0
- package/dist/modules/monitor/PerformanceMonitor.js.map +1 -0
- package/dist/modules/stealth/StealthScripts2025.d.ts +17 -0
- package/dist/modules/stealth/StealthScripts2025.d.ts.map +1 -0
- package/dist/modules/stealth/StealthScripts2025.js +274 -0
- package/dist/modules/stealth/StealthScripts2025.js.map +1 -0
- package/dist/modules/symbolic/JSVMPSymbolicExecutor.d.ts +69 -0
- package/dist/modules/symbolic/JSVMPSymbolicExecutor.d.ts.map +1 -0
- package/dist/modules/symbolic/JSVMPSymbolicExecutor.js +232 -0
- package/dist/modules/symbolic/JSVMPSymbolicExecutor.js.map +1 -0
- package/dist/modules/symbolic/SymbolicExecutor.d.ts +69 -0
- package/dist/modules/symbolic/SymbolicExecutor.d.ts.map +1 -0
- package/dist/modules/symbolic/SymbolicExecutor.js +346 -0
- package/dist/modules/symbolic/SymbolicExecutor.js.map +1 -0
- package/dist/server/AIHookToolDefinitions.d.ts +3 -0
- package/dist/server/AIHookToolDefinitions.d.ts.map +1 -0
- package/dist/server/AIHookToolDefinitions.js +284 -0
- package/dist/server/AIHookToolDefinitions.js.map +1 -0
- package/dist/server/AIHookToolHandlers.d.ts +50 -0
- package/dist/server/AIHookToolHandlers.d.ts.map +1 -0
- package/dist/server/AIHookToolHandlers.js +311 -0
- package/dist/server/AIHookToolHandlers.js.map +1 -0
- package/dist/server/AdvancedToolDefinitions.d.ts +3 -0
- package/dist/server/AdvancedToolDefinitions.d.ts.map +1 -0
- package/dist/server/AdvancedToolDefinitions.js +218 -0
- package/dist/server/AdvancedToolDefinitions.js.map +1 -0
- package/dist/server/AdvancedToolHandlers.d.ts +85 -0
- package/dist/server/AdvancedToolHandlers.d.ts.map +1 -0
- package/dist/server/AdvancedToolHandlers.js +431 -0
- package/dist/server/AdvancedToolHandlers.js.map +1 -0
- package/dist/server/BrowserToolDefinitions.d.ts +3 -0
- package/dist/server/BrowserToolDefinitions.d.ts.map +1 -0
- package/dist/server/BrowserToolDefinitions.js +841 -0
- package/dist/server/BrowserToolDefinitions.js.map +1 -0
- package/dist/server/BrowserToolHandlers.d.ts +290 -0
- package/dist/server/BrowserToolHandlers.d.ts.map +1 -0
- package/dist/server/BrowserToolHandlers.js +784 -0
- package/dist/server/BrowserToolHandlers.js.map +1 -0
- package/dist/server/CacheToolDefinitions.d.ts +3 -0
- package/dist/server/CacheToolDefinitions.d.ts.map +1 -0
- package/dist/server/CacheToolDefinitions.js +166 -0
- package/dist/server/CacheToolDefinitions.js.map +1 -0
- package/dist/server/DebuggerToolDefinitions.d.ts +3 -0
- package/dist/server/DebuggerToolDefinitions.d.ts.map +1 -0
- package/dist/server/DebuggerToolDefinitions.js +600 -0
- package/dist/server/DebuggerToolDefinitions.js.map +1 -0
- package/dist/server/DebuggerToolHandlers.d.ts +230 -0
- package/dist/server/DebuggerToolHandlers.d.ts.map +1 -0
- package/dist/server/DebuggerToolHandlers.js +935 -0
- package/dist/server/DebuggerToolHandlers.js.map +1 -0
- package/dist/server/MCPServer.d.ts +55 -0
- package/dist/server/MCPServer.d.ts.map +1 -0
- package/dist/server/MCPServer.js +1344 -0
- package/dist/server/MCPServer.js.map +1 -0
- package/dist/server/TokenBudgetToolDefinitions.d.ts +3 -0
- package/dist/server/TokenBudgetToolDefinitions.d.ts.map +1 -0
- package/dist/server/TokenBudgetToolDefinitions.js +114 -0
- package/dist/server/TokenBudgetToolDefinitions.js.map +1 -0
- package/dist/services/LLMService.d.ts +41 -0
- package/dist/services/LLMService.d.ts.map +1 -0
- package/dist/services/LLMService.js +792 -0
- package/dist/services/LLMService.js.map +1 -0
- package/dist/types/index.d.ts +527 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/AdaptiveDataSerializer.d.ts +27 -0
- package/dist/utils/AdaptiveDataSerializer.d.ts.map +1 -0
- package/dist/utils/AdaptiveDataSerializer.js +215 -0
- package/dist/utils/AdaptiveDataSerializer.js.map +1 -0
- package/dist/utils/CacheAdapters.d.ts +30 -0
- package/dist/utils/CacheAdapters.d.ts.map +1 -0
- package/dist/utils/CacheAdapters.js +83 -0
- package/dist/utils/CacheAdapters.js.map +1 -0
- package/dist/utils/TokenBudgetManager.d.ts +52 -0
- package/dist/utils/TokenBudgetManager.d.ts.map +1 -0
- package/dist/utils/TokenBudgetManager.js +190 -0
- package/dist/utils/TokenBudgetManager.js.map +1 -0
- package/dist/utils/UnifiedCacheManager.d.ts +55 -0
- package/dist/utils/UnifiedCacheManager.d.ts.map +1 -0
- package/dist/utils/UnifiedCacheManager.js +207 -0
- package/dist/utils/UnifiedCacheManager.js.map +1 -0
- package/dist/utils/cache.d.ts +13 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +92 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/config.d.ts +7 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +93 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/detailedDataManager.d.ts +60 -0
- package/dist/utils/detailedDataManager.d.ts.map +1 -0
- package/dist/utils/detailedDataManager.js +204 -0
- package/dist/utils/detailedDataManager.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/parallel.d.ts +40 -0
- package/dist/utils/parallel.d.ts.map +1 -0
- package/dist/utils/parallel.js +148 -0
- package/dist/utils/parallel.js.map +1 -0
- package/package.json +94 -0
- package/server.json +39 -0
- package/tsconfig.dev.json +14 -0
|
@@ -0,0 +1,1176 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
export class IntelligentAnalyzer {
|
|
3
|
+
llmService;
|
|
4
|
+
constructor(llmService) {
|
|
5
|
+
this.llmService = llmService;
|
|
6
|
+
if (llmService) {
|
|
7
|
+
logger.info('IntelligentAnalyzer initialized with LLM support');
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
logger.warn('IntelligentAnalyzer initialized without LLM (using rule-based analysis only)');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
static BLACKLIST_DOMAINS = [
|
|
14
|
+
'google-analytics.com',
|
|
15
|
+
'googletagmanager.com',
|
|
16
|
+
'facebook.com/tr',
|
|
17
|
+
'doubleclick.net',
|
|
18
|
+
'googlesyndication.com',
|
|
19
|
+
'clarity.ms',
|
|
20
|
+
'hotjar.com',
|
|
21
|
+
'segment.com',
|
|
22
|
+
'mixpanel.com',
|
|
23
|
+
'amplitude.com',
|
|
24
|
+
'sentry.io',
|
|
25
|
+
'bugsnag.com',
|
|
26
|
+
'cdn.jsdelivr.net',
|
|
27
|
+
'unpkg.com',
|
|
28
|
+
'cdnjs.cloudflare.com',
|
|
29
|
+
];
|
|
30
|
+
static WHITELIST_KEYWORDS = [
|
|
31
|
+
'login',
|
|
32
|
+
'auth',
|
|
33
|
+
'token',
|
|
34
|
+
'sign',
|
|
35
|
+
'encrypt',
|
|
36
|
+
'decrypt',
|
|
37
|
+
'verify',
|
|
38
|
+
'validate',
|
|
39
|
+
'captcha',
|
|
40
|
+
'api',
|
|
41
|
+
'data',
|
|
42
|
+
'user',
|
|
43
|
+
'password',
|
|
44
|
+
'secret',
|
|
45
|
+
'key',
|
|
46
|
+
'hash',
|
|
47
|
+
'crypto',
|
|
48
|
+
];
|
|
49
|
+
static FRAMEWORK_LOG_KEYWORDS = [
|
|
50
|
+
'[HMR]',
|
|
51
|
+
'[WDS]',
|
|
52
|
+
'[webpack]',
|
|
53
|
+
'Download the React DevTools',
|
|
54
|
+
'React DevTools',
|
|
55
|
+
'Vue DevTools',
|
|
56
|
+
'Angular DevTools',
|
|
57
|
+
'%c',
|
|
58
|
+
'color:',
|
|
59
|
+
'font-size:',
|
|
60
|
+
];
|
|
61
|
+
analyze(data) {
|
|
62
|
+
logger.info('Starting intelligent analysis...', {
|
|
63
|
+
requests: data.requests.length,
|
|
64
|
+
responses: data.responses.length,
|
|
65
|
+
logs: data.logs.length,
|
|
66
|
+
exceptions: data.exceptions.length,
|
|
67
|
+
});
|
|
68
|
+
const criticalRequests = this.filterCriticalRequests(data.requests);
|
|
69
|
+
const criticalResponses = this.filterCriticalResponses(data.responses);
|
|
70
|
+
const criticalLogs = this.filterCriticalLogs(data.logs);
|
|
71
|
+
const patterns = {
|
|
72
|
+
encryption: this.detectEncryptionPatterns(data.requests, data.logs),
|
|
73
|
+
signature: this.detectSignaturePatterns(data.requests, data.logs),
|
|
74
|
+
token: this.detectTokenPatterns(data.requests, data.logs),
|
|
75
|
+
antiDebug: this.detectAntiDebugPatterns(data.logs),
|
|
76
|
+
};
|
|
77
|
+
const suspiciousAPIs = this.extractSuspiciousAPIs(criticalRequests);
|
|
78
|
+
const keyFunctions = this.extractKeyFunctions(criticalLogs);
|
|
79
|
+
const result = {
|
|
80
|
+
criticalRequests,
|
|
81
|
+
criticalResponses,
|
|
82
|
+
criticalLogs,
|
|
83
|
+
exceptions: data.exceptions,
|
|
84
|
+
patterns,
|
|
85
|
+
summary: {
|
|
86
|
+
totalRequests: data.requests.length,
|
|
87
|
+
filteredRequests: criticalRequests.length,
|
|
88
|
+
totalLogs: data.logs.length,
|
|
89
|
+
filteredLogs: criticalLogs.length,
|
|
90
|
+
suspiciousAPIs,
|
|
91
|
+
keyFunctions,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
logger.success('Analysis completed', {
|
|
95
|
+
criticalRequests: criticalRequests.length,
|
|
96
|
+
criticalLogs: criticalLogs.length,
|
|
97
|
+
patterns: Object.keys(patterns).length,
|
|
98
|
+
});
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
filterCriticalRequests(requests) {
|
|
102
|
+
return requests
|
|
103
|
+
.filter(req => {
|
|
104
|
+
const isBlacklisted = IntelligentAnalyzer.BLACKLIST_DOMAINS.some(domain => req.url.includes(domain));
|
|
105
|
+
if (isBlacklisted)
|
|
106
|
+
return false;
|
|
107
|
+
const isStaticResource = /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|css|ico)$/i.test(req.url);
|
|
108
|
+
if (isStaticResource)
|
|
109
|
+
return false;
|
|
110
|
+
const hasKeyword = IntelligentAnalyzer.WHITELIST_KEYWORDS.some(keyword => req.url.toLowerCase().includes(keyword));
|
|
111
|
+
if (hasKeyword)
|
|
112
|
+
return true;
|
|
113
|
+
if (req.method === 'POST' || req.method === 'PUT')
|
|
114
|
+
return true;
|
|
115
|
+
if (req.method === 'GET' && req.url.includes('?'))
|
|
116
|
+
return true;
|
|
117
|
+
return false;
|
|
118
|
+
})
|
|
119
|
+
.sort((a, b) => {
|
|
120
|
+
const scoreA = this.calculateRequestPriority(a);
|
|
121
|
+
const scoreB = this.calculateRequestPriority(b);
|
|
122
|
+
return scoreB - scoreA;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
calculateRequestPriority(req) {
|
|
126
|
+
let score = 0;
|
|
127
|
+
if (req.method === 'POST' || req.method === 'PUT')
|
|
128
|
+
score += 10;
|
|
129
|
+
const keywordCount = IntelligentAnalyzer.WHITELIST_KEYWORDS.filter(keyword => req.url.toLowerCase().includes(keyword)).length;
|
|
130
|
+
score += keywordCount * 5;
|
|
131
|
+
if (req.postData)
|
|
132
|
+
score += 5;
|
|
133
|
+
score += Math.floor(req.url.length / 100);
|
|
134
|
+
return score;
|
|
135
|
+
}
|
|
136
|
+
filterCriticalResponses(responses) {
|
|
137
|
+
return responses
|
|
138
|
+
.filter(res => {
|
|
139
|
+
const isBlacklisted = IntelligentAnalyzer.BLACKLIST_DOMAINS.some(domain => res.url.includes(domain));
|
|
140
|
+
if (isBlacklisted)
|
|
141
|
+
return false;
|
|
142
|
+
if (res.mimeType.includes('json'))
|
|
143
|
+
return true;
|
|
144
|
+
if (res.mimeType.includes('javascript'))
|
|
145
|
+
return true;
|
|
146
|
+
const hasKeyword = IntelligentAnalyzer.WHITELIST_KEYWORDS.some(keyword => res.url.toLowerCase().includes(keyword));
|
|
147
|
+
if (hasKeyword)
|
|
148
|
+
return true;
|
|
149
|
+
return false;
|
|
150
|
+
})
|
|
151
|
+
.sort((a, b) => b.timestamp - a.timestamp);
|
|
152
|
+
}
|
|
153
|
+
filterCriticalLogs(logs) {
|
|
154
|
+
return logs
|
|
155
|
+
.filter(log => {
|
|
156
|
+
const isFrameworkLog = IntelligentAnalyzer.FRAMEWORK_LOG_KEYWORDS.some(keyword => log.text.includes(keyword));
|
|
157
|
+
if (isFrameworkLog)
|
|
158
|
+
return false;
|
|
159
|
+
if (!log.text || log.text.trim().length === 0)
|
|
160
|
+
return false;
|
|
161
|
+
if (log.type === 'error' || log.type === 'warn')
|
|
162
|
+
return true;
|
|
163
|
+
const hasKeyword = IntelligentAnalyzer.WHITELIST_KEYWORDS.some(keyword => log.text.toLowerCase().includes(keyword));
|
|
164
|
+
if (hasKeyword)
|
|
165
|
+
return true;
|
|
166
|
+
return false;
|
|
167
|
+
})
|
|
168
|
+
.sort((a, b) => {
|
|
169
|
+
const scoreA = this.calculateLogPriority(a);
|
|
170
|
+
const scoreB = this.calculateLogPriority(b);
|
|
171
|
+
return scoreB - scoreA;
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
calculateLogPriority(log) {
|
|
175
|
+
let score = 0;
|
|
176
|
+
if (log.type === 'error')
|
|
177
|
+
score += 20;
|
|
178
|
+
if (log.type === 'warn')
|
|
179
|
+
score += 10;
|
|
180
|
+
const keywordCount = IntelligentAnalyzer.WHITELIST_KEYWORDS.filter(keyword => log.text.toLowerCase().includes(keyword)).length;
|
|
181
|
+
score += keywordCount * 5;
|
|
182
|
+
return score;
|
|
183
|
+
}
|
|
184
|
+
detectEncryptionPatterns(requests, logs) {
|
|
185
|
+
const patterns = [];
|
|
186
|
+
const cryptoKeywords = {
|
|
187
|
+
AES: ['aes', 'cipher', 'encrypt', 'decrypt', 'CryptoJS.AES'],
|
|
188
|
+
RSA: ['rsa', 'publickey', 'privatekey', 'RSA.encrypt'],
|
|
189
|
+
MD5: ['md5', 'MD5', 'CryptoJS.MD5'],
|
|
190
|
+
SHA: ['sha', 'sha1', 'sha256', 'sha512', 'CryptoJS.SHA'],
|
|
191
|
+
Base64: ['base64', 'btoa', 'atob', 'Base64.encode'],
|
|
192
|
+
};
|
|
193
|
+
for (const req of requests) {
|
|
194
|
+
for (const [type, keywords] of Object.entries(cryptoKeywords)) {
|
|
195
|
+
for (const keyword of keywords) {
|
|
196
|
+
if (req.url.toLowerCase().includes(keyword.toLowerCase())) {
|
|
197
|
+
patterns.push({
|
|
198
|
+
type: type,
|
|
199
|
+
location: req.url,
|
|
200
|
+
confidence: 0.7,
|
|
201
|
+
evidence: [keyword, 'Found in URL'],
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (req.postData) {
|
|
207
|
+
const postData = req.postData.toLowerCase();
|
|
208
|
+
for (const [type, keywords] of Object.entries(cryptoKeywords)) {
|
|
209
|
+
for (const keyword of keywords) {
|
|
210
|
+
if (postData.includes(keyword.toLowerCase())) {
|
|
211
|
+
patterns.push({
|
|
212
|
+
type: type,
|
|
213
|
+
location: req.url,
|
|
214
|
+
confidence: 0.8,
|
|
215
|
+
evidence: [keyword, 'Found in POST data'],
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
for (const log of logs) {
|
|
223
|
+
const text = log.text.toLowerCase();
|
|
224
|
+
for (const [type, keywords] of Object.entries(cryptoKeywords)) {
|
|
225
|
+
for (const keyword of keywords) {
|
|
226
|
+
if (text.includes(keyword.toLowerCase())) {
|
|
227
|
+
patterns.push({
|
|
228
|
+
type: type,
|
|
229
|
+
location: log.url || 'console',
|
|
230
|
+
confidence: 0.9,
|
|
231
|
+
evidence: [keyword, 'Found in console log', log.text.substring(0, 100)],
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return this.deduplicatePatterns(patterns);
|
|
238
|
+
}
|
|
239
|
+
detectSignaturePatterns(requests, _logs) {
|
|
240
|
+
const patterns = [];
|
|
241
|
+
const signatureKeywords = [
|
|
242
|
+
'sign',
|
|
243
|
+
'signature',
|
|
244
|
+
'sig',
|
|
245
|
+
'hmac',
|
|
246
|
+
'hash',
|
|
247
|
+
'digest',
|
|
248
|
+
'checksum',
|
|
249
|
+
'verify',
|
|
250
|
+
'validation',
|
|
251
|
+
];
|
|
252
|
+
for (const req of requests) {
|
|
253
|
+
if (req.url.includes('?')) {
|
|
254
|
+
try {
|
|
255
|
+
const url = new URL(req.url);
|
|
256
|
+
const params = url.searchParams;
|
|
257
|
+
const paramNames = Array.from(params.keys());
|
|
258
|
+
for (const keyword of signatureKeywords) {
|
|
259
|
+
const matchedParams = paramNames.filter(p => p.toLowerCase().includes(keyword));
|
|
260
|
+
if (matchedParams.length > 0) {
|
|
261
|
+
let signType = 'Custom';
|
|
262
|
+
if (keyword.includes('hmac'))
|
|
263
|
+
signType = 'HMAC';
|
|
264
|
+
else if (keyword.includes('jwt'))
|
|
265
|
+
signType = 'JWT';
|
|
266
|
+
const otherParams = paramNames.filter(p => !matchedParams.includes(p) &&
|
|
267
|
+
!p.toLowerCase().includes('callback') &&
|
|
268
|
+
!p.toLowerCase().includes('_'));
|
|
269
|
+
patterns.push({
|
|
270
|
+
type: signType,
|
|
271
|
+
location: `${req.url} (URL params)`,
|
|
272
|
+
parameters: otherParams,
|
|
273
|
+
confidence: 0.82,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (e) {
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (req.headers) {
|
|
282
|
+
for (const [headerName, headerValue] of Object.entries(req.headers)) {
|
|
283
|
+
const headerNameLower = headerName.toLowerCase();
|
|
284
|
+
const isSignatureHeader = signatureKeywords.some(keyword => headerNameLower.includes(keyword));
|
|
285
|
+
if (isSignatureHeader && headerValue) {
|
|
286
|
+
let signType = 'Custom';
|
|
287
|
+
let confidence = 0.75;
|
|
288
|
+
if (/^[a-f0-9]{64,}$/i.test(headerValue)) {
|
|
289
|
+
signType = 'HMAC';
|
|
290
|
+
confidence = 0.88;
|
|
291
|
+
}
|
|
292
|
+
else if (/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$/.test(headerValue)) {
|
|
293
|
+
signType = 'JWT';
|
|
294
|
+
confidence = 0.92;
|
|
295
|
+
}
|
|
296
|
+
const otherHeaders = Object.keys(req.headers).filter(h => h.toLowerCase() !== headerNameLower &&
|
|
297
|
+
!h.toLowerCase().includes('content-type') &&
|
|
298
|
+
!h.toLowerCase().includes('user-agent'));
|
|
299
|
+
patterns.push({
|
|
300
|
+
type: signType,
|
|
301
|
+
location: `${req.url} (header: ${headerName})`,
|
|
302
|
+
parameters: otherHeaders,
|
|
303
|
+
confidence,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (req.postData && req.postData.length > 0) {
|
|
309
|
+
try {
|
|
310
|
+
const bodyData = JSON.parse(req.postData);
|
|
311
|
+
for (const [key, value] of Object.entries(bodyData)) {
|
|
312
|
+
const keyLower = key.toLowerCase();
|
|
313
|
+
const isSignatureField = signatureKeywords.some(keyword => keyLower.includes(keyword));
|
|
314
|
+
if (isSignatureField && typeof value === 'string') {
|
|
315
|
+
let signType = 'Custom';
|
|
316
|
+
let confidence = 0.7;
|
|
317
|
+
if (/^[a-f0-9]{64,}$/i.test(value)) {
|
|
318
|
+
signType = 'HMAC';
|
|
319
|
+
confidence = 0.85;
|
|
320
|
+
}
|
|
321
|
+
else if (/^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+$/.test(value)) {
|
|
322
|
+
signType = 'JWT';
|
|
323
|
+
confidence = 0.9;
|
|
324
|
+
}
|
|
325
|
+
const otherFields = Object.keys(bodyData).filter(k => k !== key);
|
|
326
|
+
patterns.push({
|
|
327
|
+
type: signType,
|
|
328
|
+
location: `${req.url} (POST body: ${key})`,
|
|
329
|
+
parameters: otherFields,
|
|
330
|
+
confidence,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
catch (e) {
|
|
336
|
+
for (const keyword of signatureKeywords) {
|
|
337
|
+
if (req.postData.includes(`${keyword}=`)) {
|
|
338
|
+
patterns.push({
|
|
339
|
+
type: 'Custom',
|
|
340
|
+
location: `${req.url} (POST body)`,
|
|
341
|
+
parameters: ['form-urlencoded data'],
|
|
342
|
+
confidence: 0.65,
|
|
343
|
+
});
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return patterns;
|
|
351
|
+
}
|
|
352
|
+
detectTokenPatterns(requests, _logs) {
|
|
353
|
+
const patterns = [];
|
|
354
|
+
const jwtRegex = /[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+/g;
|
|
355
|
+
const tokenHeaderKeywords = [
|
|
356
|
+
'authorization',
|
|
357
|
+
'token',
|
|
358
|
+
'auth',
|
|
359
|
+
'access',
|
|
360
|
+
'bearer',
|
|
361
|
+
'session',
|
|
362
|
+
'credential',
|
|
363
|
+
'api-key',
|
|
364
|
+
'apikey',
|
|
365
|
+
'x-token',
|
|
366
|
+
'x-auth',
|
|
367
|
+
'x-access',
|
|
368
|
+
'x-api-key',
|
|
369
|
+
'x-session',
|
|
370
|
+
];
|
|
371
|
+
for (const req of requests) {
|
|
372
|
+
if (req.headers) {
|
|
373
|
+
for (const [headerName, headerValue] of Object.entries(req.headers)) {
|
|
374
|
+
const headerNameLower = headerName.toLowerCase();
|
|
375
|
+
const isTokenHeader = tokenHeaderKeywords.some(keyword => headerNameLower.includes(keyword));
|
|
376
|
+
if (isTokenHeader && headerValue) {
|
|
377
|
+
const jwtMatch = headerValue.match(jwtRegex);
|
|
378
|
+
if (jwtMatch) {
|
|
379
|
+
patterns.push({
|
|
380
|
+
type: 'JWT',
|
|
381
|
+
location: `${req.url} (header: ${headerName})`,
|
|
382
|
+
format: `JWT in ${headerName} header`,
|
|
383
|
+
confidence: 0.95,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
else if (headerValue.toLowerCase().startsWith('bearer ')) {
|
|
387
|
+
patterns.push({
|
|
388
|
+
type: 'Custom',
|
|
389
|
+
location: `${req.url} (header: ${headerName})`,
|
|
390
|
+
format: `Bearer token in ${headerName} header`,
|
|
391
|
+
confidence: 0.9,
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
else if (headerValue.length > 20 && /^[A-Za-z0-9_\-+=\/]+$/.test(headerValue)) {
|
|
395
|
+
patterns.push({
|
|
396
|
+
type: 'Custom',
|
|
397
|
+
location: `${req.url} (header: ${headerName})`,
|
|
398
|
+
format: `Custom token in ${headerName} header (length: ${headerValue.length})`,
|
|
399
|
+
confidence: 0.75,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (req.url.includes('?')) {
|
|
406
|
+
try {
|
|
407
|
+
const url = new URL(req.url);
|
|
408
|
+
const params = url.searchParams;
|
|
409
|
+
const tokenParamKeywords = [
|
|
410
|
+
'token',
|
|
411
|
+
'access_token',
|
|
412
|
+
'accesstoken',
|
|
413
|
+
'auth',
|
|
414
|
+
'authorization',
|
|
415
|
+
'session',
|
|
416
|
+
'sessionid',
|
|
417
|
+
'api_key',
|
|
418
|
+
'apikey',
|
|
419
|
+
'key',
|
|
420
|
+
'credential',
|
|
421
|
+
];
|
|
422
|
+
for (const [paramName, paramValue] of params.entries()) {
|
|
423
|
+
const paramNameLower = paramName.toLowerCase();
|
|
424
|
+
const isTokenParam = tokenParamKeywords.some(keyword => paramNameLower.includes(keyword));
|
|
425
|
+
if (isTokenParam && paramValue) {
|
|
426
|
+
const jwtMatch = paramValue.match(jwtRegex);
|
|
427
|
+
if (jwtMatch) {
|
|
428
|
+
patterns.push({
|
|
429
|
+
type: 'JWT',
|
|
430
|
+
location: `${req.url} (param: ${paramName})`,
|
|
431
|
+
format: `JWT in URL parameter '${paramName}'`,
|
|
432
|
+
confidence: 0.92,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
else if (paramName.toLowerCase().includes('access_token')) {
|
|
436
|
+
patterns.push({
|
|
437
|
+
type: 'OAuth',
|
|
438
|
+
location: `${req.url} (param: ${paramName})`,
|
|
439
|
+
format: `OAuth token in URL parameter '${paramName}'`,
|
|
440
|
+
confidence: 0.88,
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
else if (paramValue.length > 20) {
|
|
444
|
+
patterns.push({
|
|
445
|
+
type: 'Custom',
|
|
446
|
+
location: `${req.url} (param: ${paramName})`,
|
|
447
|
+
format: `Custom token in URL parameter '${paramName}' (length: ${paramValue.length})`,
|
|
448
|
+
confidence: 0.7,
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
catch (e) {
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (req.postData && req.postData.length > 0) {
|
|
458
|
+
try {
|
|
459
|
+
const bodyData = JSON.parse(req.postData);
|
|
460
|
+
const tokenParamKeywords = ['token', 'access_token', 'auth', 'authorization', 'session', 'api_key'];
|
|
461
|
+
for (const [key, value] of Object.entries(bodyData)) {
|
|
462
|
+
const keyLower = key.toLowerCase();
|
|
463
|
+
const isTokenField = tokenParamKeywords.some(keyword => keyLower.includes(keyword));
|
|
464
|
+
if (isTokenField && typeof value === 'string' && value.length > 20) {
|
|
465
|
+
const jwtMatch = value.match(jwtRegex);
|
|
466
|
+
if (jwtMatch) {
|
|
467
|
+
patterns.push({
|
|
468
|
+
type: 'JWT',
|
|
469
|
+
location: `${req.url} (POST body: ${key})`,
|
|
470
|
+
format: `JWT in POST body field '${key}'`,
|
|
471
|
+
confidence: 0.93,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
patterns.push({
|
|
476
|
+
type: 'Custom',
|
|
477
|
+
location: `${req.url} (POST body: ${key})`,
|
|
478
|
+
format: `Custom token in POST body field '${key}' (length: ${value.length})`,
|
|
479
|
+
confidence: 0.72,
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
catch (e) {
|
|
486
|
+
const tokenParamKeywords = ['token', 'access_token', 'auth', 'session', 'api_key'];
|
|
487
|
+
for (const keyword of tokenParamKeywords) {
|
|
488
|
+
if (req.postData.includes(`${keyword}=`)) {
|
|
489
|
+
patterns.push({
|
|
490
|
+
type: 'Custom',
|
|
491
|
+
location: `${req.url} (POST body)`,
|
|
492
|
+
format: `Token in POST body (form-urlencoded, field: ${keyword})`,
|
|
493
|
+
confidence: 0.68,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return patterns;
|
|
501
|
+
}
|
|
502
|
+
detectAntiDebugPatterns(logs) {
|
|
503
|
+
const patterns = [];
|
|
504
|
+
for (const log of logs) {
|
|
505
|
+
const text = log.text;
|
|
506
|
+
if (text.includes('debugger')) {
|
|
507
|
+
patterns.push({
|
|
508
|
+
type: 'debugger',
|
|
509
|
+
location: log.url || 'unknown',
|
|
510
|
+
code: text.substring(0, 200),
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
if (text.includes('console.log') && text.includes('=')) {
|
|
514
|
+
patterns.push({
|
|
515
|
+
type: 'console.log',
|
|
516
|
+
location: log.url || 'unknown',
|
|
517
|
+
code: text.substring(0, 200),
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
if (text.includes('devtools') || text.includes('firebug')) {
|
|
521
|
+
patterns.push({
|
|
522
|
+
type: 'devtools-detect',
|
|
523
|
+
location: log.url || 'unknown',
|
|
524
|
+
code: text.substring(0, 200),
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
if (text.includes('performance.now') || text.includes('Date.now')) {
|
|
528
|
+
patterns.push({
|
|
529
|
+
type: 'timing-check',
|
|
530
|
+
location: log.url || 'unknown',
|
|
531
|
+
code: text.substring(0, 200),
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return patterns;
|
|
536
|
+
}
|
|
537
|
+
extractSuspiciousAPIs(requests) {
|
|
538
|
+
const apis = new Set();
|
|
539
|
+
for (const req of requests) {
|
|
540
|
+
try {
|
|
541
|
+
const url = new URL(req.url);
|
|
542
|
+
const path = url.pathname;
|
|
543
|
+
if (path.includes('/api/') || path.includes('/v1/') || path.includes('/v2/')) {
|
|
544
|
+
apis.add(`${req.method} ${path}`);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
catch (e) {
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return Array.from(apis).slice(0, 20);
|
|
551
|
+
}
|
|
552
|
+
extractKeyFunctions(logs) {
|
|
553
|
+
const functions = new Set();
|
|
554
|
+
const functionRegex = /([a-zA-Z_$][a-zA-Z0-9_$]*)\s*\(/g;
|
|
555
|
+
for (const log of logs) {
|
|
556
|
+
const matches = log.text.matchAll(functionRegex);
|
|
557
|
+
for (const match of matches) {
|
|
558
|
+
const funcName = match[1];
|
|
559
|
+
if (funcName && !['console', 'log', 'warn', 'error', 'info', 'debug'].includes(funcName)) {
|
|
560
|
+
functions.add(funcName);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return Array.from(functions).slice(0, 30);
|
|
565
|
+
}
|
|
566
|
+
deduplicatePatterns(patterns) {
|
|
567
|
+
const seen = new Set();
|
|
568
|
+
const result = [];
|
|
569
|
+
for (const pattern of patterns) {
|
|
570
|
+
const key = `${pattern.type}-${pattern.location}`;
|
|
571
|
+
if (!seen.has(key)) {
|
|
572
|
+
seen.add(key);
|
|
573
|
+
result.push(pattern);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return result;
|
|
577
|
+
}
|
|
578
|
+
aggregateSimilarRequests(requests) {
|
|
579
|
+
const groups = new Map();
|
|
580
|
+
for (const req of requests) {
|
|
581
|
+
try {
|
|
582
|
+
const url = new URL(req.url);
|
|
583
|
+
const baseUrl = `${url.origin}${url.pathname}`;
|
|
584
|
+
if (!groups.has(baseUrl)) {
|
|
585
|
+
groups.set(baseUrl, []);
|
|
586
|
+
}
|
|
587
|
+
groups.get(baseUrl).push(req);
|
|
588
|
+
}
|
|
589
|
+
catch (e) {
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return groups;
|
|
593
|
+
}
|
|
594
|
+
generateAIFriendlySummary(result) {
|
|
595
|
+
const lines = [];
|
|
596
|
+
lines.push('=== 智能分析摘要 ===\n');
|
|
597
|
+
lines.push(`📊 数据统计:`);
|
|
598
|
+
lines.push(` - 总请求数: ${result.summary.totalRequests} → 关键请求: ${result.summary.filteredRequests}`);
|
|
599
|
+
lines.push(` - 总日志数: ${result.summary.totalLogs} → 关键日志: ${result.summary.filteredLogs}`);
|
|
600
|
+
lines.push(` - 异常数: ${result.exceptions.length}\n`);
|
|
601
|
+
if (result.summary.suspiciousAPIs.length > 0) {
|
|
602
|
+
lines.push(`🔍 可疑API (${result.summary.suspiciousAPIs.length}):`);
|
|
603
|
+
result.summary.suspiciousAPIs.slice(0, 10).forEach(api => {
|
|
604
|
+
lines.push(` - ${api}`);
|
|
605
|
+
});
|
|
606
|
+
lines.push('');
|
|
607
|
+
}
|
|
608
|
+
if (result.patterns.encryption && result.patterns.encryption.length > 0) {
|
|
609
|
+
lines.push(`🔐 检测到加密算法 (${result.patterns.encryption.length}):`);
|
|
610
|
+
result.patterns.encryption.slice(0, 5).forEach(pattern => {
|
|
611
|
+
lines.push(` - ${pattern.type} (置信度: ${(pattern.confidence * 100).toFixed(0)}%)`);
|
|
612
|
+
lines.push(` 位置: ${pattern.location}`);
|
|
613
|
+
lines.push(` 证据: ${pattern.evidence.join(', ')}`);
|
|
614
|
+
});
|
|
615
|
+
lines.push('');
|
|
616
|
+
}
|
|
617
|
+
if (result.patterns.signature && result.patterns.signature.length > 0) {
|
|
618
|
+
lines.push(`✍️ 检测到签名算法 (${result.patterns.signature.length}):`);
|
|
619
|
+
result.patterns.signature.slice(0, 5).forEach(pattern => {
|
|
620
|
+
lines.push(` - ${pattern.type}`);
|
|
621
|
+
lines.push(` 参数: ${pattern.parameters.join(', ')}`);
|
|
622
|
+
});
|
|
623
|
+
lines.push('');
|
|
624
|
+
}
|
|
625
|
+
if (result.patterns.antiDebug && result.patterns.antiDebug.length > 0) {
|
|
626
|
+
lines.push(`⚠️ 检测到反调试技术 (${result.patterns.antiDebug.length}):`);
|
|
627
|
+
result.patterns.antiDebug.slice(0, 3).forEach(pattern => {
|
|
628
|
+
lines.push(` - ${pattern.type}`);
|
|
629
|
+
});
|
|
630
|
+
lines.push('');
|
|
631
|
+
}
|
|
632
|
+
if (result.summary.keyFunctions.length > 0) {
|
|
633
|
+
lines.push(`🎯 关键函数 (${result.summary.keyFunctions.length}):`);
|
|
634
|
+
lines.push(` ${result.summary.keyFunctions.slice(0, 15).join(', ')}`);
|
|
635
|
+
lines.push('');
|
|
636
|
+
}
|
|
637
|
+
lines.push('=== 分析完成 ===');
|
|
638
|
+
return lines.join('\n');
|
|
639
|
+
}
|
|
640
|
+
async analyzeCriticalRequestsWithLLM(requests) {
|
|
641
|
+
if (!this.llmService) {
|
|
642
|
+
logger.warn('LLM service not available, skipping LLM analysis');
|
|
643
|
+
return { encryption: [], signature: [], token: [], customPatterns: [] };
|
|
644
|
+
}
|
|
645
|
+
logger.info('Starting LLM-enhanced request analysis...');
|
|
646
|
+
const requestSummary = requests.slice(0, 20).map(req => {
|
|
647
|
+
const urlObj = new URL(req.url, 'http://dummy.com');
|
|
648
|
+
const params = Object.fromEntries(urlObj.searchParams.entries());
|
|
649
|
+
return {
|
|
650
|
+
url: req.url,
|
|
651
|
+
method: req.method,
|
|
652
|
+
urlParams: params,
|
|
653
|
+
headers: req.headers,
|
|
654
|
+
postData: req.postData?.substring(0, 500),
|
|
655
|
+
};
|
|
656
|
+
});
|
|
657
|
+
const systemPrompt = `# Role
|
|
658
|
+
You are a senior security researcher and reverse engineer specializing in:
|
|
659
|
+
- Web API security analysis and cryptographic pattern recognition
|
|
660
|
+
- Authentication and authorization mechanism identification (OAuth, JWT, SAML, custom tokens)
|
|
661
|
+
- Encryption algorithm detection (AES, RSA, DES, 3DES, ChaCha20, etc.)
|
|
662
|
+
- Signature scheme analysis (HMAC, RSA-PSS, ECDSA, custom signing)
|
|
663
|
+
- Parameter encoding and obfuscation techniques (Base64, Hex, URL encoding, custom encoding)
|
|
664
|
+
|
|
665
|
+
# Expertise Areas
|
|
666
|
+
- **Symmetric Encryption**: AES (CBC, GCM, CTR), DES, 3DES, Blowfish, ChaCha20
|
|
667
|
+
- **Asymmetric Encryption**: RSA (PKCS1, OAEP), ECC, ElGamal
|
|
668
|
+
- **Hash Functions**: MD5, SHA-1, SHA-256, SHA-512, BLAKE2, RIPEMD
|
|
669
|
+
- **MAC**: HMAC-SHA256, HMAC-SHA512, CMAC
|
|
670
|
+
- **Encoding**: Base64, Hex, URL encoding, custom Base variants
|
|
671
|
+
- **Token Formats**: JWT (HS256, RS256), OAuth 2.0, SAML, custom tokens
|
|
672
|
+
|
|
673
|
+
# Task
|
|
674
|
+
Analyze HTTP requests to identify cryptographic patterns, authentication mechanisms, and security-related parameters.
|
|
675
|
+
|
|
676
|
+
# Analysis Methodology
|
|
677
|
+
1. **URL Analysis**: Examine URL paths and query parameters for crypto-related keywords
|
|
678
|
+
2. **Header Analysis**: Check Authorization, X-Signature, X-Token headers
|
|
679
|
+
3. **Parameter Analysis**: Identify encrypted/encoded parameters by pattern (length, charset, format)
|
|
680
|
+
4. **Signature Detection**: Look for sign/signature/hmac parameters and their dependencies
|
|
681
|
+
5. **Token Detection**: Identify JWT (xxx.yyy.zzz), OAuth tokens, session tokens
|
|
682
|
+
6. **Custom Pattern Recognition**: Detect proprietary encryption/signing schemes
|
|
683
|
+
|
|
684
|
+
# Output Requirements
|
|
685
|
+
- Return ONLY valid JSON (no markdown, no explanations)
|
|
686
|
+
- Use confidence scores (0.0-1.0) for uncertain detections
|
|
687
|
+
- Provide specific evidence for each detection
|
|
688
|
+
- Be precise and avoid hallucination`;
|
|
689
|
+
const userPrompt = `# Network Requests to Analyze
|
|
690
|
+
\`\`\`json
|
|
691
|
+
${JSON.stringify(requestSummary, null, 2)}
|
|
692
|
+
\`\`\`
|
|
693
|
+
|
|
694
|
+
# Required Output Schema
|
|
695
|
+
Return a JSON object with this EXACT structure (all fields required):
|
|
696
|
+
|
|
697
|
+
\`\`\`json
|
|
698
|
+
{
|
|
699
|
+
"encryption": [
|
|
700
|
+
{
|
|
701
|
+
"type": "AES-256-CBC | RSA-2048 | MD5 | SHA-256 | Base64 | Custom",
|
|
702
|
+
"location": "URL parameter name or header name",
|
|
703
|
+
"confidence": 0.95,
|
|
704
|
+
"evidence": [
|
|
705
|
+
"Parameter 'data' has Base64-like pattern (length=344, charset=[A-Za-z0-9+/=])",
|
|
706
|
+
"Parameter name contains 'encrypt' keyword"
|
|
707
|
+
],
|
|
708
|
+
"parameters": {
|
|
709
|
+
"parameterName": "data",
|
|
710
|
+
"sampleValue": "first 50 chars of encrypted data...",
|
|
711
|
+
"detectedPattern": "Base64 | Hex | Custom",
|
|
712
|
+
"estimatedKeySize": "128 | 192 | 256 | null"
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
],
|
|
716
|
+
"signature": [
|
|
717
|
+
{
|
|
718
|
+
"type": "HMAC-SHA256 | JWT-RS256 | Custom",
|
|
719
|
+
"location": "URL or header",
|
|
720
|
+
"parameters": ["timestamp", "nonce", "data"],
|
|
721
|
+
"confidence": 0.88,
|
|
722
|
+
"signatureParameter": "sign",
|
|
723
|
+
"algorithm": "detected or inferred algorithm",
|
|
724
|
+
"evidence": [
|
|
725
|
+
"Found 'sign' parameter with 64-char hex string (SHA-256 output length)",
|
|
726
|
+
"Request includes timestamp and nonce (common in HMAC)"
|
|
727
|
+
]
|
|
728
|
+
}
|
|
729
|
+
],
|
|
730
|
+
"token": [
|
|
731
|
+
{
|
|
732
|
+
"type": "JWT | OAuth2 | Custom",
|
|
733
|
+
"location": "Authorization header | URL parameter",
|
|
734
|
+
"format": "Bearer JWT | URL parameter 'access_token'",
|
|
735
|
+
"confidence": 0.98,
|
|
736
|
+
"tokenStructure": "xxx.yyy.zzz (JWT) | opaque string",
|
|
737
|
+
"evidence": [
|
|
738
|
+
"Authorization header contains 'Bearer' prefix",
|
|
739
|
+
"Token matches JWT pattern (3 Base64 segments separated by dots)"
|
|
740
|
+
]
|
|
741
|
+
}
|
|
742
|
+
],
|
|
743
|
+
"customPatterns": [
|
|
744
|
+
{
|
|
745
|
+
"type": "Anti-replay | Rate limiting | Custom encryption | Other",
|
|
746
|
+
"description": "Detailed description of the pattern",
|
|
747
|
+
"location": "URL or header",
|
|
748
|
+
"confidence": 0.75,
|
|
749
|
+
"relatedParameters": ["param1", "param2"],
|
|
750
|
+
"evidence": ["evidence 1", "evidence 2"]
|
|
751
|
+
}
|
|
752
|
+
]
|
|
753
|
+
}
|
|
754
|
+
\`\`\`
|
|
755
|
+
|
|
756
|
+
# Example Output (for reference)
|
|
757
|
+
\`\`\`json
|
|
758
|
+
{
|
|
759
|
+
"encryption": [
|
|
760
|
+
{
|
|
761
|
+
"type": "AES-256-CBC",
|
|
762
|
+
"location": "POST data parameter 'encryptedData'",
|
|
763
|
+
"confidence": 0.92,
|
|
764
|
+
"evidence": [
|
|
765
|
+
"Parameter value is Base64-encoded (length=344, divisible by 4)",
|
|
766
|
+
"Decoded length suggests AES block cipher (multiple of 16 bytes)",
|
|
767
|
+
"Parameter name explicitly mentions 'encrypted'"
|
|
768
|
+
],
|
|
769
|
+
"parameters": {
|
|
770
|
+
"parameterName": "encryptedData",
|
|
771
|
+
"sampleValue": "U2FsdGVkX1+1234567890abcdefghijklmnopqrstuvwxyz...",
|
|
772
|
+
"detectedPattern": "Base64",
|
|
773
|
+
"estimatedKeySize": "256"
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
],
|
|
777
|
+
"signature": [
|
|
778
|
+
{
|
|
779
|
+
"type": "HMAC-SHA256",
|
|
780
|
+
"location": "URL parameter 'sign'",
|
|
781
|
+
"parameters": ["timestamp", "nonce", "appId", "data"],
|
|
782
|
+
"confidence": 0.95,
|
|
783
|
+
"signatureParameter": "sign",
|
|
784
|
+
"algorithm": "HMAC-SHA256",
|
|
785
|
+
"evidence": [
|
|
786
|
+
"Signature is 64-char hex string (SHA-256 output)",
|
|
787
|
+
"Request includes timestamp, nonce (anti-replay)",
|
|
788
|
+
"All parameters except 'sign' likely participate in signing"
|
|
789
|
+
]
|
|
790
|
+
}
|
|
791
|
+
],
|
|
792
|
+
"token": [
|
|
793
|
+
{
|
|
794
|
+
"type": "JWT",
|
|
795
|
+
"location": "Authorization header",
|
|
796
|
+
"format": "Bearer JWT (HS256)",
|
|
797
|
+
"confidence": 0.99,
|
|
798
|
+
"tokenStructure": "eyJhbGc.eyJzdWI.SflKxwRJ",
|
|
799
|
+
"evidence": [
|
|
800
|
+
"Perfect JWT format: header.payload.signature",
|
|
801
|
+
"Header decodes to {\"alg\":\"HS256\",\"typ\":\"JWT\"}",
|
|
802
|
+
"Payload contains standard claims (sub, exp, iat)"
|
|
803
|
+
]
|
|
804
|
+
}
|
|
805
|
+
],
|
|
806
|
+
"customPatterns": [
|
|
807
|
+
{
|
|
808
|
+
"type": "Anti-replay mechanism",
|
|
809
|
+
"description": "Uses timestamp + nonce to prevent replay attacks",
|
|
810
|
+
"location": "URL parameters",
|
|
811
|
+
"confidence": 0.88,
|
|
812
|
+
"relatedParameters": ["timestamp", "nonce"],
|
|
813
|
+
"evidence": [
|
|
814
|
+
"Timestamp parameter present in all requests",
|
|
815
|
+
"Nonce appears to be random UUID",
|
|
816
|
+
"Both parameters likely included in signature calculation"
|
|
817
|
+
]
|
|
818
|
+
}
|
|
819
|
+
]
|
|
820
|
+
}
|
|
821
|
+
\`\`\`
|
|
822
|
+
|
|
823
|
+
Now analyze the provided requests and return ONLY the JSON output (no additional text).`;
|
|
824
|
+
try {
|
|
825
|
+
const response = await this.llmService.chat([
|
|
826
|
+
{ role: 'system', content: systemPrompt },
|
|
827
|
+
{ role: 'user', content: userPrompt },
|
|
828
|
+
], { temperature: 0.2, maxTokens: 3000 });
|
|
829
|
+
const result = JSON.parse(response.content);
|
|
830
|
+
logger.success('LLM request analysis completed', {
|
|
831
|
+
encryption: result.encryption?.length || 0,
|
|
832
|
+
signature: result.signature?.length || 0,
|
|
833
|
+
token: result.token?.length || 0,
|
|
834
|
+
custom: result.customPatterns?.length || 0,
|
|
835
|
+
});
|
|
836
|
+
return result;
|
|
837
|
+
}
|
|
838
|
+
catch (error) {
|
|
839
|
+
logger.error('LLM request analysis failed:', error);
|
|
840
|
+
return { encryption: [], signature: [], token: [], customPatterns: [] };
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
async analyzeCriticalLogsWithLLM(logs) {
|
|
844
|
+
if (!this.llmService) {
|
|
845
|
+
logger.warn('LLM service not available, skipping LLM log analysis');
|
|
846
|
+
return { keyFunctions: [], dataFlow: '', suspiciousPatterns: [] };
|
|
847
|
+
}
|
|
848
|
+
logger.info('Starting LLM-enhanced log analysis...');
|
|
849
|
+
const logSummary = logs.slice(0, 50).map((log, index) => ({
|
|
850
|
+
index,
|
|
851
|
+
type: log.type,
|
|
852
|
+
text: log.text.substring(0, 300),
|
|
853
|
+
url: log.url,
|
|
854
|
+
lineNumber: log.lineNumber,
|
|
855
|
+
stackTrace: log.stackTrace?.slice(0, 3),
|
|
856
|
+
}));
|
|
857
|
+
const systemPrompt = `# Role
|
|
858
|
+
You are an expert JavaScript reverse engineer and security analyst specializing in:
|
|
859
|
+
- Console log analysis and code behavior understanding
|
|
860
|
+
- Anti-debugging technique detection (debugger statements, DevTools detection, timing checks)
|
|
861
|
+
- Code obfuscation pattern recognition (string arrays, control flow flattening, VM protection)
|
|
862
|
+
- Cryptographic operation identification from runtime logs
|
|
863
|
+
- Data flow analysis and sensitive information leakage detection
|
|
864
|
+
- Framework and library identification from console output
|
|
865
|
+
|
|
866
|
+
# Known Patterns
|
|
867
|
+
**Anti-Debugging**:
|
|
868
|
+
- debugger statements
|
|
869
|
+
- DevTools detection (window.outerHeight - window.innerHeight)
|
|
870
|
+
- Function.prototype.toString checks
|
|
871
|
+
- Timing-based detection (performance.now, Date.now)
|
|
872
|
+
- Console.log redirection/blocking
|
|
873
|
+
|
|
874
|
+
**Obfuscation Indicators**:
|
|
875
|
+
- Mangled variable names (_0x1234, _0xabcd)
|
|
876
|
+
- String array decoders
|
|
877
|
+
- Control flow state machines
|
|
878
|
+
- Eval/Function constructor usage
|
|
879
|
+
|
|
880
|
+
**Crypto Operations**:
|
|
881
|
+
- CryptoJS, crypto-js, JSEncrypt, forge library calls
|
|
882
|
+
- Web Crypto API usage (crypto.subtle)
|
|
883
|
+
- Custom encryption function calls
|
|
884
|
+
|
|
885
|
+
**Sensitive Operations**:
|
|
886
|
+
- localStorage/sessionStorage access
|
|
887
|
+
- Cookie manipulation
|
|
888
|
+
- XHR/Fetch API calls
|
|
889
|
+
- WebSocket connections
|
|
890
|
+
|
|
891
|
+
# Task
|
|
892
|
+
Analyze console logs to:
|
|
893
|
+
1. Identify key functions and their purposes
|
|
894
|
+
2. Map data flow through the application
|
|
895
|
+
3. Detect suspicious patterns (anti-debugging, obfuscation, crypto)
|
|
896
|
+
4. Assess security implications
|
|
897
|
+
|
|
898
|
+
# Analysis Standards
|
|
899
|
+
- Use OWASP guidelines for security assessment
|
|
900
|
+
- Provide confidence scores for uncertain identifications
|
|
901
|
+
- Be precise and avoid hallucination
|
|
902
|
+
- Focus on actionable insights`;
|
|
903
|
+
const userPrompt = `# Console Logs to Analyze
|
|
904
|
+
\`\`\`json
|
|
905
|
+
${JSON.stringify(logSummary, null, 2)}
|
|
906
|
+
\`\`\`
|
|
907
|
+
|
|
908
|
+
# Required Output Schema
|
|
909
|
+
Return ONLY valid JSON with this exact structure:
|
|
910
|
+
|
|
911
|
+
\`\`\`json
|
|
912
|
+
{
|
|
913
|
+
"keyFunctions": [
|
|
914
|
+
{
|
|
915
|
+
"name": "function name (e.g., 'encryptPassword', '_0x1a2b')",
|
|
916
|
+
"purpose": "what the function does",
|
|
917
|
+
"confidence": 0.92,
|
|
918
|
+
"evidence": ["log index 5 shows function call", "parameter suggests encryption"],
|
|
919
|
+
"category": "encryption | authentication | data-processing | network | obfuscation | other"
|
|
920
|
+
}
|
|
921
|
+
],
|
|
922
|
+
"dataFlow": "Concise description of how data flows through the application based on logs",
|
|
923
|
+
"suspiciousPatterns": [
|
|
924
|
+
{
|
|
925
|
+
"type": "anti-debugging | obfuscation | crypto | data-leakage | other",
|
|
926
|
+
"description": "Detailed description of the suspicious pattern",
|
|
927
|
+
"location": "log index or URL",
|
|
928
|
+
"severity": "critical | high | medium | low",
|
|
929
|
+
"evidence": ["specific log entries that support this finding"],
|
|
930
|
+
"recommendation": "how to investigate or mitigate"
|
|
931
|
+
}
|
|
932
|
+
],
|
|
933
|
+
"frameworkDetection": {
|
|
934
|
+
"detected": true,
|
|
935
|
+
"frameworks": ["React 18.x", "Axios 1.x"],
|
|
936
|
+
"confidence": 0.88,
|
|
937
|
+
"evidence": ["log mentions React DevTools", "axios request interceptor"]
|
|
938
|
+
},
|
|
939
|
+
"securityConcerns": [
|
|
940
|
+
{
|
|
941
|
+
"type": "XSS | Sensitive data exposure | Insecure crypto | Other",
|
|
942
|
+
"description": "what's the concern",
|
|
943
|
+
"severity": "critical | high | medium | low",
|
|
944
|
+
"cwe": "CWE-79",
|
|
945
|
+
"affectedLogs": [1, 5, 12]
|
|
946
|
+
}
|
|
947
|
+
]
|
|
948
|
+
}
|
|
949
|
+
\`\`\`
|
|
950
|
+
|
|
951
|
+
# Example Output
|
|
952
|
+
\`\`\`json
|
|
953
|
+
{
|
|
954
|
+
"keyFunctions": [
|
|
955
|
+
{
|
|
956
|
+
"name": "encryptUserData",
|
|
957
|
+
"purpose": "Encrypts user credentials before sending to server",
|
|
958
|
+
"confidence": 0.95,
|
|
959
|
+
"evidence": [
|
|
960
|
+
"Log 3: 'Encrypting password...'",
|
|
961
|
+
"Log 5: CryptoJS.AES.encrypt called",
|
|
962
|
+
"Log 7: 'Encrypted data: U2FsdGVk...'"
|
|
963
|
+
],
|
|
964
|
+
"category": "encryption"
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
"name": "_0x1a2b",
|
|
968
|
+
"purpose": "String array decoder (obfuscation)",
|
|
969
|
+
"confidence": 0.88,
|
|
970
|
+
"evidence": [
|
|
971
|
+
"Log 1: Function accesses array with numeric index",
|
|
972
|
+
"Log 2: Returns decoded string",
|
|
973
|
+
"Mangled name suggests obfuscation"
|
|
974
|
+
],
|
|
975
|
+
"category": "obfuscation"
|
|
976
|
+
}
|
|
977
|
+
],
|
|
978
|
+
"dataFlow": "User input -> validation -> encryption (AES-256) -> API request -> response decryption -> UI update. Sensitive data (password) is encrypted before transmission.",
|
|
979
|
+
"suspiciousPatterns": [
|
|
980
|
+
{
|
|
981
|
+
"type": "anti-debugging",
|
|
982
|
+
"description": "Code checks for DevTools using window size comparison",
|
|
983
|
+
"location": "Log index 10",
|
|
984
|
+
"severity": "medium",
|
|
985
|
+
"evidence": [
|
|
986
|
+
"Log 10: 'if(window.outerHeight - window.innerHeight > 100)'",
|
|
987
|
+
"This is a common DevTools detection technique"
|
|
988
|
+
],
|
|
989
|
+
"recommendation": "Investigate why the application tries to detect debugging. May indicate anti-reverse-engineering measures."
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
"type": "obfuscation",
|
|
993
|
+
"description": "Heavy use of mangled variable names and string array",
|
|
994
|
+
"location": "Multiple logs",
|
|
995
|
+
"severity": "low",
|
|
996
|
+
"evidence": [
|
|
997
|
+
"Logs 1-5: Variables named _0x1234, _0xabcd",
|
|
998
|
+
"Log 2: String array access pattern"
|
|
999
|
+
],
|
|
1000
|
+
"recommendation": "Code is obfuscated. Use deobfuscation tools or manual analysis."
|
|
1001
|
+
}
|
|
1002
|
+
],
|
|
1003
|
+
"frameworkDetection": {
|
|
1004
|
+
"detected": true,
|
|
1005
|
+
"frameworks": ["React 18.2", "CryptoJS 4.1"],
|
|
1006
|
+
"confidence": 0.92,
|
|
1007
|
+
"evidence": [
|
|
1008
|
+
"Log 15: 'Download the React DevTools'",
|
|
1009
|
+
"Log 5: 'CryptoJS.AES.encrypt'"
|
|
1010
|
+
]
|
|
1011
|
+
},
|
|
1012
|
+
"securityConcerns": [
|
|
1013
|
+
{
|
|
1014
|
+
"type": "Sensitive data exposure",
|
|
1015
|
+
"description": "Password appears in console log before encryption",
|
|
1016
|
+
"severity": "high",
|
|
1017
|
+
"cwe": "CWE-532",
|
|
1018
|
+
"affectedLogs": [2]
|
|
1019
|
+
}
|
|
1020
|
+
]
|
|
1021
|
+
}
|
|
1022
|
+
\`\`\`
|
|
1023
|
+
|
|
1024
|
+
Now analyze the logs and return ONLY the JSON output (no additional text).`;
|
|
1025
|
+
try {
|
|
1026
|
+
const response = await this.llmService.chat([
|
|
1027
|
+
{ role: 'system', content: systemPrompt },
|
|
1028
|
+
{ role: 'user', content: userPrompt },
|
|
1029
|
+
], { temperature: 0.2, maxTokens: 2500 });
|
|
1030
|
+
const result = JSON.parse(response.content);
|
|
1031
|
+
logger.success('LLM log analysis completed', {
|
|
1032
|
+
keyFunctions: result.keyFunctions?.length || 0,
|
|
1033
|
+
suspiciousPatterns: result.suspiciousPatterns?.length || 0,
|
|
1034
|
+
});
|
|
1035
|
+
return result;
|
|
1036
|
+
}
|
|
1037
|
+
catch (error) {
|
|
1038
|
+
logger.error('LLM log analysis failed:', error);
|
|
1039
|
+
return { keyFunctions: [], dataFlow: '', suspiciousPatterns: [] };
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
async expandKeywordsWithLLM(context) {
|
|
1043
|
+
if (!this.llmService) {
|
|
1044
|
+
return { apiKeywords: [], cryptoKeywords: [], frameworkKeywords: [], businessKeywords: [] };
|
|
1045
|
+
}
|
|
1046
|
+
logger.info('Expanding keywords with LLM...');
|
|
1047
|
+
const urlPatterns = context.requests.slice(0, 15).map(r => {
|
|
1048
|
+
try {
|
|
1049
|
+
const url = new URL(r.url);
|
|
1050
|
+
return {
|
|
1051
|
+
path: url.pathname,
|
|
1052
|
+
params: Array.from(url.searchParams.keys()),
|
|
1053
|
+
method: r.method,
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
1056
|
+
catch {
|
|
1057
|
+
return { path: r.url, params: [], method: r.method };
|
|
1058
|
+
}
|
|
1059
|
+
});
|
|
1060
|
+
const logKeywords = context.logs.slice(0, 20).map(l => l.text.substring(0, 150));
|
|
1061
|
+
const systemPrompt = `# Role
|
|
1062
|
+
You are a web application security analyst and reverse engineer specializing in:
|
|
1063
|
+
- API endpoint pattern recognition
|
|
1064
|
+
- Business logic inference from network traffic
|
|
1065
|
+
- Framework and library identification
|
|
1066
|
+
- Cryptographic operation detection
|
|
1067
|
+
- Domain-specific terminology extraction
|
|
1068
|
+
|
|
1069
|
+
# Task
|
|
1070
|
+
Analyze the provided network requests and console logs to infer relevant keywords that can help filter and prioritize future analysis.
|
|
1071
|
+
|
|
1072
|
+
# Methodology
|
|
1073
|
+
1. **API Keywords**: Extract common API-related terms from URL paths and parameters
|
|
1074
|
+
2. **Crypto Keywords**: Identify encryption, hashing, signing related terms
|
|
1075
|
+
3. **Framework Keywords**: Detect framework-specific patterns and terminology
|
|
1076
|
+
4. **Business Keywords**: Infer business domain terms (e.g., 'order', 'payment', 'user')
|
|
1077
|
+
|
|
1078
|
+
# Output Requirements
|
|
1079
|
+
- Return ONLY valid JSON
|
|
1080
|
+
- Keywords should be lowercase
|
|
1081
|
+
- Avoid generic terms (e.g., 'data', 'info')
|
|
1082
|
+
- Focus on actionable, specific keywords
|
|
1083
|
+
- Limit to 10-15 keywords per category`;
|
|
1084
|
+
const userPrompt = `# Website Domain
|
|
1085
|
+
${context.domain}
|
|
1086
|
+
|
|
1087
|
+
# URL Patterns (${urlPatterns.length} samples)
|
|
1088
|
+
\`\`\`json
|
|
1089
|
+
${JSON.stringify(urlPatterns, null, 2)}
|
|
1090
|
+
\`\`\`
|
|
1091
|
+
|
|
1092
|
+
# Console Log Samples (${logKeywords.length} samples)
|
|
1093
|
+
\`\`\`
|
|
1094
|
+
${logKeywords.join('\n---\n')}
|
|
1095
|
+
\`\`\`
|
|
1096
|
+
|
|
1097
|
+
# Required Output Schema
|
|
1098
|
+
\`\`\`json
|
|
1099
|
+
{
|
|
1100
|
+
"apiKeywords": [
|
|
1101
|
+
"string (e.g., 'auth', 'login', 'verify', 'validate')"
|
|
1102
|
+
],
|
|
1103
|
+
"cryptoKeywords": [
|
|
1104
|
+
"string (e.g., 'encrypt', 'decrypt', 'sign', 'hash', 'token')"
|
|
1105
|
+
],
|
|
1106
|
+
"frameworkKeywords": [
|
|
1107
|
+
"string (e.g., 'react', 'vue', 'axios', 'redux')"
|
|
1108
|
+
],
|
|
1109
|
+
"businessKeywords": [
|
|
1110
|
+
"string (e.g., 'order', 'payment', 'cart', 'checkout', 'product')"
|
|
1111
|
+
]
|
|
1112
|
+
}
|
|
1113
|
+
\`\`\`
|
|
1114
|
+
|
|
1115
|
+
# Example Output
|
|
1116
|
+
\`\`\`json
|
|
1117
|
+
{
|
|
1118
|
+
"apiKeywords": ["auth", "login", "verify", "captcha", "session", "refresh"],
|
|
1119
|
+
"cryptoKeywords": ["encrypt", "decrypt", "sign", "signature", "token", "hmac"],
|
|
1120
|
+
"frameworkKeywords": ["react", "axios", "redux", "antd"],
|
|
1121
|
+
"businessKeywords": ["order", "payment", "cart", "product", "user", "address"]
|
|
1122
|
+
}
|
|
1123
|
+
\`\`\`
|
|
1124
|
+
|
|
1125
|
+
Now analyze the data and return ONLY the JSON output.`;
|
|
1126
|
+
try {
|
|
1127
|
+
const response = await this.llmService.chat([
|
|
1128
|
+
{ role: 'system', content: systemPrompt },
|
|
1129
|
+
{ role: 'user', content: userPrompt },
|
|
1130
|
+
], { temperature: 0.4, maxTokens: 800 });
|
|
1131
|
+
const result = JSON.parse(response.content);
|
|
1132
|
+
logger.success('Keywords expanded', {
|
|
1133
|
+
api: result.apiKeywords?.length || 0,
|
|
1134
|
+
crypto: result.cryptoKeywords?.length || 0,
|
|
1135
|
+
framework: result.frameworkKeywords?.length || 0,
|
|
1136
|
+
});
|
|
1137
|
+
return result;
|
|
1138
|
+
}
|
|
1139
|
+
catch (error) {
|
|
1140
|
+
logger.error('Keyword expansion failed:', error);
|
|
1141
|
+
return { apiKeywords: [], cryptoKeywords: [], frameworkKeywords: [], businessKeywords: [] };
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
async analyzeWithLLM(data) {
|
|
1145
|
+
logger.info('Starting hybrid analysis (rules + LLM)...');
|
|
1146
|
+
const ruleBasedResult = this.analyze(data);
|
|
1147
|
+
if (this.llmService) {
|
|
1148
|
+
try {
|
|
1149
|
+
const llmRequestAnalysis = await this.analyzeCriticalRequestsWithLLM(ruleBasedResult.criticalRequests);
|
|
1150
|
+
const llmLogAnalysis = await this.analyzeCriticalLogsWithLLM(ruleBasedResult.criticalLogs);
|
|
1151
|
+
ruleBasedResult.patterns.encryption = [
|
|
1152
|
+
...(ruleBasedResult.patterns.encryption || []),
|
|
1153
|
+
...llmRequestAnalysis.encryption,
|
|
1154
|
+
];
|
|
1155
|
+
ruleBasedResult.patterns.signature = [
|
|
1156
|
+
...(ruleBasedResult.patterns.signature || []),
|
|
1157
|
+
...llmRequestAnalysis.signature,
|
|
1158
|
+
];
|
|
1159
|
+
ruleBasedResult.patterns.token = [
|
|
1160
|
+
...(ruleBasedResult.patterns.token || []),
|
|
1161
|
+
...llmRequestAnalysis.token,
|
|
1162
|
+
];
|
|
1163
|
+
ruleBasedResult.summary.keyFunctions = [
|
|
1164
|
+
...ruleBasedResult.summary.keyFunctions,
|
|
1165
|
+
...llmLogAnalysis.keyFunctions.map(f => f.name),
|
|
1166
|
+
];
|
|
1167
|
+
logger.success('Hybrid analysis completed with LLM enhancement');
|
|
1168
|
+
}
|
|
1169
|
+
catch (error) {
|
|
1170
|
+
logger.error('LLM enhancement failed, using rule-based results only:', error);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
return ruleBasedResult;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
//# sourceMappingURL=IntelligentAnalyzer.js.map
|