@jshookmcp/jshook 0.2.2 → 0.2.3
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/LICENSE +661 -661
- package/README.md +4 -4
- package/README.zh.md +3 -3
- package/dist/native/scripts/linux/enum-windows.sh +12 -12
- package/dist/native/scripts/macos/enum-windows.applescript +22 -22
- package/dist/native/scripts/windows/enum-windows-by-class.ps1 +51 -51
- package/dist/native/scripts/windows/enum-windows.ps1 +44 -44
- package/dist/native/scripts/windows/inject-dll.ps1 +21 -21
- package/dist/src/modules/analyzer/CodeAnalyzer.d.ts +1 -1
- package/dist/src/modules/analyzer/CodeAnalyzer.js +1 -1
- package/dist/src/modules/browser/BrowserDiscovery.d.ts +6 -5
- package/dist/src/modules/browser/BrowserDiscovery.js +1 -1
- package/dist/src/modules/browser/BrowserModeManager.d.ts +1 -1
- package/dist/src/modules/browser/BrowserModeManager.js +1 -1
- package/dist/src/modules/browser/UnifiedBrowserManager.js +1 -1
- package/dist/src/modules/captcha/AICaptchaDetector.d.ts +22 -22
- package/dist/src/modules/captcha/AICaptchaDetector.js +75 -75
- package/dist/src/modules/captcha/CaptchaDetector.d.ts +31 -17
- package/dist/src/modules/captcha/CaptchaDetector.js +1 -1
- package/dist/src/modules/collector/CodeCache.d.ts +2 -2
- package/dist/src/modules/collector/CodeCollector.d.ts +12 -9
- package/dist/src/modules/collector/CodeCollector.js +1 -1
- package/dist/src/modules/collector/DOMInspector.d.ts +3 -2
- package/dist/src/modules/collector/DOMInspector.js +1 -1
- package/dist/src/modules/crypto/CryptoDetector.d.ts +1 -1
- package/dist/src/modules/crypto/CryptoDetector.js +1 -1
- package/dist/src/modules/debugger/ScriptManager.impl.extract-function-tree.js +1 -1
- package/dist/src/modules/deobfuscator/Deobfuscator.d.ts +1 -1
- package/dist/src/modules/deobfuscator/Deobfuscator.js +1 -1
- package/dist/src/modules/deobfuscator/JSVMPDeobfuscator.restore.d.ts +1 -1
- package/dist/src/modules/deobfuscator/JSVMPDeobfuscator.restore.js +2 -2
- package/dist/src/modules/deobfuscator/PackerDeobfuscator.js +1 -1
- package/dist/src/modules/deobfuscator/VMDeobfuscator.d.ts +1 -1
- package/dist/src/modules/deobfuscator/VMDeobfuscator.js +82 -82
- package/dist/src/modules/emulator/AIEnvironmentAnalyzer.js +1 -1
- package/dist/src/modules/external/ExternalToolRunner.d.ts +1 -1
- package/dist/src/modules/external/ExternalToolRunner.js +1 -1
- package/dist/src/modules/hook/HookGeneratorBuilders.core.generators.compose.js +5 -5
- package/dist/src/modules/hook/HookGeneratorBuilders.core.generators.network.js +311 -311
- package/dist/src/modules/hook/HookGeneratorBuilders.core.generators.runtime.js +410 -410
- package/dist/src/modules/hook/HookGeneratorBuilders.core.generators.storage.js +122 -122
- package/dist/src/modules/monitor/ConsoleMonitor.impl.core.dynamic.js +194 -194
- package/dist/src/modules/monitor/PlaywrightNetworkMonitor.js +62 -62
- package/dist/src/modules/process/LinuxProcessManager.js +2 -2
- package/dist/src/modules/process/MacProcessManager.js +26 -26
- package/dist/src/modules/process/ProcessManager.impl.js +1 -1
- package/dist/src/modules/process/memory/availability.js +49 -49
- package/dist/src/modules/process/memory/injector.js +185 -185
- package/dist/src/modules/process/memory/reader.js +50 -50
- package/dist/src/modules/process/memory/regions.dump.js +51 -51
- package/dist/src/modules/process/memory/regions.enumerate.js +107 -107
- package/dist/src/modules/process/memory/regions.modules.js +80 -80
- package/dist/src/modules/process/memory/regions.protection.js +106 -106
- package/dist/src/modules/process/memory/scanner.darwin.js +41 -41
- package/dist/src/modules/process/memory/scanner.windows.js +124 -124
- package/dist/src/modules/process/memory/writer.js +54 -54
- package/dist/src/modules/security/ExecutionSandbox.js +44 -44
- package/dist/src/modules/stealth/StealthScripts.d.ts +3 -2
- package/dist/src/modules/stealth/StealthScripts.js +35 -1
- package/dist/src/modules/stealth/StealthVerifier.d.ts +1 -1
- package/dist/src/modules/stealth/StealthVerifier.js +1 -1
- package/dist/src/modules/trace/TraceDB.js +63 -63
- package/dist/src/native/CodeInjector.js +1 -1
- package/dist/src/native/HardwareBreakpoint.js +1 -1
- package/dist/src/server/MCPServer.js +1 -0
- package/dist/src/server/MCPServer.search.helpers.js +1 -1
- package/dist/src/server/MCPServer.tools.js +1 -1
- package/dist/src/server/ToolCallContextGuard.d.ts +5 -0
- package/dist/src/server/ToolCallContextGuard.js +77 -0
- package/dist/src/server/ToolRouter.d.ts +1 -1
- package/dist/src/server/ToolRouter.js +2 -2
- package/dist/src/server/domains/analysis/handlers.impl.d.ts +8 -8
- package/dist/src/server/domains/analysis/handlers.impl.js +8 -8
- package/dist/src/server/domains/analysis/handlers.web-tools.js +2 -2
- package/dist/src/server/domains/browser/definitions.tools.page-core.js +59 -59
- package/dist/src/server/domains/browser/definitions.tools.runtime.js +41 -41
- package/dist/src/server/domains/browser/definitions.tools.security.js +114 -114
- package/dist/src/server/domains/browser/handlers/facade-initializer.d.ts +3 -3
- package/dist/src/server/domains/browser/handlers/facade-initializer.js +3 -3
- package/dist/src/server/domains/browser/handlers/framework-state.js +210 -0
- package/dist/src/server/domains/browser/handlers/stealth-injection.js +8 -2
- package/dist/src/server/domains/browser/handlers.impl.d.ts +15 -11
- package/dist/src/server/domains/browser/handlers.impl.js +4 -4
- package/dist/src/server/domains/coordination/definitions.js +67 -0
- package/dist/src/server/domains/coordination/index.d.ts +18 -0
- package/dist/src/server/domains/coordination/index.js +132 -0
- package/dist/src/server/domains/coordination/manifest.js +15 -0
- package/dist/src/server/domains/graphql/handlers.impl.core.runtime.replay.js +2 -2
- package/dist/src/server/domains/graphql/handlers.impl.core.runtime.shared.js +77 -77
- package/dist/src/server/domains/hooks/ai-handlers.js +3 -3
- package/dist/src/server/domains/maintenance/handlers.d.ts +2 -2
- package/dist/src/server/domains/maintenance/handlers.js +2 -2
- package/dist/src/server/domains/platform/handlers/bridge-handlers.d.ts +1 -1
- package/dist/src/server/domains/platform/handlers/bridge-handlers.js +1 -1
- package/dist/src/server/domains/platform/handlers/miniapp-handlers.d.ts +1 -1
- package/dist/src/server/domains/platform/handlers/miniapp-handlers.js +1 -1
- package/dist/src/server/domains/process/handlers.impl.core.runtime.inject.js +1 -1
- package/dist/src/server/domains/trace/TraceSummarizer.d.ts +60 -0
- package/dist/src/server/domains/trace/TraceSummarizer.js +109 -0
- package/dist/src/server/domains/trace/definitions.tools.js +101 -71
- package/dist/src/server/domains/trace/handlers.d.ts +2 -1
- package/dist/src/server/domains/trace/handlers.js +59 -4
- package/dist/src/server/domains/trace/manifest.js +3 -1
- package/dist/src/server/domains/transform/handlers.impl.transform-base.js +103 -103
- package/dist/src/server/domains/wasm/handlers.js +2 -2
- package/dist/src/server/domains/workflow/handlers.impl.workflow-account-bundle.js +1 -1
- package/dist/src/server/domains/workflow/handlers.impl.workflow-api.js +51 -51
- package/dist/src/server/domains/workflow/handlers.impl.workflow-base.js +51 -51
- package/dist/src/server/extensions/ExtensionManager.roots.js +15 -5
- package/dist/src/server/http/HttpMiddleware.js +1 -1
- package/dist/src/server/registry/contracts.d.ts +6 -0
- package/dist/src/server/sandbox/MCPBridge.d.ts +9 -0
- package/dist/src/server/sandbox/MCPBridge.js +22 -0
- package/dist/src/server/sandbox/QuickJSSandbox.d.ts +4 -1
- package/dist/src/server/sandbox/QuickJSSandbox.js +149 -0
- package/dist/src/server/sandbox/SandboxHelpers.js +250 -250
- package/dist/src/server/sandbox/types.d.ts +13 -0
- package/dist/src/server/search/AffinityGraph.d.ts +7 -1
- package/dist/src/server/search/AffinityGraph.js +24 -3
- package/dist/src/services/LLMService.js +1 -1
- package/dist/src/utils/UnifiedCacheManager.d.ts +1 -1
- package/dist/src/utils/UnifiedCacheManager.js +2 -2
- package/dist/src/utils/cliFastPath.js +18 -4
- package/package.json +5 -3
- package/scripts/postinstall.cjs +37 -37
- package/src/native/scripts/linux/enum-windows.sh +12 -12
- package/src/native/scripts/macos/enum-windows.applescript +22 -22
- package/src/native/scripts/windows/enum-windows-by-class.ps1 +51 -51
- package/src/native/scripts/windows/enum-windows.ps1 +44 -44
- package/src/native/scripts/windows/inject-dll.ps1 +21 -21
|
@@ -1,320 +1,320 @@
|
|
|
1
1
|
export function generateXHRHook(action, customCode, _condition, _performance = false) {
|
|
2
|
-
return `
|
|
3
|
-
(function() {
|
|
4
|
-
'use strict';
|
|
5
|
-
|
|
6
|
-
const XHR = XMLHttpRequest.prototype;
|
|
7
|
-
const originalOpen = XHR.open;
|
|
8
|
-
const originalSend = XHR.send;
|
|
9
|
-
const originalSetRequestHeader = XHR.setRequestHeader;
|
|
10
|
-
|
|
11
|
-
XHR.open = function(method, url, async, user, password) {
|
|
12
|
-
this._hookData = {
|
|
13
|
-
method: method,
|
|
14
|
-
url: url,
|
|
15
|
-
async: async !== false,
|
|
16
|
-
timestamp: Date.now(),
|
|
17
|
-
headers: {},
|
|
18
|
-
stackTrace: new Error().stack
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
console.log('[XHR Hook] open:', {
|
|
22
|
-
method: method,
|
|
23
|
-
url: url,
|
|
24
|
-
async: async !== false
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
${action === 'block' ? 'return;' : ''}
|
|
28
|
-
|
|
29
|
-
return originalOpen.apply(this, arguments);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
XHR.setRequestHeader = function(header, value) {
|
|
33
|
-
if (this._hookData) {
|
|
34
|
-
this._hookData.headers[header] = value;
|
|
35
|
-
console.log('[XHR Hook] setRequestHeader:', { header, value });
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return originalSetRequestHeader.apply(this, arguments);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
XHR.send = function(data) {
|
|
42
|
-
const xhr = this;
|
|
43
|
-
|
|
44
|
-
if (xhr._hookData) {
|
|
45
|
-
xhr._hookData.requestData = data;
|
|
46
|
-
xhr._hookData.sendTime = Date.now();
|
|
47
|
-
|
|
48
|
-
console.log('[XHR Hook] send:', {
|
|
49
|
-
url: xhr._hookData.url,
|
|
50
|
-
method: xhr._hookData.method,
|
|
51
|
-
headers: xhr._hookData.headers,
|
|
52
|
-
data: data
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const originalOnReadyStateChange = xhr.onreadystatechange;
|
|
57
|
-
|
|
58
|
-
xhr.onreadystatechange = function() {
|
|
59
|
-
if (xhr.readyState === 4) {
|
|
60
|
-
const responseTime = Date.now() - (xhr._hookData?.sendTime || 0);
|
|
61
|
-
|
|
62
|
-
console.log('[XHR Hook] response:', {
|
|
63
|
-
url: xhr._hookData?.url,
|
|
64
|
-
status: xhr.status,
|
|
65
|
-
statusText: xhr.statusText,
|
|
66
|
-
responseTime: responseTime + 'ms',
|
|
67
|
-
responseHeaders: xhr.getAllResponseHeaders(),
|
|
68
|
-
responseType: xhr.responseType,
|
|
69
|
-
responseURL: xhr.responseURL
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
if (xhr.responseType === '' || xhr.responseType === 'text') {
|
|
74
|
-
console.log('[XHR Hook] responseText:', xhr.responseText?.substring(0, 500));
|
|
75
|
-
} else if (xhr.responseType === 'json') {
|
|
76
|
-
console.log('[XHR Hook] responseJSON:', xhr.response);
|
|
77
|
-
} else {
|
|
78
|
-
console.log('[XHR Hook] response:', typeof xhr.response);
|
|
79
|
-
}
|
|
80
|
-
} catch (e) {
|
|
81
|
-
console.warn('[XHR Hook] Failed to log response:', e);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (originalOnReadyStateChange) {
|
|
86
|
-
return originalOnReadyStateChange.apply(this, arguments);
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const originalAddEventListener = xhr.addEventListener;
|
|
91
|
-
xhr.addEventListener = function(event, listener, ...args) {
|
|
92
|
-
if (event === 'load' || event === 'error' || event === 'abort') {
|
|
93
|
-
const wrappedListener = function(e) {
|
|
94
|
-
console.log(\`[XHR Hook] event '\${event}':\`, {
|
|
95
|
-
url: xhr._hookData?.url,
|
|
96
|
-
status: xhr.status
|
|
97
|
-
});
|
|
98
|
-
return listener.apply(this, arguments);
|
|
99
|
-
};
|
|
100
|
-
return originalAddEventListener.call(this, event, wrappedListener, ...args);
|
|
101
|
-
}
|
|
102
|
-
return originalAddEventListener.apply(this, arguments);
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
${customCode || ''}
|
|
106
|
-
|
|
107
|
-
return originalSend.apply(this, arguments);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
console.log('[Hook] XHR hooked successfully');
|
|
111
|
-
})();
|
|
2
|
+
return `
|
|
3
|
+
(function() {
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const XHR = XMLHttpRequest.prototype;
|
|
7
|
+
const originalOpen = XHR.open;
|
|
8
|
+
const originalSend = XHR.send;
|
|
9
|
+
const originalSetRequestHeader = XHR.setRequestHeader;
|
|
10
|
+
|
|
11
|
+
XHR.open = function(method, url, async, user, password) {
|
|
12
|
+
this._hookData = {
|
|
13
|
+
method: method,
|
|
14
|
+
url: url,
|
|
15
|
+
async: async !== false,
|
|
16
|
+
timestamp: Date.now(),
|
|
17
|
+
headers: {},
|
|
18
|
+
stackTrace: new Error().stack
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
console.log('[XHR Hook] open:', {
|
|
22
|
+
method: method,
|
|
23
|
+
url: url,
|
|
24
|
+
async: async !== false
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
${action === 'block' ? 'return;' : ''}
|
|
28
|
+
|
|
29
|
+
return originalOpen.apply(this, arguments);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
XHR.setRequestHeader = function(header, value) {
|
|
33
|
+
if (this._hookData) {
|
|
34
|
+
this._hookData.headers[header] = value;
|
|
35
|
+
console.log('[XHR Hook] setRequestHeader:', { header, value });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return originalSetRequestHeader.apply(this, arguments);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
XHR.send = function(data) {
|
|
42
|
+
const xhr = this;
|
|
43
|
+
|
|
44
|
+
if (xhr._hookData) {
|
|
45
|
+
xhr._hookData.requestData = data;
|
|
46
|
+
xhr._hookData.sendTime = Date.now();
|
|
47
|
+
|
|
48
|
+
console.log('[XHR Hook] send:', {
|
|
49
|
+
url: xhr._hookData.url,
|
|
50
|
+
method: xhr._hookData.method,
|
|
51
|
+
headers: xhr._hookData.headers,
|
|
52
|
+
data: data
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const originalOnReadyStateChange = xhr.onreadystatechange;
|
|
57
|
+
|
|
58
|
+
xhr.onreadystatechange = function() {
|
|
59
|
+
if (xhr.readyState === 4) {
|
|
60
|
+
const responseTime = Date.now() - (xhr._hookData?.sendTime || 0);
|
|
61
|
+
|
|
62
|
+
console.log('[XHR Hook] response:', {
|
|
63
|
+
url: xhr._hookData?.url,
|
|
64
|
+
status: xhr.status,
|
|
65
|
+
statusText: xhr.statusText,
|
|
66
|
+
responseTime: responseTime + 'ms',
|
|
67
|
+
responseHeaders: xhr.getAllResponseHeaders(),
|
|
68
|
+
responseType: xhr.responseType,
|
|
69
|
+
responseURL: xhr.responseURL
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
if (xhr.responseType === '' || xhr.responseType === 'text') {
|
|
74
|
+
console.log('[XHR Hook] responseText:', xhr.responseText?.substring(0, 500));
|
|
75
|
+
} else if (xhr.responseType === 'json') {
|
|
76
|
+
console.log('[XHR Hook] responseJSON:', xhr.response);
|
|
77
|
+
} else {
|
|
78
|
+
console.log('[XHR Hook] response:', typeof xhr.response);
|
|
79
|
+
}
|
|
80
|
+
} catch (e) {
|
|
81
|
+
console.warn('[XHR Hook] Failed to log response:', e);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (originalOnReadyStateChange) {
|
|
86
|
+
return originalOnReadyStateChange.apply(this, arguments);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const originalAddEventListener = xhr.addEventListener;
|
|
91
|
+
xhr.addEventListener = function(event, listener, ...args) {
|
|
92
|
+
if (event === 'load' || event === 'error' || event === 'abort') {
|
|
93
|
+
const wrappedListener = function(e) {
|
|
94
|
+
console.log(\`[XHR Hook] event '\${event}':\`, {
|
|
95
|
+
url: xhr._hookData?.url,
|
|
96
|
+
status: xhr.status
|
|
97
|
+
});
|
|
98
|
+
return listener.apply(this, arguments);
|
|
99
|
+
};
|
|
100
|
+
return originalAddEventListener.call(this, event, wrappedListener, ...args);
|
|
101
|
+
}
|
|
102
|
+
return originalAddEventListener.apply(this, arguments);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
${customCode || ''}
|
|
106
|
+
|
|
107
|
+
return originalSend.apply(this, arguments);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
console.log('[Hook] XHR hooked successfully');
|
|
111
|
+
})();
|
|
112
112
|
`.trim();
|
|
113
113
|
}
|
|
114
114
|
export function generateFetchHook(action, customCode, _condition, _performance = false) {
|
|
115
|
-
return `
|
|
116
|
-
(function() {
|
|
117
|
-
'use strict';
|
|
118
|
-
|
|
119
|
-
const originalFetch = window.fetch;
|
|
120
|
-
|
|
121
|
-
window.fetch = new Proxy(originalFetch, {
|
|
122
|
-
apply: function(target, thisArg, args) {
|
|
123
|
-
const [resource, config] = args;
|
|
124
|
-
|
|
125
|
-
let url, method, headers, body;
|
|
126
|
-
|
|
127
|
-
if (resource instanceof Request) {
|
|
128
|
-
url = resource.url;
|
|
129
|
-
method = resource.method;
|
|
130
|
-
headers = Object.fromEntries(resource.headers.entries());
|
|
131
|
-
body = resource.body;
|
|
132
|
-
} else {
|
|
133
|
-
url = resource;
|
|
134
|
-
method = config?.method || 'GET';
|
|
135
|
-
headers = config?.headers || {};
|
|
136
|
-
body = config?.body;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const hookContext = {
|
|
140
|
-
url: url,
|
|
141
|
-
method: method,
|
|
142
|
-
headers: headers,
|
|
143
|
-
body: body,
|
|
144
|
-
timestamp: Date.now(),
|
|
145
|
-
stackTrace: new Error().stack.split('\\n').slice(2, 5).join('\\n')
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
console.log('[Fetch Hook] request:', hookContext);
|
|
149
|
-
|
|
150
|
-
${action === 'block' ? 'return Promise.reject(new Error("Fetch blocked by hook"));' : ''}
|
|
151
|
-
${customCode || ''}
|
|
152
|
-
|
|
153
|
-
const startTime = performance.now();
|
|
154
|
-
|
|
155
|
-
return Reflect.apply(target, thisArg, args)
|
|
156
|
-
.then(async response => {
|
|
157
|
-
const endTime = performance.now();
|
|
158
|
-
const duration = (endTime - startTime).toFixed(2);
|
|
159
|
-
|
|
160
|
-
const clonedResponse = response.clone();
|
|
161
|
-
|
|
162
|
-
const responseInfo = {
|
|
163
|
-
url: url,
|
|
164
|
-
status: response.status,
|
|
165
|
-
statusText: response.statusText,
|
|
166
|
-
ok: response.ok,
|
|
167
|
-
redirected: response.redirected,
|
|
168
|
-
type: response.type,
|
|
169
|
-
headers: Object.fromEntries(response.headers.entries()),
|
|
170
|
-
duration: duration + 'ms'
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
console.log('[Fetch Hook] response:', responseInfo);
|
|
174
|
-
|
|
175
|
-
try {
|
|
176
|
-
const contentType = response.headers.get('content-type') || '';
|
|
177
|
-
|
|
178
|
-
if (contentType.includes('application/json')) {
|
|
179
|
-
const json = await clonedResponse.json();
|
|
180
|
-
console.log('[Fetch Hook] responseJSON:', json);
|
|
181
|
-
} else if (contentType.includes('text/')) {
|
|
182
|
-
const text = await clonedResponse.text();
|
|
183
|
-
console.log('[Fetch Hook] responseText:', text.substring(0, 500));
|
|
184
|
-
} else {
|
|
185
|
-
console.log('[Fetch Hook] response type:', contentType);
|
|
186
|
-
}
|
|
187
|
-
} catch (e) {
|
|
188
|
-
console.warn('[Fetch Hook] Failed to parse response:', e.message);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return response;
|
|
192
|
-
})
|
|
193
|
-
.catch(error => {
|
|
194
|
-
const endTime = performance.now();
|
|
195
|
-
const duration = (endTime - startTime).toFixed(2);
|
|
196
|
-
|
|
197
|
-
console.error('[Fetch Hook] error:', {
|
|
198
|
-
url: url,
|
|
199
|
-
error: error.message,
|
|
200
|
-
duration: duration + 'ms'
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
throw error;
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
console.log('[Fetch Hook] Successfully hooked window.fetch');
|
|
209
|
-
})();
|
|
115
|
+
return `
|
|
116
|
+
(function() {
|
|
117
|
+
'use strict';
|
|
118
|
+
|
|
119
|
+
const originalFetch = window.fetch;
|
|
120
|
+
|
|
121
|
+
window.fetch = new Proxy(originalFetch, {
|
|
122
|
+
apply: function(target, thisArg, args) {
|
|
123
|
+
const [resource, config] = args;
|
|
124
|
+
|
|
125
|
+
let url, method, headers, body;
|
|
126
|
+
|
|
127
|
+
if (resource instanceof Request) {
|
|
128
|
+
url = resource.url;
|
|
129
|
+
method = resource.method;
|
|
130
|
+
headers = Object.fromEntries(resource.headers.entries());
|
|
131
|
+
body = resource.body;
|
|
132
|
+
} else {
|
|
133
|
+
url = resource;
|
|
134
|
+
method = config?.method || 'GET';
|
|
135
|
+
headers = config?.headers || {};
|
|
136
|
+
body = config?.body;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const hookContext = {
|
|
140
|
+
url: url,
|
|
141
|
+
method: method,
|
|
142
|
+
headers: headers,
|
|
143
|
+
body: body,
|
|
144
|
+
timestamp: Date.now(),
|
|
145
|
+
stackTrace: new Error().stack.split('\\n').slice(2, 5).join('\\n')
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
console.log('[Fetch Hook] request:', hookContext);
|
|
149
|
+
|
|
150
|
+
${action === 'block' ? 'return Promise.reject(new Error("Fetch blocked by hook"));' : ''}
|
|
151
|
+
${customCode || ''}
|
|
152
|
+
|
|
153
|
+
const startTime = performance.now();
|
|
154
|
+
|
|
155
|
+
return Reflect.apply(target, thisArg, args)
|
|
156
|
+
.then(async response => {
|
|
157
|
+
const endTime = performance.now();
|
|
158
|
+
const duration = (endTime - startTime).toFixed(2);
|
|
159
|
+
|
|
160
|
+
const clonedResponse = response.clone();
|
|
161
|
+
|
|
162
|
+
const responseInfo = {
|
|
163
|
+
url: url,
|
|
164
|
+
status: response.status,
|
|
165
|
+
statusText: response.statusText,
|
|
166
|
+
ok: response.ok,
|
|
167
|
+
redirected: response.redirected,
|
|
168
|
+
type: response.type,
|
|
169
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
170
|
+
duration: duration + 'ms'
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
console.log('[Fetch Hook] response:', responseInfo);
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
const contentType = response.headers.get('content-type') || '';
|
|
177
|
+
|
|
178
|
+
if (contentType.includes('application/json')) {
|
|
179
|
+
const json = await clonedResponse.json();
|
|
180
|
+
console.log('[Fetch Hook] responseJSON:', json);
|
|
181
|
+
} else if (contentType.includes('text/')) {
|
|
182
|
+
const text = await clonedResponse.text();
|
|
183
|
+
console.log('[Fetch Hook] responseText:', text.substring(0, 500));
|
|
184
|
+
} else {
|
|
185
|
+
console.log('[Fetch Hook] response type:', contentType);
|
|
186
|
+
}
|
|
187
|
+
} catch (e) {
|
|
188
|
+
console.warn('[Fetch Hook] Failed to parse response:', e.message);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return response;
|
|
192
|
+
})
|
|
193
|
+
.catch(error => {
|
|
194
|
+
const endTime = performance.now();
|
|
195
|
+
const duration = (endTime - startTime).toFixed(2);
|
|
196
|
+
|
|
197
|
+
console.error('[Fetch Hook] error:', {
|
|
198
|
+
url: url,
|
|
199
|
+
error: error.message,
|
|
200
|
+
duration: duration + 'ms'
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
throw error;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
console.log('[Fetch Hook] Successfully hooked window.fetch');
|
|
209
|
+
})();
|
|
210
210
|
`.trim();
|
|
211
211
|
}
|
|
212
212
|
export function generateWebSocketHook(action, customCode, _condition, _performance = false) {
|
|
213
|
-
return `
|
|
214
|
-
(function() {
|
|
215
|
-
'use strict';
|
|
216
|
-
|
|
217
|
-
const OriginalWebSocket = window.WebSocket;
|
|
218
|
-
let wsCounter = 0;
|
|
219
|
-
|
|
220
|
-
window.WebSocket = function(url, protocols) {
|
|
221
|
-
const wsId = ++wsCounter;
|
|
222
|
-
const connectTime = Date.now();
|
|
223
|
-
|
|
224
|
-
console.log(\`[WebSocket Hook #\${wsId}] connecting:\`, {
|
|
225
|
-
url: url,
|
|
226
|
-
protocols: protocols,
|
|
227
|
-
timestamp: new Date().toISOString()
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
${action === 'block' ? 'throw new Error("WebSocket blocked by hook");' : ''}
|
|
231
|
-
|
|
232
|
-
const ws = new OriginalWebSocket(url, protocols);
|
|
233
|
-
|
|
234
|
-
const originalSend = ws.send;
|
|
235
|
-
ws.send = function(data) {
|
|
236
|
-
const dataInfo = {
|
|
237
|
-
wsId: wsId,
|
|
238
|
-
url: url,
|
|
239
|
-
timestamp: new Date().toISOString(),
|
|
240
|
-
dataType: typeof data,
|
|
241
|
-
size: data?.length || data?.byteLength || data?.size || 0
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
if (typeof data === 'string') {
|
|
245
|
-
dataInfo.content = data.length > 500 ? data.substring(0, 500) + '...' : data;
|
|
246
|
-
} else if (data instanceof ArrayBuffer) {
|
|
247
|
-
dataInfo.content = \`ArrayBuffer(\${data.byteLength} bytes)\`;
|
|
248
|
-
} else if (data instanceof Blob) {
|
|
249
|
-
dataInfo.content = \`Blob(\${data.size} bytes, \${data.type})\`;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
console.log(\`[WebSocket Hook #\${wsId}] send:\`, dataInfo);
|
|
253
|
-
|
|
254
|
-
${customCode || ''}
|
|
255
|
-
|
|
256
|
-
return originalSend.apply(this, arguments);
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
ws.addEventListener('open', function(event) {
|
|
260
|
-
const duration = Date.now() - connectTime;
|
|
261
|
-
console.log(\`[WebSocket Hook #\${wsId}] open:\`, {
|
|
262
|
-
url: url,
|
|
263
|
-
readyState: ws.readyState,
|
|
264
|
-
protocol: ws.protocol,
|
|
265
|
-
extensions: ws.extensions,
|
|
266
|
-
duration: duration + 'ms'
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
ws.addEventListener('message', function(event) {
|
|
271
|
-
const messageInfo = {
|
|
272
|
-
wsId: wsId,
|
|
273
|
-
url: url,
|
|
274
|
-
timestamp: new Date().toISOString(),
|
|
275
|
-
dataType: typeof event.data
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
if (typeof event.data === 'string') {
|
|
279
|
-
messageInfo.content = event.data.length > 500 ? event.data.substring(0, 500) + '...' : event.data;
|
|
280
|
-
} else if (event.data instanceof ArrayBuffer) {
|
|
281
|
-
messageInfo.content = \`ArrayBuffer(\${event.data.byteLength} bytes)\`;
|
|
282
|
-
} else if (event.data instanceof Blob) {
|
|
283
|
-
messageInfo.content = \`Blob(\${event.data.size} bytes, \${event.data.type})\`;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
console.log(\`[WebSocket Hook #\${wsId}] message:\`, messageInfo);
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
ws.addEventListener('error', function(event) {
|
|
290
|
-
console.error(\`[WebSocket Hook #\${wsId}] error:\`, {
|
|
291
|
-
url: url,
|
|
292
|
-
readyState: ws.readyState,
|
|
293
|
-
timestamp: new Date().toISOString()
|
|
294
|
-
});
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
ws.addEventListener('close', function(event) {
|
|
298
|
-
const duration = Date.now() - connectTime;
|
|
299
|
-
console.log(\`[WebSocket Hook #\${wsId}] close:\`, {
|
|
300
|
-
url: url,
|
|
301
|
-
code: event.code,
|
|
302
|
-
reason: event.reason,
|
|
303
|
-
wasClean: event.wasClean,
|
|
304
|
-
duration: duration + 'ms',
|
|
305
|
-
timestamp: new Date().toISOString()
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
return ws;
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
window.WebSocket.CONNECTING = OriginalWebSocket.CONNECTING;
|
|
313
|
-
window.WebSocket.OPEN = OriginalWebSocket.OPEN;
|
|
314
|
-
window.WebSocket.CLOSING = OriginalWebSocket.CLOSING;
|
|
315
|
-
window.WebSocket.CLOSED = OriginalWebSocket.CLOSED;
|
|
316
|
-
|
|
317
|
-
console.log('[WebSocket Hook] Successfully hooked window.WebSocket');
|
|
318
|
-
})();
|
|
213
|
+
return `
|
|
214
|
+
(function() {
|
|
215
|
+
'use strict';
|
|
216
|
+
|
|
217
|
+
const OriginalWebSocket = window.WebSocket;
|
|
218
|
+
let wsCounter = 0;
|
|
219
|
+
|
|
220
|
+
window.WebSocket = function(url, protocols) {
|
|
221
|
+
const wsId = ++wsCounter;
|
|
222
|
+
const connectTime = Date.now();
|
|
223
|
+
|
|
224
|
+
console.log(\`[WebSocket Hook #\${wsId}] connecting:\`, {
|
|
225
|
+
url: url,
|
|
226
|
+
protocols: protocols,
|
|
227
|
+
timestamp: new Date().toISOString()
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
${action === 'block' ? 'throw new Error("WebSocket blocked by hook");' : ''}
|
|
231
|
+
|
|
232
|
+
const ws = new OriginalWebSocket(url, protocols);
|
|
233
|
+
|
|
234
|
+
const originalSend = ws.send;
|
|
235
|
+
ws.send = function(data) {
|
|
236
|
+
const dataInfo = {
|
|
237
|
+
wsId: wsId,
|
|
238
|
+
url: url,
|
|
239
|
+
timestamp: new Date().toISOString(),
|
|
240
|
+
dataType: typeof data,
|
|
241
|
+
size: data?.length || data?.byteLength || data?.size || 0
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
if (typeof data === 'string') {
|
|
245
|
+
dataInfo.content = data.length > 500 ? data.substring(0, 500) + '...' : data;
|
|
246
|
+
} else if (data instanceof ArrayBuffer) {
|
|
247
|
+
dataInfo.content = \`ArrayBuffer(\${data.byteLength} bytes)\`;
|
|
248
|
+
} else if (data instanceof Blob) {
|
|
249
|
+
dataInfo.content = \`Blob(\${data.size} bytes, \${data.type})\`;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
console.log(\`[WebSocket Hook #\${wsId}] send:\`, dataInfo);
|
|
253
|
+
|
|
254
|
+
${customCode || ''}
|
|
255
|
+
|
|
256
|
+
return originalSend.apply(this, arguments);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
ws.addEventListener('open', function(event) {
|
|
260
|
+
const duration = Date.now() - connectTime;
|
|
261
|
+
console.log(\`[WebSocket Hook #\${wsId}] open:\`, {
|
|
262
|
+
url: url,
|
|
263
|
+
readyState: ws.readyState,
|
|
264
|
+
protocol: ws.protocol,
|
|
265
|
+
extensions: ws.extensions,
|
|
266
|
+
duration: duration + 'ms'
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
ws.addEventListener('message', function(event) {
|
|
271
|
+
const messageInfo = {
|
|
272
|
+
wsId: wsId,
|
|
273
|
+
url: url,
|
|
274
|
+
timestamp: new Date().toISOString(),
|
|
275
|
+
dataType: typeof event.data
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
if (typeof event.data === 'string') {
|
|
279
|
+
messageInfo.content = event.data.length > 500 ? event.data.substring(0, 500) + '...' : event.data;
|
|
280
|
+
} else if (event.data instanceof ArrayBuffer) {
|
|
281
|
+
messageInfo.content = \`ArrayBuffer(\${event.data.byteLength} bytes)\`;
|
|
282
|
+
} else if (event.data instanceof Blob) {
|
|
283
|
+
messageInfo.content = \`Blob(\${event.data.size} bytes, \${event.data.type})\`;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
console.log(\`[WebSocket Hook #\${wsId}] message:\`, messageInfo);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
ws.addEventListener('error', function(event) {
|
|
290
|
+
console.error(\`[WebSocket Hook #\${wsId}] error:\`, {
|
|
291
|
+
url: url,
|
|
292
|
+
readyState: ws.readyState,
|
|
293
|
+
timestamp: new Date().toISOString()
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
ws.addEventListener('close', function(event) {
|
|
298
|
+
const duration = Date.now() - connectTime;
|
|
299
|
+
console.log(\`[WebSocket Hook #\${wsId}] close:\`, {
|
|
300
|
+
url: url,
|
|
301
|
+
code: event.code,
|
|
302
|
+
reason: event.reason,
|
|
303
|
+
wasClean: event.wasClean,
|
|
304
|
+
duration: duration + 'ms',
|
|
305
|
+
timestamp: new Date().toISOString()
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
return ws;
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
window.WebSocket.CONNECTING = OriginalWebSocket.CONNECTING;
|
|
313
|
+
window.WebSocket.OPEN = OriginalWebSocket.OPEN;
|
|
314
|
+
window.WebSocket.CLOSING = OriginalWebSocket.CLOSING;
|
|
315
|
+
window.WebSocket.CLOSED = OriginalWebSocket.CLOSED;
|
|
316
|
+
|
|
317
|
+
console.log('[WebSocket Hook] Successfully hooked window.WebSocket');
|
|
318
|
+
})();
|
|
319
319
|
`.trim();
|
|
320
320
|
}
|