@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,1225 @@
|
|
|
1
|
+
import { logger } from '../../utils/logger.js';
|
|
2
|
+
export class HookManager {
|
|
3
|
+
hooks = new Map();
|
|
4
|
+
hookScripts = new Map();
|
|
5
|
+
hookMetadata = new Map();
|
|
6
|
+
hookConditions = new Map();
|
|
7
|
+
MAX_HOOK_RECORDS = 1000;
|
|
8
|
+
MAX_TOTAL_RECORDS = 10000;
|
|
9
|
+
async createHook(options) {
|
|
10
|
+
logger.info(`Creating hook for ${options.target} (type: ${options.type})...`);
|
|
11
|
+
try {
|
|
12
|
+
const { target, type, action = 'log', condition, performance = false } = options;
|
|
13
|
+
const hookScript = this.generateHookScript(target, type, action, options.customCode, condition, performance);
|
|
14
|
+
const hookId = `${target}-${type}-${Date.now()}`;
|
|
15
|
+
this.hookScripts.set(hookId, hookScript);
|
|
16
|
+
if (condition) {
|
|
17
|
+
this.hookConditions.set(hookId, condition);
|
|
18
|
+
}
|
|
19
|
+
this.hookMetadata.set(hookId, {
|
|
20
|
+
id: hookId,
|
|
21
|
+
enabled: true,
|
|
22
|
+
createdAt: Date.now(),
|
|
23
|
+
callCount: 0,
|
|
24
|
+
totalExecutionTime: 0,
|
|
25
|
+
});
|
|
26
|
+
logger.success(`Hook created: ${hookId}`);
|
|
27
|
+
return {
|
|
28
|
+
hookId,
|
|
29
|
+
script: hookScript,
|
|
30
|
+
instructions: this.getInjectionInstructions(type),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
logger.error('Failed to create hook', error);
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
generateHookScript(target, type, action, customCode, condition, performance = false) {
|
|
39
|
+
switch (type) {
|
|
40
|
+
case 'function':
|
|
41
|
+
return this.generateFunctionHook(target, action, customCode, condition, performance);
|
|
42
|
+
case 'xhr':
|
|
43
|
+
return this.generateXHRHook(action, customCode, condition, performance);
|
|
44
|
+
case 'fetch':
|
|
45
|
+
return this.generateFetchHook(action, customCode, condition, performance);
|
|
46
|
+
case 'websocket':
|
|
47
|
+
return this.generateWebSocketHook(action, customCode, condition, performance);
|
|
48
|
+
case 'localstorage':
|
|
49
|
+
return this.generateLocalStorageHook(action, customCode, condition, performance);
|
|
50
|
+
case 'cookie':
|
|
51
|
+
return this.generateCookieHook(action, customCode, condition, performance);
|
|
52
|
+
case 'eval':
|
|
53
|
+
return this.generateEvalHook(action, customCode, condition, performance);
|
|
54
|
+
case 'object-method':
|
|
55
|
+
return this.generateObjectMethodHook(target, action, customCode, condition, performance);
|
|
56
|
+
default:
|
|
57
|
+
throw new Error(`Unsupported hook type: ${type}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
generateFunctionHook(target, action, customCode, condition, performance = false) {
|
|
61
|
+
const conditionCode = condition
|
|
62
|
+
? `
|
|
63
|
+
// 条件检查
|
|
64
|
+
let callCount = 0;
|
|
65
|
+
let lastCallTime = 0;
|
|
66
|
+
const maxCalls = ${condition.maxCalls || 'Infinity'};
|
|
67
|
+
const minInterval = ${condition.minInterval || 0};
|
|
68
|
+
`
|
|
69
|
+
: '';
|
|
70
|
+
const performanceCode = performance
|
|
71
|
+
? `
|
|
72
|
+
const startTime = performance.now();
|
|
73
|
+
`
|
|
74
|
+
: '';
|
|
75
|
+
const performanceEndCode = performance
|
|
76
|
+
? `
|
|
77
|
+
const endTime = performance.now();
|
|
78
|
+
console.log('[Hook] Execution time:', (endTime - startTime).toFixed(2), 'ms');
|
|
79
|
+
`
|
|
80
|
+
: '';
|
|
81
|
+
return `
|
|
82
|
+
(function() {
|
|
83
|
+
'use strict';
|
|
84
|
+
${conditionCode}
|
|
85
|
+
|
|
86
|
+
// 保存原始函数
|
|
87
|
+
const originalFunction = ${target};
|
|
88
|
+
|
|
89
|
+
if (typeof originalFunction !== 'function') {
|
|
90
|
+
console.error('[Hook] Target is not a function: ${target}');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Hook函数
|
|
95
|
+
${target} = function(...args) {
|
|
96
|
+
${condition
|
|
97
|
+
? `
|
|
98
|
+
// 条件过滤
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
if (callCount >= maxCalls) {
|
|
101
|
+
console.log('[Hook] Max calls reached, skipping');
|
|
102
|
+
return originalFunction.apply(this, args);
|
|
103
|
+
}
|
|
104
|
+
if (now - lastCallTime < minInterval) {
|
|
105
|
+
console.log('[Hook] Min interval not met, skipping');
|
|
106
|
+
return originalFunction.apply(this, args);
|
|
107
|
+
}
|
|
108
|
+
callCount++;
|
|
109
|
+
lastCallTime = now;
|
|
110
|
+
`
|
|
111
|
+
: ''}
|
|
112
|
+
|
|
113
|
+
${performanceCode}
|
|
114
|
+
|
|
115
|
+
const hookContext = {
|
|
116
|
+
target: '${target}',
|
|
117
|
+
type: 'function',
|
|
118
|
+
timestamp: Date.now(),
|
|
119
|
+
arguments: args,
|
|
120
|
+
stackTrace: new Error().stack
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
console.log('[Hook] Function called:', hookContext);
|
|
124
|
+
|
|
125
|
+
${action === 'block' ? 'return undefined;' : ''}
|
|
126
|
+
${action === 'modify' && customCode ? customCode : ''}
|
|
127
|
+
|
|
128
|
+
// 调用原始函数
|
|
129
|
+
const result = originalFunction.apply(this, args);
|
|
130
|
+
|
|
131
|
+
${performanceEndCode}
|
|
132
|
+
|
|
133
|
+
console.log('[Hook] Function result:', result);
|
|
134
|
+
|
|
135
|
+
return result;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
console.log('[Hook] Successfully hooked: ${target}');
|
|
139
|
+
})();
|
|
140
|
+
`.trim();
|
|
141
|
+
}
|
|
142
|
+
generateXHRHook(action, customCode, _condition, _performance = false) {
|
|
143
|
+
return `
|
|
144
|
+
(function() {
|
|
145
|
+
'use strict';
|
|
146
|
+
|
|
147
|
+
// 保存原始方法
|
|
148
|
+
const XHR = XMLHttpRequest.prototype;
|
|
149
|
+
const originalOpen = XHR.open;
|
|
150
|
+
const originalSend = XHR.send;
|
|
151
|
+
const originalSetRequestHeader = XHR.setRequestHeader;
|
|
152
|
+
|
|
153
|
+
// Hook open方法
|
|
154
|
+
XHR.open = function(method, url, async, user, password) {
|
|
155
|
+
// 保存请求信息
|
|
156
|
+
this._hookData = {
|
|
157
|
+
method: method,
|
|
158
|
+
url: url,
|
|
159
|
+
async: async !== false, // 默认异步
|
|
160
|
+
timestamp: Date.now(),
|
|
161
|
+
headers: {},
|
|
162
|
+
stackTrace: new Error().stack
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
console.log('[XHR Hook] open:', {
|
|
166
|
+
method: method,
|
|
167
|
+
url: url,
|
|
168
|
+
async: async !== false
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
${action === 'block' ? 'return;' : ''}
|
|
172
|
+
|
|
173
|
+
// 调用原始方法
|
|
174
|
+
return originalOpen.apply(this, arguments);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Hook setRequestHeader方法
|
|
178
|
+
XHR.setRequestHeader = function(header, value) {
|
|
179
|
+
if (this._hookData) {
|
|
180
|
+
this._hookData.headers[header] = value;
|
|
181
|
+
console.log('[XHR Hook] setRequestHeader:', { header, value });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return originalSetRequestHeader.apply(this, arguments);
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// Hook send方法
|
|
188
|
+
XHR.send = function(data) {
|
|
189
|
+
const xhr = this;
|
|
190
|
+
|
|
191
|
+
if (xhr._hookData) {
|
|
192
|
+
xhr._hookData.requestData = data;
|
|
193
|
+
xhr._hookData.sendTime = Date.now();
|
|
194
|
+
|
|
195
|
+
console.log('[XHR Hook] send:', {
|
|
196
|
+
url: xhr._hookData.url,
|
|
197
|
+
method: xhr._hookData.method,
|
|
198
|
+
headers: xhr._hookData.headers,
|
|
199
|
+
data: data
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Hook响应处理
|
|
204
|
+
const originalOnReadyStateChange = xhr.onreadystatechange;
|
|
205
|
+
|
|
206
|
+
xhr.onreadystatechange = function() {
|
|
207
|
+
// readyState === 4 表示请求完成
|
|
208
|
+
if (xhr.readyState === 4) {
|
|
209
|
+
const responseTime = Date.now() - (xhr._hookData?.sendTime || 0);
|
|
210
|
+
|
|
211
|
+
console.log('[XHR Hook] response:', {
|
|
212
|
+
url: xhr._hookData?.url,
|
|
213
|
+
status: xhr.status,
|
|
214
|
+
statusText: xhr.statusText,
|
|
215
|
+
responseTime: responseTime + 'ms',
|
|
216
|
+
responseHeaders: xhr.getAllResponseHeaders(),
|
|
217
|
+
responseType: xhr.responseType,
|
|
218
|
+
responseURL: xhr.responseURL
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// 根据responseType记录响应内容
|
|
222
|
+
try {
|
|
223
|
+
if (xhr.responseType === '' || xhr.responseType === 'text') {
|
|
224
|
+
console.log('[XHR Hook] responseText:', xhr.responseText?.substring(0, 500));
|
|
225
|
+
} else if (xhr.responseType === 'json') {
|
|
226
|
+
console.log('[XHR Hook] responseJSON:', xhr.response);
|
|
227
|
+
} else {
|
|
228
|
+
console.log('[XHR Hook] response:', typeof xhr.response);
|
|
229
|
+
}
|
|
230
|
+
} catch (e) {
|
|
231
|
+
console.warn('[XHR Hook] Failed to log response:', e);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// 调用原始的onreadystatechange
|
|
236
|
+
if (originalOnReadyStateChange) {
|
|
237
|
+
return originalOnReadyStateChange.apply(this, arguments);
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// 也Hook addEventListener('load')
|
|
242
|
+
const originalAddEventListener = xhr.addEventListener;
|
|
243
|
+
xhr.addEventListener = function(event, listener, ...args) {
|
|
244
|
+
if (event === 'load' || event === 'error' || event === 'abort') {
|
|
245
|
+
const wrappedListener = function(e) {
|
|
246
|
+
console.log(\`[XHR Hook] event '\${event}':\`, {
|
|
247
|
+
url: xhr._hookData?.url,
|
|
248
|
+
status: xhr.status
|
|
249
|
+
});
|
|
250
|
+
return listener.apply(this, arguments);
|
|
251
|
+
};
|
|
252
|
+
return originalAddEventListener.call(this, event, wrappedListener, ...args);
|
|
253
|
+
}
|
|
254
|
+
return originalAddEventListener.apply(this, arguments);
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
${customCode || ''}
|
|
258
|
+
|
|
259
|
+
// 调用原始send
|
|
260
|
+
return originalSend.apply(this, arguments);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
console.log('[Hook] XHR hooked successfully');
|
|
264
|
+
})();
|
|
265
|
+
`.trim();
|
|
266
|
+
}
|
|
267
|
+
generateFetchHook(action, customCode, _condition, _performance = false) {
|
|
268
|
+
return `
|
|
269
|
+
(function() {
|
|
270
|
+
'use strict';
|
|
271
|
+
|
|
272
|
+
const originalFetch = window.fetch;
|
|
273
|
+
|
|
274
|
+
// 使用Proxy包装fetch (更强大的拦截方式)
|
|
275
|
+
window.fetch = new Proxy(originalFetch, {
|
|
276
|
+
apply: function(target, thisArg, args) {
|
|
277
|
+
const [resource, config] = args;
|
|
278
|
+
|
|
279
|
+
// 解析请求信息
|
|
280
|
+
let url, method, headers, body;
|
|
281
|
+
|
|
282
|
+
if (resource instanceof Request) {
|
|
283
|
+
// 如果是Request对象
|
|
284
|
+
url = resource.url;
|
|
285
|
+
method = resource.method;
|
|
286
|
+
headers = Object.fromEntries(resource.headers.entries());
|
|
287
|
+
body = resource.body;
|
|
288
|
+
} else {
|
|
289
|
+
// 如果是URL字符串
|
|
290
|
+
url = resource;
|
|
291
|
+
method = config?.method || 'GET';
|
|
292
|
+
headers = config?.headers || {};
|
|
293
|
+
body = config?.body;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const hookContext = {
|
|
297
|
+
url: url,
|
|
298
|
+
method: method,
|
|
299
|
+
headers: headers,
|
|
300
|
+
body: body,
|
|
301
|
+
timestamp: Date.now(),
|
|
302
|
+
stackTrace: new Error().stack.split('\\n').slice(2, 5).join('\\n') // 简化调用栈
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
console.log('[Fetch Hook] request:', hookContext);
|
|
306
|
+
|
|
307
|
+
${action === 'block' ? 'return Promise.reject(new Error("Fetch blocked by hook"));' : ''}
|
|
308
|
+
${customCode || ''}
|
|
309
|
+
|
|
310
|
+
// 调用原始fetch
|
|
311
|
+
const startTime = performance.now();
|
|
312
|
+
|
|
313
|
+
return Reflect.apply(target, thisArg, args)
|
|
314
|
+
.then(async response => {
|
|
315
|
+
const endTime = performance.now();
|
|
316
|
+
const duration = (endTime - startTime).toFixed(2);
|
|
317
|
+
|
|
318
|
+
// Clone响应以便读取 (重要: Response只能读取一次)
|
|
319
|
+
const clonedResponse = response.clone();
|
|
320
|
+
|
|
321
|
+
// 记录响应基本信息
|
|
322
|
+
const responseInfo = {
|
|
323
|
+
url: url,
|
|
324
|
+
status: response.status,
|
|
325
|
+
statusText: response.statusText,
|
|
326
|
+
ok: response.ok,
|
|
327
|
+
redirected: response.redirected,
|
|
328
|
+
type: response.type,
|
|
329
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
330
|
+
duration: duration + 'ms'
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
console.log('[Fetch Hook] response:', responseInfo);
|
|
334
|
+
|
|
335
|
+
// 尝试读取响应内容 (根据Content-Type)
|
|
336
|
+
try {
|
|
337
|
+
const contentType = response.headers.get('content-type') || '';
|
|
338
|
+
|
|
339
|
+
if (contentType.includes('application/json')) {
|
|
340
|
+
const json = await clonedResponse.json();
|
|
341
|
+
console.log('[Fetch Hook] responseJSON:', json);
|
|
342
|
+
} else if (contentType.includes('text/')) {
|
|
343
|
+
const text = await clonedResponse.text();
|
|
344
|
+
console.log('[Fetch Hook] responseText:', text.substring(0, 500));
|
|
345
|
+
} else {
|
|
346
|
+
console.log('[Fetch Hook] response type:', contentType);
|
|
347
|
+
}
|
|
348
|
+
} catch (e) {
|
|
349
|
+
console.warn('[Fetch Hook] Failed to parse response:', e.message);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return response;
|
|
353
|
+
})
|
|
354
|
+
.catch(error => {
|
|
355
|
+
const endTime = performance.now();
|
|
356
|
+
const duration = (endTime - startTime).toFixed(2);
|
|
357
|
+
|
|
358
|
+
console.error('[Fetch Hook] error:', {
|
|
359
|
+
url: url,
|
|
360
|
+
error: error.message,
|
|
361
|
+
duration: duration + 'ms'
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
throw error;
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
console.log('[Fetch Hook] Successfully hooked window.fetch');
|
|
370
|
+
})();
|
|
371
|
+
`.trim();
|
|
372
|
+
}
|
|
373
|
+
generateWebSocketHook(action, customCode, _condition, _performance = false) {
|
|
374
|
+
return `
|
|
375
|
+
(function() {
|
|
376
|
+
'use strict';
|
|
377
|
+
|
|
378
|
+
const OriginalWebSocket = window.WebSocket;
|
|
379
|
+
let wsCounter = 0;
|
|
380
|
+
|
|
381
|
+
window.WebSocket = function(url, protocols) {
|
|
382
|
+
const wsId = ++wsCounter;
|
|
383
|
+
const connectTime = Date.now();
|
|
384
|
+
|
|
385
|
+
console.log(\`[WebSocket Hook #\${wsId}] connecting:\`, {
|
|
386
|
+
url: url,
|
|
387
|
+
protocols: protocols,
|
|
388
|
+
timestamp: new Date().toISOString()
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
${action === 'block' ? 'throw new Error("WebSocket blocked by hook");' : ''}
|
|
392
|
+
|
|
393
|
+
// 创建原始WebSocket实例
|
|
394
|
+
const ws = new OriginalWebSocket(url, protocols);
|
|
395
|
+
|
|
396
|
+
// Hook send方法
|
|
397
|
+
const originalSend = ws.send;
|
|
398
|
+
ws.send = function(data) {
|
|
399
|
+
const dataInfo = {
|
|
400
|
+
wsId: wsId,
|
|
401
|
+
url: url,
|
|
402
|
+
timestamp: new Date().toISOString(),
|
|
403
|
+
dataType: typeof data,
|
|
404
|
+
size: data?.length || data?.byteLength || data?.size || 0
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
// 根据数据类型记录内容
|
|
408
|
+
if (typeof data === 'string') {
|
|
409
|
+
dataInfo.content = data.length > 500 ? data.substring(0, 500) + '...' : data;
|
|
410
|
+
} else if (data instanceof ArrayBuffer) {
|
|
411
|
+
dataInfo.content = \`ArrayBuffer(\${data.byteLength} bytes)\`;
|
|
412
|
+
} else if (data instanceof Blob) {
|
|
413
|
+
dataInfo.content = \`Blob(\${data.size} bytes, \${data.type})\`;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
console.log(\`[WebSocket Hook #\${wsId}] send:\`, dataInfo);
|
|
417
|
+
|
|
418
|
+
${customCode || ''}
|
|
419
|
+
|
|
420
|
+
return originalSend.apply(this, arguments);
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
// Hook open事件
|
|
424
|
+
ws.addEventListener('open', function(event) {
|
|
425
|
+
const duration = Date.now() - connectTime;
|
|
426
|
+
console.log(\`[WebSocket Hook #\${wsId}] open:\`, {
|
|
427
|
+
url: url,
|
|
428
|
+
readyState: ws.readyState,
|
|
429
|
+
protocol: ws.protocol,
|
|
430
|
+
extensions: ws.extensions,
|
|
431
|
+
duration: duration + 'ms'
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
// Hook message事件
|
|
436
|
+
ws.addEventListener('message', function(event) {
|
|
437
|
+
const messageInfo = {
|
|
438
|
+
wsId: wsId,
|
|
439
|
+
url: url,
|
|
440
|
+
timestamp: new Date().toISOString(),
|
|
441
|
+
dataType: typeof event.data
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
// 根据数据类型记录内容
|
|
445
|
+
if (typeof event.data === 'string') {
|
|
446
|
+
messageInfo.content = event.data.length > 500 ? event.data.substring(0, 500) + '...' : event.data;
|
|
447
|
+
} else if (event.data instanceof ArrayBuffer) {
|
|
448
|
+
messageInfo.content = \`ArrayBuffer(\${event.data.byteLength} bytes)\`;
|
|
449
|
+
} else if (event.data instanceof Blob) {
|
|
450
|
+
messageInfo.content = \`Blob(\${event.data.size} bytes, \${event.data.type})\`;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
console.log(\`[WebSocket Hook #\${wsId}] message:\`, messageInfo);
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// Hook error事件
|
|
457
|
+
ws.addEventListener('error', function(event) {
|
|
458
|
+
console.error(\`[WebSocket Hook #\${wsId}] error:\`, {
|
|
459
|
+
url: url,
|
|
460
|
+
readyState: ws.readyState,
|
|
461
|
+
timestamp: new Date().toISOString()
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// Hook close事件
|
|
466
|
+
ws.addEventListener('close', function(event) {
|
|
467
|
+
const duration = Date.now() - connectTime;
|
|
468
|
+
console.log(\`[WebSocket Hook #\${wsId}] close:\`, {
|
|
469
|
+
url: url,
|
|
470
|
+
code: event.code,
|
|
471
|
+
reason: event.reason,
|
|
472
|
+
wasClean: event.wasClean,
|
|
473
|
+
duration: duration + 'ms',
|
|
474
|
+
timestamp: new Date().toISOString()
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
return ws;
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// 复制原始WebSocket的静态属性
|
|
482
|
+
window.WebSocket.CONNECTING = OriginalWebSocket.CONNECTING;
|
|
483
|
+
window.WebSocket.OPEN = OriginalWebSocket.OPEN;
|
|
484
|
+
window.WebSocket.CLOSING = OriginalWebSocket.CLOSING;
|
|
485
|
+
window.WebSocket.CLOSED = OriginalWebSocket.CLOSED;
|
|
486
|
+
|
|
487
|
+
console.log('[WebSocket Hook] Successfully hooked window.WebSocket');
|
|
488
|
+
})();
|
|
489
|
+
`.trim();
|
|
490
|
+
}
|
|
491
|
+
generateLocalStorageHook(action, customCode, _condition, _performance = false) {
|
|
492
|
+
return `
|
|
493
|
+
(function() {
|
|
494
|
+
'use strict';
|
|
495
|
+
|
|
496
|
+
// 保存原始方法
|
|
497
|
+
const originalSetItem = Storage.prototype.setItem;
|
|
498
|
+
const originalGetItem = Storage.prototype.getItem;
|
|
499
|
+
const originalRemoveItem = Storage.prototype.removeItem;
|
|
500
|
+
const originalClear = Storage.prototype.clear;
|
|
501
|
+
|
|
502
|
+
// Hook setItem
|
|
503
|
+
Storage.prototype.setItem = function(key, value) {
|
|
504
|
+
const storageType = this === window.localStorage ? 'localStorage' : 'sessionStorage';
|
|
505
|
+
const stackTrace = new Error().stack.split('\\n').slice(2, 4).join('\\n');
|
|
506
|
+
|
|
507
|
+
console.log(\`[Storage Hook] \${storageType}.setItem:\`, {
|
|
508
|
+
key: key,
|
|
509
|
+
value: value,
|
|
510
|
+
valueType: typeof value,
|
|
511
|
+
valueLength: value?.length || 0,
|
|
512
|
+
stackTrace: stackTrace
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
${action === 'block' ? 'return;' : ''}
|
|
516
|
+
${customCode || ''}
|
|
517
|
+
|
|
518
|
+
return originalSetItem.apply(this, arguments);
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
// Hook getItem
|
|
522
|
+
Storage.prototype.getItem = function(key) {
|
|
523
|
+
const value = originalGetItem.apply(this, arguments);
|
|
524
|
+
const storageType = this === window.localStorage ? 'localStorage' : 'sessionStorage';
|
|
525
|
+
|
|
526
|
+
console.log(\`[Storage Hook] \${storageType}.getItem:\`, {
|
|
527
|
+
key: key,
|
|
528
|
+
value: value,
|
|
529
|
+
found: value !== null
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
return value;
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
// Hook removeItem
|
|
536
|
+
Storage.prototype.removeItem = function(key) {
|
|
537
|
+
const storageType = this === window.localStorage ? 'localStorage' : 'sessionStorage';
|
|
538
|
+
const oldValue = this.getItem(key);
|
|
539
|
+
|
|
540
|
+
console.log(\`[Storage Hook] \${storageType}.removeItem:\`, {
|
|
541
|
+
key: key,
|
|
542
|
+
oldValue: oldValue
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
return originalRemoveItem.apply(this, arguments);
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
// Hook clear
|
|
549
|
+
Storage.prototype.clear = function() {
|
|
550
|
+
const storageType = this === window.localStorage ? 'localStorage' : 'sessionStorage';
|
|
551
|
+
const itemCount = this.length;
|
|
552
|
+
|
|
553
|
+
console.log(\`[Storage Hook] \${storageType}.clear:\`, {
|
|
554
|
+
itemCount: itemCount,
|
|
555
|
+
items: Object.keys(this)
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
return originalClear.apply(this, arguments);
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
console.log('[Storage Hook] Successfully hooked localStorage and sessionStorage');
|
|
562
|
+
})();
|
|
563
|
+
`.trim();
|
|
564
|
+
}
|
|
565
|
+
generateCookieHook(action, customCode, _condition, _performance = false) {
|
|
566
|
+
return `
|
|
567
|
+
(function() {
|
|
568
|
+
'use strict';
|
|
569
|
+
|
|
570
|
+
// 获取原始cookie描述符
|
|
571
|
+
const cookieDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
|
|
572
|
+
Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
|
|
573
|
+
|
|
574
|
+
if (!cookieDescriptor) {
|
|
575
|
+
console.error('[Cookie Hook] Failed to get cookie descriptor');
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
const originalGet = cookieDescriptor.get;
|
|
580
|
+
const originalSet = cookieDescriptor.set;
|
|
581
|
+
|
|
582
|
+
// 解析cookie字符串
|
|
583
|
+
function parseCookie(cookieString) {
|
|
584
|
+
const parts = cookieString.split(';')[0].split('=');
|
|
585
|
+
return {
|
|
586
|
+
name: parts[0]?.trim(),
|
|
587
|
+
value: parts[1]?.trim(),
|
|
588
|
+
raw: cookieString
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// 重新定义document.cookie
|
|
593
|
+
Object.defineProperty(document, 'cookie', {
|
|
594
|
+
get: function() {
|
|
595
|
+
const value = originalGet.call(this);
|
|
596
|
+
|
|
597
|
+
console.log('[Cookie Hook] get:', {
|
|
598
|
+
value: value,
|
|
599
|
+
cookieCount: value ? value.split(';').length : 0
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
return value;
|
|
603
|
+
},
|
|
604
|
+
set: function(value) {
|
|
605
|
+
const cookieInfo = parseCookie(value);
|
|
606
|
+
const stackTrace = new Error().stack.split('\\n').slice(2, 4).join('\\n');
|
|
607
|
+
|
|
608
|
+
console.log('[Cookie Hook] set:', {
|
|
609
|
+
name: cookieInfo.name,
|
|
610
|
+
value: cookieInfo.value,
|
|
611
|
+
raw: cookieInfo.raw,
|
|
612
|
+
stackTrace: stackTrace
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
${action === 'block' ? 'return;' : ''}
|
|
616
|
+
${customCode || ''}
|
|
617
|
+
|
|
618
|
+
return originalSet.call(this, value);
|
|
619
|
+
},
|
|
620
|
+
configurable: true
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
console.log('[Cookie Hook] Successfully hooked document.cookie');
|
|
624
|
+
})();
|
|
625
|
+
`.trim();
|
|
626
|
+
}
|
|
627
|
+
getInjectionInstructions(type) {
|
|
628
|
+
const baseInstructions = `
|
|
629
|
+
To inject this hook:
|
|
630
|
+
|
|
631
|
+
1. Open Chrome DevTools (F12)
|
|
632
|
+
2. Go to Console tab
|
|
633
|
+
3. Copy and paste the hook script
|
|
634
|
+
4. Press Enter to execute
|
|
635
|
+
|
|
636
|
+
The hook will start monitoring ${type} operations immediately.
|
|
637
|
+
`.trim();
|
|
638
|
+
return baseInstructions;
|
|
639
|
+
}
|
|
640
|
+
recordHookEvent(hookId, context) {
|
|
641
|
+
const record = {
|
|
642
|
+
hookId,
|
|
643
|
+
timestamp: Date.now(),
|
|
644
|
+
context,
|
|
645
|
+
};
|
|
646
|
+
const records = this.hooks.get(hookId) || [];
|
|
647
|
+
records.push(record);
|
|
648
|
+
this.hooks.set(hookId, records);
|
|
649
|
+
logger.debug(`Hook event recorded: ${hookId}`);
|
|
650
|
+
}
|
|
651
|
+
getHookRecords(hookId) {
|
|
652
|
+
return this.hooks.get(hookId) || [];
|
|
653
|
+
}
|
|
654
|
+
clearHookRecords(hookId) {
|
|
655
|
+
if (hookId) {
|
|
656
|
+
this.hooks.delete(hookId);
|
|
657
|
+
logger.info(`Cleared records for hook: ${hookId}`);
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
this.hooks.clear();
|
|
661
|
+
logger.info('Cleared all hook records');
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
generateEvalHook(action, customCode, _condition, _performance = false) {
|
|
665
|
+
return `
|
|
666
|
+
(function() {
|
|
667
|
+
'use strict';
|
|
668
|
+
|
|
669
|
+
// 保存原始函数
|
|
670
|
+
const originalEval = window.eval;
|
|
671
|
+
const originalFunction = window.Function;
|
|
672
|
+
const originalSetTimeout = window.setTimeout;
|
|
673
|
+
const originalSetInterval = window.setInterval;
|
|
674
|
+
|
|
675
|
+
let evalCounter = 0;
|
|
676
|
+
|
|
677
|
+
// Hook eval
|
|
678
|
+
window.eval = function(code) {
|
|
679
|
+
const evalId = ++evalCounter;
|
|
680
|
+
const stackTrace = new Error().stack.split('\\n').slice(2, 5).join('\\n');
|
|
681
|
+
|
|
682
|
+
console.log(\`[Eval Hook #\${evalId}] eval:\`, {
|
|
683
|
+
code: typeof code === 'string' ? (code.length > 200 ? code.substring(0, 200) + '...' : code) : code,
|
|
684
|
+
codeType: typeof code,
|
|
685
|
+
codeLength: code?.length || 0,
|
|
686
|
+
stackTrace: stackTrace,
|
|
687
|
+
timestamp: new Date().toISOString()
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
${action === 'block' ? 'return undefined;' : ''}
|
|
691
|
+
${customCode || ''}
|
|
692
|
+
|
|
693
|
+
try {
|
|
694
|
+
const result = originalEval.call(this, code);
|
|
695
|
+
console.log(\`[Eval Hook #\${evalId}] result:\`, typeof result);
|
|
696
|
+
return result;
|
|
697
|
+
} catch (error) {
|
|
698
|
+
console.error(\`[Eval Hook #\${evalId}] error:\`, error.message);
|
|
699
|
+
throw error;
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
|
|
703
|
+
// Hook Function constructor
|
|
704
|
+
window.Function = function(...args) {
|
|
705
|
+
const evalId = ++evalCounter;
|
|
706
|
+
const stackTrace = new Error().stack.split('\\n').slice(2, 5).join('\\n');
|
|
707
|
+
|
|
708
|
+
// Function构造函数的最后一个参数是函数体,前面的是参数名
|
|
709
|
+
const functionBody = args[args.length - 1];
|
|
710
|
+
const functionParams = args.slice(0, -1);
|
|
711
|
+
|
|
712
|
+
console.log(\`[Eval Hook #\${evalId}] Function constructor:\`, {
|
|
713
|
+
params: functionParams,
|
|
714
|
+
body: typeof functionBody === 'string' ?
|
|
715
|
+
(functionBody.length > 200 ? functionBody.substring(0, 200) + '...' : functionBody) :
|
|
716
|
+
functionBody,
|
|
717
|
+
bodyLength: functionBody?.length || 0,
|
|
718
|
+
stackTrace: stackTrace,
|
|
719
|
+
timestamp: new Date().toISOString()
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
${action === 'block' ? 'return function() {};' : ''}
|
|
723
|
+
${customCode || ''}
|
|
724
|
+
|
|
725
|
+
try {
|
|
726
|
+
const result = originalFunction.apply(this, args);
|
|
727
|
+
console.log(\`[Eval Hook #\${evalId}] Function created\`);
|
|
728
|
+
return result;
|
|
729
|
+
} catch (error) {
|
|
730
|
+
console.error(\`[Eval Hook #\${evalId}] error:\`, error.message);
|
|
731
|
+
throw error;
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
// Hook setTimeout (可以接受字符串代码)
|
|
736
|
+
window.setTimeout = function(handler, timeout, ...args) {
|
|
737
|
+
if (typeof handler === 'string') {
|
|
738
|
+
const evalId = ++evalCounter;
|
|
739
|
+
console.log(\`[Eval Hook #\${evalId}] setTimeout with code:\`, {
|
|
740
|
+
code: handler.length > 200 ? handler.substring(0, 200) + '...' : handler,
|
|
741
|
+
timeout: timeout,
|
|
742
|
+
timestamp: new Date().toISOString()
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
${action === 'block' ? 'return 0;' : ''}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
return originalSetTimeout.apply(this, [handler, timeout, ...args]);
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
// Hook setInterval (可以接受字符串代码)
|
|
752
|
+
window.setInterval = function(handler, timeout, ...args) {
|
|
753
|
+
if (typeof handler === 'string') {
|
|
754
|
+
const evalId = ++evalCounter;
|
|
755
|
+
console.log(\`[Eval Hook #\${evalId}] setInterval with code:\`, {
|
|
756
|
+
code: handler.length > 200 ? handler.substring(0, 200) + '...' : handler,
|
|
757
|
+
timeout: timeout,
|
|
758
|
+
timestamp: new Date().toISOString()
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
${action === 'block' ? 'return 0;' : ''}
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
return originalSetInterval.apply(this, [handler, timeout, ...args]);
|
|
765
|
+
};
|
|
766
|
+
|
|
767
|
+
console.log('[Eval Hook] Successfully hooked eval, Function, setTimeout, setInterval');
|
|
768
|
+
})();
|
|
769
|
+
`.trim();
|
|
770
|
+
}
|
|
771
|
+
generateObjectMethodHook(target, action, customCode, _condition, _performance = false) {
|
|
772
|
+
const parts = target.split('.');
|
|
773
|
+
const methodName = parts.pop();
|
|
774
|
+
const objectPath = parts.join('.');
|
|
775
|
+
return `
|
|
776
|
+
(function() {
|
|
777
|
+
'use strict';
|
|
778
|
+
|
|
779
|
+
// 解析对象路径
|
|
780
|
+
function getObjectByPath(path) {
|
|
781
|
+
const parts = path.split('.');
|
|
782
|
+
let obj = window;
|
|
783
|
+
|
|
784
|
+
for (const part of parts) {
|
|
785
|
+
if (part === 'window') continue;
|
|
786
|
+
if (!obj || !(part in obj)) {
|
|
787
|
+
return null;
|
|
788
|
+
}
|
|
789
|
+
obj = obj[part];
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
return obj;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const targetObject = getObjectByPath('${objectPath}');
|
|
796
|
+
const methodName = '${methodName}';
|
|
797
|
+
|
|
798
|
+
if (!targetObject) {
|
|
799
|
+
console.error('[Object Hook] Target object not found: ${objectPath}');
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// 检查是否是方法
|
|
804
|
+
const descriptor = Object.getOwnPropertyDescriptor(targetObject, methodName) ||
|
|
805
|
+
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(targetObject), methodName);
|
|
806
|
+
|
|
807
|
+
if (!descriptor) {
|
|
808
|
+
console.error('[Object Hook] Property not found: ${target}');
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
let callCounter = 0;
|
|
813
|
+
|
|
814
|
+
// 如果是普通方法
|
|
815
|
+
if (typeof targetObject[methodName] === 'function') {
|
|
816
|
+
const originalMethod = targetObject[methodName];
|
|
817
|
+
|
|
818
|
+
targetObject[methodName] = function(...args) {
|
|
819
|
+
const callId = ++callCounter;
|
|
820
|
+
const startTime = performance.now();
|
|
821
|
+
const stackTrace = new Error().stack.split('\\n').slice(2, 5).join('\\n');
|
|
822
|
+
|
|
823
|
+
console.log(\`[Object Hook #\${callId}] ${target}:\`, {
|
|
824
|
+
arguments: args,
|
|
825
|
+
this: this,
|
|
826
|
+
thisType: this?.constructor?.name,
|
|
827
|
+
stackTrace: stackTrace,
|
|
828
|
+
timestamp: new Date().toISOString()
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
${action === 'block' ? 'return undefined;' : ''}
|
|
832
|
+
${customCode || ''}
|
|
833
|
+
|
|
834
|
+
try {
|
|
835
|
+
const result = originalMethod.apply(this, args);
|
|
836
|
+
const endTime = performance.now();
|
|
837
|
+
const duration = (endTime - startTime).toFixed(2);
|
|
838
|
+
|
|
839
|
+
console.log(\`[Object Hook #\${callId}] ${target} result:\`, {
|
|
840
|
+
result: result,
|
|
841
|
+
resultType: typeof result,
|
|
842
|
+
duration: duration + 'ms'
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
return result;
|
|
846
|
+
} catch (error) {
|
|
847
|
+
console.error(\`[Object Hook #\${callId}] ${target} error:\`, error);
|
|
848
|
+
throw error;
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
// 保留原始方法的属性
|
|
853
|
+
Object.setPrototypeOf(targetObject[methodName], originalMethod);
|
|
854
|
+
|
|
855
|
+
console.log('[Object Hook] Successfully hooked method: ${target}');
|
|
856
|
+
}
|
|
857
|
+
// 如果是getter/setter
|
|
858
|
+
else if (descriptor.get || descriptor.set) {
|
|
859
|
+
const originalGet = descriptor.get;
|
|
860
|
+
const originalSet = descriptor.set;
|
|
861
|
+
|
|
862
|
+
Object.defineProperty(targetObject, methodName, {
|
|
863
|
+
get: function() {
|
|
864
|
+
console.log('[Object Hook] getter called: ${target}');
|
|
865
|
+
return originalGet ? originalGet.call(this) : undefined;
|
|
866
|
+
},
|
|
867
|
+
set: function(value) {
|
|
868
|
+
console.log('[Object Hook] setter called: ${target}', { value });
|
|
869
|
+
${action === 'block' ? 'return;' : ''}
|
|
870
|
+
if (originalSet) {
|
|
871
|
+
originalSet.call(this, value);
|
|
872
|
+
}
|
|
873
|
+
},
|
|
874
|
+
configurable: true,
|
|
875
|
+
enumerable: descriptor.enumerable
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
console.log('[Object Hook] Successfully hooked property: ${target}');
|
|
879
|
+
}
|
|
880
|
+
})();
|
|
881
|
+
`.trim();
|
|
882
|
+
}
|
|
883
|
+
enableHook(hookId) {
|
|
884
|
+
const metadata = this.hookMetadata.get(hookId);
|
|
885
|
+
if (metadata) {
|
|
886
|
+
metadata.enabled = true;
|
|
887
|
+
logger.info(`Hook enabled: ${hookId}`);
|
|
888
|
+
}
|
|
889
|
+
else {
|
|
890
|
+
logger.warn(`Hook not found: ${hookId}`);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
disableHook(hookId) {
|
|
894
|
+
const metadata = this.hookMetadata.get(hookId);
|
|
895
|
+
if (metadata) {
|
|
896
|
+
metadata.enabled = false;
|
|
897
|
+
logger.info(`Hook disabled: ${hookId}`);
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
logger.warn(`Hook not found: ${hookId}`);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
getHookMetadata(hookId) {
|
|
904
|
+
return this.hookMetadata.get(hookId);
|
|
905
|
+
}
|
|
906
|
+
getAllHookMetadata() {
|
|
907
|
+
return Array.from(this.hookMetadata.values());
|
|
908
|
+
}
|
|
909
|
+
exportHookData(hookId) {
|
|
910
|
+
if (hookId) {
|
|
911
|
+
const metadata = this.hookMetadata.get(hookId);
|
|
912
|
+
const records = this.hooks.get(hookId) || [];
|
|
913
|
+
const script = this.hookScripts.get(hookId) || '';
|
|
914
|
+
return {
|
|
915
|
+
metadata: metadata ? [metadata] : [],
|
|
916
|
+
records: { [hookId]: records },
|
|
917
|
+
scripts: { [hookId]: script },
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
const metadata = Array.from(this.hookMetadata.values());
|
|
921
|
+
const records = {};
|
|
922
|
+
const scripts = {};
|
|
923
|
+
this.hooks.forEach((value, key) => {
|
|
924
|
+
records[key] = value;
|
|
925
|
+
});
|
|
926
|
+
this.hookScripts.forEach((value, key) => {
|
|
927
|
+
scripts[key] = value;
|
|
928
|
+
});
|
|
929
|
+
return { metadata, records, scripts };
|
|
930
|
+
}
|
|
931
|
+
getHookStats(hookId) {
|
|
932
|
+
const metadata = this.hookMetadata.get(hookId);
|
|
933
|
+
if (!metadata) {
|
|
934
|
+
return null;
|
|
935
|
+
}
|
|
936
|
+
return {
|
|
937
|
+
callCount: metadata.callCount,
|
|
938
|
+
avgExecutionTime: metadata.callCount > 0 ? metadata.totalExecutionTime / metadata.callCount : 0,
|
|
939
|
+
totalExecutionTime: metadata.totalExecutionTime,
|
|
940
|
+
enabled: metadata.enabled,
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
deleteHook(hookId) {
|
|
944
|
+
this.hookScripts.delete(hookId);
|
|
945
|
+
this.hookMetadata.delete(hookId);
|
|
946
|
+
this.hookConditions.delete(hookId);
|
|
947
|
+
this.hooks.delete(hookId);
|
|
948
|
+
logger.info(`Hook deleted: ${hookId}`);
|
|
949
|
+
}
|
|
950
|
+
getAllHooks() {
|
|
951
|
+
return Array.from(this.hookScripts.keys());
|
|
952
|
+
}
|
|
953
|
+
recordHookCall(hookId, record) {
|
|
954
|
+
if (!this.hooks.has(hookId)) {
|
|
955
|
+
this.hooks.set(hookId, []);
|
|
956
|
+
}
|
|
957
|
+
const records = this.hooks.get(hookId);
|
|
958
|
+
if (records.length >= this.MAX_HOOK_RECORDS) {
|
|
959
|
+
records.shift();
|
|
960
|
+
logger.debug(`Hook ${hookId} reached max records, removed oldest`);
|
|
961
|
+
}
|
|
962
|
+
records.push(record);
|
|
963
|
+
const totalRecords = Array.from(this.hooks.values()).reduce((sum, arr) => sum + arr.length, 0);
|
|
964
|
+
if (totalRecords > this.MAX_TOTAL_RECORDS) {
|
|
965
|
+
this.cleanupOldestRecords();
|
|
966
|
+
}
|
|
967
|
+
const metadata = this.hookMetadata.get(hookId);
|
|
968
|
+
if (metadata) {
|
|
969
|
+
metadata.callCount++;
|
|
970
|
+
metadata.lastCalled = Date.now();
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
cleanupOldestRecords() {
|
|
974
|
+
let oldestHookId = null;
|
|
975
|
+
let oldestTimestamp = Infinity;
|
|
976
|
+
for (const [hookId, records] of this.hooks.entries()) {
|
|
977
|
+
if (records.length > 0) {
|
|
978
|
+
const firstRecord = records[0];
|
|
979
|
+
if (firstRecord && firstRecord.timestamp < oldestTimestamp) {
|
|
980
|
+
oldestTimestamp = firstRecord.timestamp;
|
|
981
|
+
oldestHookId = hookId;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
if (oldestHookId) {
|
|
986
|
+
const records = this.hooks.get(oldestHookId);
|
|
987
|
+
const removeCount = Math.floor(records.length / 2);
|
|
988
|
+
records.splice(0, removeCount);
|
|
989
|
+
logger.warn(`Cleaned up ${removeCount} old records from ${oldestHookId} (total records exceeded limit)`);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
getHookRecordsStats() {
|
|
993
|
+
let totalRecords = 0;
|
|
994
|
+
let oldestRecord = null;
|
|
995
|
+
let newestRecord = null;
|
|
996
|
+
const recordsByHook = {};
|
|
997
|
+
for (const [hookId, records] of this.hooks.entries()) {
|
|
998
|
+
recordsByHook[hookId] = records.length;
|
|
999
|
+
totalRecords += records.length;
|
|
1000
|
+
if (records.length > 0) {
|
|
1001
|
+
const firstRecord = records[0];
|
|
1002
|
+
const lastRecord = records[records.length - 1];
|
|
1003
|
+
if (firstRecord) {
|
|
1004
|
+
const firstTimestamp = firstRecord.timestamp;
|
|
1005
|
+
if (oldestRecord === null || firstTimestamp < oldestRecord) {
|
|
1006
|
+
oldestRecord = firstTimestamp;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
if (lastRecord) {
|
|
1010
|
+
const lastTimestamp = lastRecord.timestamp;
|
|
1011
|
+
if (newestRecord === null || lastTimestamp > newestRecord) {
|
|
1012
|
+
newestRecord = lastTimestamp;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
return {
|
|
1018
|
+
totalHooks: this.hooks.size,
|
|
1019
|
+
totalRecords,
|
|
1020
|
+
recordsByHook,
|
|
1021
|
+
oldestRecord,
|
|
1022
|
+
newestRecord,
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
generateAntiDebugBypass() {
|
|
1026
|
+
return `
|
|
1027
|
+
(function() {
|
|
1028
|
+
'use strict';
|
|
1029
|
+
|
|
1030
|
+
console.log('[Anti-Debug Bypass] Initializing...');
|
|
1031
|
+
|
|
1032
|
+
// 1. 禁用debugger语句
|
|
1033
|
+
const originalEval = window.eval;
|
|
1034
|
+
window.eval = function(code) {
|
|
1035
|
+
if (typeof code === 'string') {
|
|
1036
|
+
// 移除debugger语句
|
|
1037
|
+
code = code.replace(/debugger\\s*;?/g, '');
|
|
1038
|
+
}
|
|
1039
|
+
return originalEval.call(this, code);
|
|
1040
|
+
};
|
|
1041
|
+
|
|
1042
|
+
const originalFunction = window.Function;
|
|
1043
|
+
window.Function = function(...args) {
|
|
1044
|
+
if (args.length > 0) {
|
|
1045
|
+
const lastArg = args[args.length - 1];
|
|
1046
|
+
if (typeof lastArg === 'string') {
|
|
1047
|
+
args[args.length - 1] = lastArg.replace(/debugger\\s*;?/g, '');
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
return originalFunction.apply(this, args);
|
|
1051
|
+
};
|
|
1052
|
+
|
|
1053
|
+
// 2. 绕过DevTools检测
|
|
1054
|
+
Object.defineProperty(window, 'outerHeight', {
|
|
1055
|
+
get: function() {
|
|
1056
|
+
return window.innerHeight;
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
|
|
1060
|
+
Object.defineProperty(window, 'outerWidth', {
|
|
1061
|
+
get: function() {
|
|
1062
|
+
return window.innerWidth;
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
|
|
1066
|
+
// 3. 绕过时间差检测
|
|
1067
|
+
let lastTime = Date.now();
|
|
1068
|
+
const originalDateNow = Date.now;
|
|
1069
|
+
Date.now = function() {
|
|
1070
|
+
const currentTime = originalDateNow();
|
|
1071
|
+
// 如果时间差异过大(可能是debugger暂停),返回正常的时间增量
|
|
1072
|
+
if (currentTime - lastTime > 100) {
|
|
1073
|
+
lastTime += 16; // 模拟正常的帧时间
|
|
1074
|
+
return lastTime;
|
|
1075
|
+
}
|
|
1076
|
+
lastTime = currentTime;
|
|
1077
|
+
return currentTime;
|
|
1078
|
+
};
|
|
1079
|
+
|
|
1080
|
+
// 4. 绕过toString检测
|
|
1081
|
+
const originalToString = Function.prototype.toString;
|
|
1082
|
+
Function.prototype.toString = function() {
|
|
1083
|
+
if (this === window.eval || this === window.Function) {
|
|
1084
|
+
return 'function () { [native code] }';
|
|
1085
|
+
}
|
|
1086
|
+
return originalToString.call(this);
|
|
1087
|
+
};
|
|
1088
|
+
|
|
1089
|
+
// 5. 绕过控制台检测
|
|
1090
|
+
const devtools = { open: false };
|
|
1091
|
+
const threshold = 160;
|
|
1092
|
+
|
|
1093
|
+
setInterval(function() {
|
|
1094
|
+
if (window.outerWidth - window.innerWidth > threshold ||
|
|
1095
|
+
window.outerHeight - window.innerHeight > threshold) {
|
|
1096
|
+
devtools.open = true;
|
|
1097
|
+
} else {
|
|
1098
|
+
devtools.open = false;
|
|
1099
|
+
}
|
|
1100
|
+
}, 500);
|
|
1101
|
+
|
|
1102
|
+
// 覆盖devtools检测
|
|
1103
|
+
Object.defineProperty(window, 'devtools', {
|
|
1104
|
+
get: function() {
|
|
1105
|
+
return { open: false };
|
|
1106
|
+
}
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
console.log('[Anti-Debug Bypass] Successfully bypassed anti-debugging protections');
|
|
1110
|
+
})();
|
|
1111
|
+
`.trim();
|
|
1112
|
+
}
|
|
1113
|
+
generateHookTemplate(targetName, targetType) {
|
|
1114
|
+
if (targetType === 'function') {
|
|
1115
|
+
return `
|
|
1116
|
+
(function() {
|
|
1117
|
+
'use strict';
|
|
1118
|
+
|
|
1119
|
+
const original = ${targetName};
|
|
1120
|
+
|
|
1121
|
+
${targetName} = function(...args) {
|
|
1122
|
+
console.log('[Hook] ${targetName} called:', args);
|
|
1123
|
+
|
|
1124
|
+
// 在这里添加自定义逻辑
|
|
1125
|
+
|
|
1126
|
+
const result = original.apply(this, args);
|
|
1127
|
+
console.log('[Hook] ${targetName} result:', result);
|
|
1128
|
+
|
|
1129
|
+
return result;
|
|
1130
|
+
};
|
|
1131
|
+
|
|
1132
|
+
console.log('[Hook] Successfully hooked: ${targetName}');
|
|
1133
|
+
})();
|
|
1134
|
+
`.trim();
|
|
1135
|
+
}
|
|
1136
|
+
else if (targetType === 'property') {
|
|
1137
|
+
return `
|
|
1138
|
+
(function() {
|
|
1139
|
+
'use strict';
|
|
1140
|
+
|
|
1141
|
+
const descriptor = Object.getOwnPropertyDescriptor(${targetName.split('.').slice(0, -1).join('.')}, '${targetName.split('.').pop()}');
|
|
1142
|
+
const originalGet = descriptor?.get;
|
|
1143
|
+
const originalSet = descriptor?.set;
|
|
1144
|
+
|
|
1145
|
+
Object.defineProperty(${targetName.split('.').slice(0, -1).join('.')}, '${targetName.split('.').pop()}', {
|
|
1146
|
+
get: function() {
|
|
1147
|
+
console.log('[Hook] ${targetName} get');
|
|
1148
|
+
return originalGet ? originalGet.call(this) : undefined;
|
|
1149
|
+
},
|
|
1150
|
+
set: function(value) {
|
|
1151
|
+
console.log('[Hook] ${targetName} set:', value);
|
|
1152
|
+
if (originalSet) {
|
|
1153
|
+
originalSet.call(this, value);
|
|
1154
|
+
}
|
|
1155
|
+
},
|
|
1156
|
+
configurable: true
|
|
1157
|
+
});
|
|
1158
|
+
|
|
1159
|
+
console.log('[Hook] Successfully hooked property: ${targetName}');
|
|
1160
|
+
})();
|
|
1161
|
+
`.trim();
|
|
1162
|
+
}
|
|
1163
|
+
else {
|
|
1164
|
+
return `
|
|
1165
|
+
(function() {
|
|
1166
|
+
'use strict';
|
|
1167
|
+
|
|
1168
|
+
const original = ${targetName};
|
|
1169
|
+
|
|
1170
|
+
${targetName} = function(...args) {
|
|
1171
|
+
console.log('[Hook] ${targetName} constructor called:', args);
|
|
1172
|
+
|
|
1173
|
+
const instance = new original(...args);
|
|
1174
|
+
|
|
1175
|
+
// Hook实例方法
|
|
1176
|
+
const methodNames = Object.getOwnPropertyNames(original.prototype);
|
|
1177
|
+
methodNames.forEach(name => {
|
|
1178
|
+
if (name !== 'constructor' && typeof instance[name] === 'function') {
|
|
1179
|
+
const originalMethod = instance[name];
|
|
1180
|
+
instance[name] = function(...methodArgs) {
|
|
1181
|
+
console.log(\`[Hook] \${name} called:\`, methodArgs);
|
|
1182
|
+
return originalMethod.apply(this, methodArgs);
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
|
|
1187
|
+
return instance;
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
// 保留原型链
|
|
1191
|
+
${targetName}.prototype = original.prototype;
|
|
1192
|
+
|
|
1193
|
+
console.log('[Hook] Successfully hooked prototype: ${targetName}');
|
|
1194
|
+
})();
|
|
1195
|
+
`.trim();
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
async createBatchHooks(targets) {
|
|
1199
|
+
logger.info(`Creating ${targets.length} hooks...`);
|
|
1200
|
+
const results = [];
|
|
1201
|
+
for (const { target, type, action = 'log' } of targets) {
|
|
1202
|
+
try {
|
|
1203
|
+
const result = await this.createHook({ target, type, action });
|
|
1204
|
+
results.push(result);
|
|
1205
|
+
}
|
|
1206
|
+
catch (error) {
|
|
1207
|
+
logger.error(`Failed to create hook for ${target}:`, error);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
logger.success(`Created ${results.length}/${targets.length} hooks`);
|
|
1211
|
+
return results;
|
|
1212
|
+
}
|
|
1213
|
+
generateHookChain(hooks) {
|
|
1214
|
+
const scripts = hooks.map(h => h.script).join('\n\n');
|
|
1215
|
+
return `
|
|
1216
|
+
// Hook Chain - ${hooks.length} hooks
|
|
1217
|
+
// Generated at: ${new Date().toISOString()}
|
|
1218
|
+
|
|
1219
|
+
${scripts}
|
|
1220
|
+
|
|
1221
|
+
console.log('[Hook Chain] All ${hooks.length} hooks initialized');
|
|
1222
|
+
`.trim();
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
//# sourceMappingURL=HookManager.js.map
|