deepspider 0.1.0
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/.claude/agents/check.md +122 -0
- package/.claude/agents/debug.md +106 -0
- package/.claude/agents/dispatch.md +214 -0
- package/.claude/agents/implement.md +96 -0
- package/.claude/agents/plan.md +396 -0
- package/.claude/agents/research.md +120 -0
- package/.claude/commands/evolve/merge.md +80 -0
- package/.claude/commands/trellis/before-backend-dev.md +13 -0
- package/.claude/commands/trellis/before-frontend-dev.md +13 -0
- package/.claude/commands/trellis/break-loop.md +107 -0
- package/.claude/commands/trellis/check-backend.md +13 -0
- package/.claude/commands/trellis/check-cross-layer.md +153 -0
- package/.claude/commands/trellis/check-frontend.md +13 -0
- package/.claude/commands/trellis/create-command.md +154 -0
- package/.claude/commands/trellis/finish-work.md +129 -0
- package/.claude/commands/trellis/integrate-skill.md +219 -0
- package/.claude/commands/trellis/onboard.md +358 -0
- package/.claude/commands/trellis/parallel.md +193 -0
- package/.claude/commands/trellis/record-session.md +62 -0
- package/.claude/commands/trellis/start.md +280 -0
- package/.claude/commands/trellis/update-spec.md +213 -0
- package/.claude/hooks/inject-subagent-context.py +758 -0
- package/.claude/hooks/ralph-loop.py +374 -0
- package/.claude/hooks/session-start.py +126 -0
- package/.claude/settings.json +41 -0
- package/.claude/skills/deepagents-guide/SKILL.md +428 -0
- package/.cursor/commands/trellis-before-backend-dev.md +13 -0
- package/.cursor/commands/trellis-before-frontend-dev.md +13 -0
- package/.cursor/commands/trellis-break-loop.md +107 -0
- package/.cursor/commands/trellis-check-backend.md +13 -0
- package/.cursor/commands/trellis-check-cross-layer.md +153 -0
- package/.cursor/commands/trellis-check-frontend.md +13 -0
- package/.cursor/commands/trellis-create-command.md +154 -0
- package/.cursor/commands/trellis-finish-work.md +129 -0
- package/.cursor/commands/trellis-integrate-skill.md +219 -0
- package/.cursor/commands/trellis-onboard.md +358 -0
- package/.cursor/commands/trellis-record-session.md +62 -0
- package/.cursor/commands/trellis-start.md +156 -0
- package/.cursor/commands/trellis-update-spec.md +213 -0
- package/.env.example +11 -0
- package/.husky/pre-commit +1 -0
- package/.mcp.json +8 -0
- package/.trellis/.template-hashes.json +65 -0
- package/.trellis/.version +1 -0
- package/.trellis/scripts/add-session.sh +384 -0
- package/.trellis/scripts/common/developer.sh +129 -0
- package/.trellis/scripts/common/git-context.sh +263 -0
- package/.trellis/scripts/common/paths.sh +208 -0
- package/.trellis/scripts/common/phase.sh +150 -0
- package/.trellis/scripts/common/registry.sh +247 -0
- package/.trellis/scripts/common/task-queue.sh +142 -0
- package/.trellis/scripts/common/task-utils.sh +151 -0
- package/.trellis/scripts/common/worktree.sh +128 -0
- package/.trellis/scripts/create-bootstrap.sh +299 -0
- package/.trellis/scripts/get-context.sh +7 -0
- package/.trellis/scripts/get-developer.sh +15 -0
- package/.trellis/scripts/init-developer.sh +34 -0
- package/.trellis/scripts/multi-agent/cleanup.sh +396 -0
- package/.trellis/scripts/multi-agent/create-pr.sh +241 -0
- package/.trellis/scripts/multi-agent/plan.sh +207 -0
- package/.trellis/scripts/multi-agent/start.sh +310 -0
- package/.trellis/scripts/multi-agent/status.sh +828 -0
- package/.trellis/scripts/task.sh +1118 -0
- package/.trellis/spec/backend/deepagents-guide.md +337 -0
- package/.trellis/spec/backend/directory-structure.md +126 -0
- package/.trellis/spec/backend/examples/skills/deepagents-guide/README.md +11 -0
- package/.trellis/spec/backend/examples/skills/deepagents-guide/agent.js.template +20 -0
- package/.trellis/spec/backend/examples/skills/deepagents-guide/skills-config.js.template +13 -0
- package/.trellis/spec/backend/examples/skills/deepagents-guide/subagent.js.template +19 -0
- package/.trellis/spec/backend/hook-guidelines.md +178 -0
- package/.trellis/spec/backend/index.md +36 -0
- package/.trellis/spec/backend/quality-guidelines.md +201 -0
- package/.trellis/spec/backend/state-management.md +76 -0
- package/.trellis/spec/backend/tool-guidelines.md +144 -0
- package/.trellis/spec/backend/type-safety.md +71 -0
- package/.trellis/spec/guides/code-reuse-thinking-guide.md +92 -0
- package/.trellis/spec/guides/cross-layer-thinking-guide.md +94 -0
- package/.trellis/spec/guides/index.md +79 -0
- package/.trellis/tasks/archive/02-02-evolving-skills/prd.md +61 -0
- package/.trellis/tasks/archive/02-02-evolving-skills/task.json +29 -0
- package/.trellis/tasks/archive/2026-02/00-bootstrap-guidelines/prd.md +86 -0
- package/.trellis/tasks/archive/2026-02/00-bootstrap-guidelines/task.json +27 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/check.jsonl +3 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/debug.jsonl +2 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/implement.jsonl +5 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/prd.md +33 -0
- package/.trellis/tasks/archive/2026-02/02-02-skills-system/task.json +41 -0
- package/.trellis/workflow.md +407 -0
- package/.trellis/workspace/index.md +123 -0
- package/.trellis/workspace/pony/index.md +40 -0
- package/.trellis/workspace/pony/journal-1.md +7 -0
- package/.trellis/worktree.yaml +47 -0
- package/AGENTS.md +18 -0
- package/CLAUDE.md +292 -0
- package/README.md +134 -0
- package/agents/deepspider.md +142 -0
- package/docs/DEBUG.md +42 -0
- package/docs/GUIDE.md +334 -0
- package/docs/PROMPT.md +60 -0
- package/docs/USAGE.md +226 -0
- package/eslint.config.js +51 -0
- package/package.json +78 -0
- package/requirements-crypto.txt +14 -0
- package/src/agent/index.js +97 -0
- package/src/agent/logger.js +164 -0
- package/src/agent/middleware/filterTools.js +64 -0
- package/src/agent/middleware/report.js +79 -0
- package/src/agent/prompts/system.js +315 -0
- package/src/agent/run.js +575 -0
- package/src/agent/skills/anti-detect/SKILL.md +28 -0
- package/src/agent/skills/anti-detect/evolved.md +12 -0
- package/src/agent/skills/captcha/SKILL.md +37 -0
- package/src/agent/skills/captcha/evolved.md +12 -0
- package/src/agent/skills/config.js +30 -0
- package/src/agent/skills/crawler/SKILL.md +9 -0
- package/src/agent/skills/crawler/evolved.md +16 -0
- package/src/agent/skills/dynamic-analysis/SKILL.md +91 -0
- package/src/agent/skills/dynamic-analysis/evolved.md +12 -0
- package/src/agent/skills/env/SKILL.md +72 -0
- package/src/agent/skills/env/evolved.md +12 -0
- package/src/agent/skills/evolve.js +79 -0
- package/src/agent/skills/general/SKILL.md +12 -0
- package/src/agent/skills/general/evolved.md +12 -0
- package/src/agent/skills/js2python/SKILL.md +30 -0
- package/src/agent/skills/js2python/evolved.md +13 -0
- package/src/agent/skills/report/SKILL.md +21 -0
- package/src/agent/skills/report/evolved.md +12 -0
- package/src/agent/skills/sandbox/SKILL.md +22 -0
- package/src/agent/skills/sandbox/evolved.md +16 -0
- package/src/agent/skills/static-analysis/SKILL.md +93 -0
- package/src/agent/skills/static-analysis/evolved.md +12 -0
- package/src/agent/skills/xpath/SKILL.md +119 -0
- package/src/agent/subagents/anti-detect.js +45 -0
- package/src/agent/subagents/captcha.js +51 -0
- package/src/agent/subagents/crawler.js +138 -0
- package/src/agent/subagents/dynamic.js +64 -0
- package/src/agent/subagents/env-agent.js +82 -0
- package/src/agent/subagents/index.js +37 -0
- package/src/agent/subagents/js2python.js +72 -0
- package/src/agent/subagents/sandbox.js +55 -0
- package/src/agent/subagents/static.js +66 -0
- package/src/agent/tools/analysis.js +135 -0
- package/src/agent/tools/analyzer.js +85 -0
- package/src/agent/tools/anti-detect.js +89 -0
- package/src/agent/tools/antidebug.js +64 -0
- package/src/agent/tools/async.js +43 -0
- package/src/agent/tools/browser.js +324 -0
- package/src/agent/tools/captcha.js +223 -0
- package/src/agent/tools/capture.js +179 -0
- package/src/agent/tools/correlate.js +303 -0
- package/src/agent/tools/crawler.js +116 -0
- package/src/agent/tools/cryptohook.js +80 -0
- package/src/agent/tools/debug.js +246 -0
- package/src/agent/tools/deobfuscator.js +90 -0
- package/src/agent/tools/env.js +83 -0
- package/src/agent/tools/envdump.js +92 -0
- package/src/agent/tools/evolve.js +164 -0
- package/src/agent/tools/extract.js +114 -0
- package/src/agent/tools/extractor.js +54 -0
- package/src/agent/tools/file.js +224 -0
- package/src/agent/tools/hook.js +84 -0
- package/src/agent/tools/hookManager.js +178 -0
- package/src/agent/tools/index.js +137 -0
- package/src/agent/tools/nodejs.js +101 -0
- package/src/agent/tools/patch.js +46 -0
- package/src/agent/tools/preprocess.js +71 -0
- package/src/agent/tools/profile.js +122 -0
- package/src/agent/tools/python.js +627 -0
- package/src/agent/tools/report.js +124 -0
- package/src/agent/tools/runtime.js +132 -0
- package/src/agent/tools/sandbox.js +79 -0
- package/src/agent/tools/store.js +73 -0
- package/src/agent/tools/trace.js +74 -0
- package/src/agent/tools/tracing.js +201 -0
- package/src/agent/tools/utils.js +51 -0
- package/src/agent/tools/verify.js +184 -0
- package/src/agent/tools/webcrack.js +109 -0
- package/src/analyzer/ASTAnalyzer.js +387 -0
- package/src/analyzer/CallStackAnalyzer.js +379 -0
- package/src/analyzer/Deobfuscator.js +289 -0
- package/src/analyzer/EncryptionAnalyzer.js +99 -0
- package/src/analyzer/index.js +22 -0
- package/src/browser/EnvBridge.js +186 -0
- package/src/browser/cdp.js +168 -0
- package/src/browser/client.js +197 -0
- package/src/browser/collector.js +444 -0
- package/src/browser/collectors/RequestCryptoLinker.js +109 -0
- package/src/browser/collectors/ResponseSearcher.js +107 -0
- package/src/browser/collectors/ScriptCollector.js +158 -0
- package/src/browser/collectors/index.js +26 -0
- package/src/browser/defaultHooks.js +932 -0
- package/src/browser/hooks/crypto.js +55 -0
- package/src/browser/hooks/index.js +64 -0
- package/src/browser/hooks/native.js +9 -0
- package/src/browser/hooks/network.js +33 -0
- package/src/browser/index.js +42 -0
- package/src/browser/interceptors/NetworkInterceptor.js +116 -0
- package/src/browser/interceptors/ScriptInterceptor.js +76 -0
- package/src/browser/interceptors/index.js +6 -0
- package/src/browser/ui/analysisPanel.js +1782 -0
- package/src/browser/ui/confirmDialog.js +158 -0
- package/src/browser/ui/panel.html +152 -0
- package/src/browser/ui/selector.js +170 -0
- package/src/config/index.js +5 -0
- package/src/config/paths.js +71 -0
- package/src/config/patterns/crypto.js +36 -0
- package/src/config/profiles/chrome.json +71 -0
- package/src/config/profiles/firefox.json +44 -0
- package/src/config/profiles/safari.json +38 -0
- package/src/core/EnvMonitor.js +200 -0
- package/src/core/PatchGenerator.js +278 -0
- package/src/core/Sandbox.js +181 -0
- package/src/env/AntiAntiDebug.js +111 -0
- package/src/env/AsyncHook.js +68 -0
- package/src/env/BrowserAPIList.js +265 -0
- package/src/env/CookieHook.js +48 -0
- package/src/env/CryptoHook.js +205 -0
- package/src/env/EnvCodeGenerator.js +157 -0
- package/src/env/EnvDumper.js +356 -0
- package/src/env/EnvExtractor.js +220 -0
- package/src/env/HookBase.js +618 -0
- package/src/env/NetworkHook.js +159 -0
- package/src/env/modules/bom/history.js +29 -0
- package/src/env/modules/bom/location.js +26 -0
- package/src/env/modules/bom/navigator.js +70 -0
- package/src/env/modules/bom/screen.js +26 -0
- package/src/env/modules/bom/storage.js +23 -0
- package/src/env/modules/dom/document.js +110 -0
- package/src/env/modules/dom/event.js +51 -0
- package/src/env/modules/index.js +34 -0
- package/src/env/modules/webapi/fetch.js +46 -0
- package/src/env/modules/webapi/url.js +47 -0
- package/src/env/modules/webapi/xhr.js +48 -0
- package/src/index.js +27 -0
- package/src/mcp/server.js +89 -0
- package/src/store/DataStore.js +708 -0
- package/src/store/Store.js +158 -0
- package/src/store/Validator.js +24 -0
- package/test/analyze.test.js +90 -0
- package/test/envdump.test.js +74 -0
- package/test/flow.test.js +90 -0
- package/test/hooks.test.js +138 -0
- package/test/plugin.test.js +35 -0
- package/test/refactor-full.test.js +30 -0
- package/test/refactor.test.js +21 -0
- package/test/samples/obfuscated.js +61 -0
- package/test/samples/original.js +66 -0
- package/test/samples/v10_eval_chain.js +52 -0
- package/test/samples/v11_bytecode_vm.js +81 -0
- package/test/samples/v12_polymorphic.js +69 -0
- package/test/samples/v1_ob_basic.js +98 -0
- package/test/samples/v2_ob_advanced.js +99 -0
- package/test/samples/v3_jjencode.js +77 -0
- package/test/samples/v4_aaencode.js +73 -0
- package/test/samples/v5_control_flow.js +86 -0
- package/test/samples/v6_string_encryption.js +71 -0
- package/test/samples/v7_jsvmp.js +83 -0
- package/test/samples/v8_anti_debug.js +79 -0
- package/test/samples/v9_proxy_trap.js +49 -0
- package/test/samples.test.js +96 -0
- package/test/webcrack.test.js +55 -0
|
@@ -0,0 +1,932 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DeepSpider - 默认 Hook 脚本
|
|
3
|
+
* 浏览器启动时自动注入
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { HookBase } from '../env/HookBase.js';
|
|
7
|
+
import { getAllCollectorScripts } from './collectors/index.js';
|
|
8
|
+
import { getAnalysisPanelScript } from './ui/analysisPanel.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 生成默认注入的 Hook 代码
|
|
12
|
+
*/
|
|
13
|
+
export function getDefaultHookScript() {
|
|
14
|
+
return HookBase.getBaseCode()
|
|
15
|
+
+ getNetworkHooks()
|
|
16
|
+
+ getCookieHook()
|
|
17
|
+
+ getJSONHooks()
|
|
18
|
+
+ getEncodingHooks()
|
|
19
|
+
+ getStorageHooks()
|
|
20
|
+
+ getWebSocketHooks()
|
|
21
|
+
+ getEvalHooks()
|
|
22
|
+
+ getWebpackHooks()
|
|
23
|
+
+ getCryptoHooks()
|
|
24
|
+
+ getCanvasHooks()
|
|
25
|
+
+ getNavigatorHooks()
|
|
26
|
+
+ getDOMHooks()
|
|
27
|
+
+ getProxyHooks()
|
|
28
|
+
+ getErrorStackHooks()
|
|
29
|
+
+ getAllCollectorScripts()
|
|
30
|
+
+ getAnalysisPanelScript(); // 分析面板 UI
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 网络请求 Hook (XHR + Fetch)
|
|
35
|
+
*/
|
|
36
|
+
function getNetworkHooks() {
|
|
37
|
+
return `
|
|
38
|
+
// === XHR Hook ===
|
|
39
|
+
(function() {
|
|
40
|
+
const deepspider = window.__deepspider__;
|
|
41
|
+
if (!deepspider) return;
|
|
42
|
+
|
|
43
|
+
const OriginalXHR = XMLHttpRequest;
|
|
44
|
+
|
|
45
|
+
XMLHttpRequest = function() {
|
|
46
|
+
const xhr = new OriginalXHR();
|
|
47
|
+
const log = { method: '', url: '', requestHeaders: {}, requestBody: null, response: null, status: 0 };
|
|
48
|
+
|
|
49
|
+
const originalOpen = xhr.open;
|
|
50
|
+
xhr.open = deepspider.native(function(method, url) {
|
|
51
|
+
log.method = method;
|
|
52
|
+
log.url = url;
|
|
53
|
+
return originalOpen.apply(xhr, arguments);
|
|
54
|
+
}, originalOpen);
|
|
55
|
+
|
|
56
|
+
const originalSetHeader = xhr.setRequestHeader;
|
|
57
|
+
xhr.setRequestHeader = deepspider.native(function(name, value) {
|
|
58
|
+
log.requestHeaders[name] = value;
|
|
59
|
+
return originalSetHeader.apply(xhr, arguments);
|
|
60
|
+
}, originalSetHeader);
|
|
61
|
+
|
|
62
|
+
const originalSend = xhr.send;
|
|
63
|
+
xhr.send = deepspider.native(function(body) {
|
|
64
|
+
log.requestId = deepspider.startRequest(log.url, log.method);
|
|
65
|
+
log.requestBody = body;
|
|
66
|
+
deepspider.log('xhr', { action: 'send', ...log, body: body?.toString().slice(0, 200) });
|
|
67
|
+
return originalSend.apply(xhr, arguments);
|
|
68
|
+
}, originalSend);
|
|
69
|
+
|
|
70
|
+
xhr.addEventListener('load', function() {
|
|
71
|
+
log.status = xhr.status;
|
|
72
|
+
log.response = xhr.responseText?.slice(0, 500);
|
|
73
|
+
const ctx = deepspider.endRequest();
|
|
74
|
+
deepspider.log('xhr', {
|
|
75
|
+
action: 'response',
|
|
76
|
+
url: log.url,
|
|
77
|
+
status: log.status,
|
|
78
|
+
response: log.response?.slice(0, 100),
|
|
79
|
+
linkedCrypto: ctx?.cryptoCalls || []
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return xhr;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
XMLHttpRequest.prototype = OriginalXHR.prototype;
|
|
87
|
+
console.log('[DeepSpider] XHR Hook 已启用');
|
|
88
|
+
})();
|
|
89
|
+
|
|
90
|
+
// === Fetch Hook ===
|
|
91
|
+
(function() {
|
|
92
|
+
const deepspider = window.__deepspider__;
|
|
93
|
+
if (!deepspider) return;
|
|
94
|
+
|
|
95
|
+
const OriginalFetch = fetch;
|
|
96
|
+
|
|
97
|
+
fetch = deepspider.native(async function(url, options = {}) {
|
|
98
|
+
const log = {
|
|
99
|
+
url: typeof url === 'string' ? url : url.url,
|
|
100
|
+
method: options.method || 'GET',
|
|
101
|
+
headers: options.headers || {},
|
|
102
|
+
body: null,
|
|
103
|
+
response: null,
|
|
104
|
+
status: 0
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
log.requestId = deepspider.startRequest(log.url, log.method);
|
|
108
|
+
|
|
109
|
+
if (options.body) {
|
|
110
|
+
log.body = typeof options.body === 'string' ? options.body.slice(0, 500) : '[FormData/Blob]';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
deepspider.log('fetch', { action: 'request', ...log });
|
|
114
|
+
|
|
115
|
+
const response = await OriginalFetch.apply(this, arguments);
|
|
116
|
+
log.status = response.status;
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const cloned = response.clone();
|
|
120
|
+
const text = await cloned.text();
|
|
121
|
+
log.response = text.slice(0, 500);
|
|
122
|
+
const ctx = deepspider.endRequest();
|
|
123
|
+
deepspider.log('fetch', {
|
|
124
|
+
action: 'response',
|
|
125
|
+
url: log.url,
|
|
126
|
+
status: log.status,
|
|
127
|
+
response: log.response.slice(0, 100),
|
|
128
|
+
linkedCrypto: ctx?.cryptoCalls || []
|
|
129
|
+
});
|
|
130
|
+
} catch (e) {
|
|
131
|
+
deepspider.endRequest();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return response;
|
|
135
|
+
}, OriginalFetch);
|
|
136
|
+
|
|
137
|
+
console.log('[DeepSpider] Fetch Hook 已启用');
|
|
138
|
+
})();
|
|
139
|
+
`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Cookie Hook
|
|
144
|
+
*/
|
|
145
|
+
function getCookieHook() {
|
|
146
|
+
return `
|
|
147
|
+
// === Cookie Hook ===
|
|
148
|
+
(function() {
|
|
149
|
+
const deepspider = window.__deepspider__;
|
|
150
|
+
if (!deepspider) return;
|
|
151
|
+
|
|
152
|
+
const cookieDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
|
|
153
|
+
Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');
|
|
154
|
+
|
|
155
|
+
if (cookieDesc) {
|
|
156
|
+
Object.defineProperty(document, 'cookie', {
|
|
157
|
+
get: function() {
|
|
158
|
+
const value = cookieDesc.get.call(document);
|
|
159
|
+
deepspider.log('cookie', { action: 'read', value: value?.slice(0, 100) });
|
|
160
|
+
return value;
|
|
161
|
+
},
|
|
162
|
+
set: function(val) {
|
|
163
|
+
deepspider.log('cookie', { action: 'write', value: val });
|
|
164
|
+
return cookieDesc.set.call(document, val);
|
|
165
|
+
},
|
|
166
|
+
configurable: true
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
console.log('[DeepSpider] Cookie Hook 已启用');
|
|
171
|
+
})();
|
|
172
|
+
`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* JSON.parse/stringify Hook
|
|
177
|
+
* 只记录较大的 JSON 数据,避免性能问题
|
|
178
|
+
*/
|
|
179
|
+
function getJSONHooks() {
|
|
180
|
+
return `
|
|
181
|
+
// === JSON Hook ===
|
|
182
|
+
(function() {
|
|
183
|
+
const deepspider = window.__deepspider__;
|
|
184
|
+
if (!deepspider) return;
|
|
185
|
+
|
|
186
|
+
const OriginalParse = JSON.parse;
|
|
187
|
+
const OriginalStringify = JSON.stringify;
|
|
188
|
+
const MIN_LOG_LENGTH = 50; // 只记录长度超过 50 的数据
|
|
189
|
+
|
|
190
|
+
JSON.parse = deepspider.native(function(text, reviver) {
|
|
191
|
+
const textStr = String(text);
|
|
192
|
+
if (textStr.length >= MIN_LOG_LENGTH) {
|
|
193
|
+
deepspider.log('json', {
|
|
194
|
+
action: 'parse',
|
|
195
|
+
input: textStr.slice(0, 200),
|
|
196
|
+
len: textStr.length
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return OriginalParse.call(JSON, text, reviver);
|
|
200
|
+
}, OriginalParse);
|
|
201
|
+
|
|
202
|
+
JSON.stringify = deepspider.native(function(value, replacer, space) {
|
|
203
|
+
const result = OriginalStringify.call(JSON, value, replacer, space);
|
|
204
|
+
if (result && result.length >= MIN_LOG_LENGTH) {
|
|
205
|
+
deepspider.log('json', {
|
|
206
|
+
action: 'stringify',
|
|
207
|
+
output: result.slice(0, 200),
|
|
208
|
+
len: result.length
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return result;
|
|
212
|
+
}, OriginalStringify);
|
|
213
|
+
|
|
214
|
+
console.log('[DeepSpider] JSON Hook 已启用');
|
|
215
|
+
})();
|
|
216
|
+
`;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Base64 + TextEncoder/Decoder Hook
|
|
221
|
+
*/
|
|
222
|
+
function getEncodingHooks() {
|
|
223
|
+
return `
|
|
224
|
+
// === Encoding Hook ===
|
|
225
|
+
(function() {
|
|
226
|
+
const deepspider = window.__deepspider__;
|
|
227
|
+
if (!deepspider) return;
|
|
228
|
+
|
|
229
|
+
// atob/btoa Hook
|
|
230
|
+
const OriginalAtob = atob;
|
|
231
|
+
const OriginalBtoa = btoa;
|
|
232
|
+
|
|
233
|
+
window.atob = deepspider.native(function(data) {
|
|
234
|
+
const result = OriginalAtob.call(window, data);
|
|
235
|
+
deepspider.log('encoding', {
|
|
236
|
+
action: 'atob',
|
|
237
|
+
input: String(data).slice(0, 100),
|
|
238
|
+
output: result.slice(0, 100)
|
|
239
|
+
});
|
|
240
|
+
return result;
|
|
241
|
+
}, OriginalAtob);
|
|
242
|
+
|
|
243
|
+
window.btoa = deepspider.native(function(data) {
|
|
244
|
+
const result = OriginalBtoa.call(window, data);
|
|
245
|
+
deepspider.log('encoding', {
|
|
246
|
+
action: 'btoa',
|
|
247
|
+
input: String(data).slice(0, 100),
|
|
248
|
+
output: result.slice(0, 100)
|
|
249
|
+
});
|
|
250
|
+
return result;
|
|
251
|
+
}, OriginalBtoa);
|
|
252
|
+
|
|
253
|
+
// TextEncoder Hook
|
|
254
|
+
if (window.TextEncoder) {
|
|
255
|
+
const OriginalEncode = TextEncoder.prototype.encode;
|
|
256
|
+
TextEncoder.prototype.encode = deepspider.native(function(input) {
|
|
257
|
+
const result = OriginalEncode.call(this, input);
|
|
258
|
+
if (input && input.length >= 20) {
|
|
259
|
+
deepspider.log('encoding', {
|
|
260
|
+
action: 'TextEncoder.encode',
|
|
261
|
+
input: String(input).slice(0, 100),
|
|
262
|
+
len: result.length
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
}, OriginalEncode);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// TextDecoder Hook
|
|
270
|
+
if (window.TextDecoder) {
|
|
271
|
+
const OriginalDecode = TextDecoder.prototype.decode;
|
|
272
|
+
TextDecoder.prototype.decode = deepspider.native(function(input) {
|
|
273
|
+
const result = OriginalDecode.call(this, input);
|
|
274
|
+
if (result && result.length >= 20) {
|
|
275
|
+
deepspider.log('encoding', {
|
|
276
|
+
action: 'TextDecoder.decode',
|
|
277
|
+
output: result.slice(0, 100),
|
|
278
|
+
len: result.length
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
return result;
|
|
282
|
+
}, OriginalDecode);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
console.log('[DeepSpider] Encoding Hook 已启用');
|
|
286
|
+
})();
|
|
287
|
+
`;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* localStorage/sessionStorage Hook
|
|
292
|
+
*/
|
|
293
|
+
function getStorageHooks() {
|
|
294
|
+
return `
|
|
295
|
+
// === Storage Hook ===
|
|
296
|
+
(function() {
|
|
297
|
+
const deepspider = window.__deepspider__;
|
|
298
|
+
if (!deepspider) return;
|
|
299
|
+
|
|
300
|
+
function hookStorage(storage, name) {
|
|
301
|
+
const origGet = storage.getItem.bind(storage);
|
|
302
|
+
const origSet = storage.setItem.bind(storage);
|
|
303
|
+
|
|
304
|
+
storage.getItem = deepspider.native(function(key) {
|
|
305
|
+
const value = origGet(key);
|
|
306
|
+
deepspider.log('storage', { action: 'get', storage: name, key: key, value: value?.slice(0, 100) });
|
|
307
|
+
return value;
|
|
308
|
+
}, origGet);
|
|
309
|
+
|
|
310
|
+
storage.setItem = deepspider.native(function(key, value) {
|
|
311
|
+
deepspider.log('storage', { action: 'set', storage: name, key: key, value: String(value).slice(0, 100) });
|
|
312
|
+
return origSet(key, value);
|
|
313
|
+
}, origSet);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (window.localStorage) hookStorage(localStorage, 'local');
|
|
317
|
+
if (window.sessionStorage) hookStorage(sessionStorage, 'session');
|
|
318
|
+
|
|
319
|
+
console.log('[DeepSpider] Storage Hook 已启用');
|
|
320
|
+
})();
|
|
321
|
+
`;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* WebSocket Hook
|
|
326
|
+
*/
|
|
327
|
+
function getWebSocketHooks() {
|
|
328
|
+
return `
|
|
329
|
+
// === WebSocket Hook ===
|
|
330
|
+
(function() {
|
|
331
|
+
const deepspider = window.__deepspider__;
|
|
332
|
+
if (!deepspider) return;
|
|
333
|
+
if (!window.WebSocket) return;
|
|
334
|
+
|
|
335
|
+
const OriginalWS = WebSocket;
|
|
336
|
+
|
|
337
|
+
window.WebSocket = function(url, protocols) {
|
|
338
|
+
deepspider.log('websocket', { action: 'connect', url: url });
|
|
339
|
+
const ws = new OriginalWS(url, protocols);
|
|
340
|
+
|
|
341
|
+
const origSend = ws.send.bind(ws);
|
|
342
|
+
ws.send = deepspider.native(function(data) {
|
|
343
|
+
deepspider.log('websocket', {
|
|
344
|
+
action: 'send',
|
|
345
|
+
url: url,
|
|
346
|
+
data: String(data).slice(0, 200)
|
|
347
|
+
});
|
|
348
|
+
return origSend(data);
|
|
349
|
+
}, origSend);
|
|
350
|
+
|
|
351
|
+
ws.addEventListener('message', function(e) {
|
|
352
|
+
deepspider.log('websocket', {
|
|
353
|
+
action: 'message',
|
|
354
|
+
url: url,
|
|
355
|
+
data: String(e.data).slice(0, 200)
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
ws.addEventListener('close', function(e) {
|
|
360
|
+
deepspider.log('websocket', { action: 'close', url: url, code: e.code });
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
ws.addEventListener('error', function() {
|
|
364
|
+
deepspider.log('websocket', { action: 'error', url: url });
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
return ws;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
window.WebSocket.prototype = OriginalWS.prototype;
|
|
371
|
+
window.WebSocket.CONNECTING = OriginalWS.CONNECTING;
|
|
372
|
+
window.WebSocket.OPEN = OriginalWS.OPEN;
|
|
373
|
+
window.WebSocket.CLOSING = OriginalWS.CLOSING;
|
|
374
|
+
window.WebSocket.CLOSED = OriginalWS.CLOSED;
|
|
375
|
+
|
|
376
|
+
console.log('[DeepSpider] WebSocket Hook 已启用');
|
|
377
|
+
})();
|
|
378
|
+
`;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Webpack 模块 Hook - 检测闭包内的加密库
|
|
383
|
+
*/
|
|
384
|
+
function getWebpackHooks() {
|
|
385
|
+
return `
|
|
386
|
+
// === Webpack Hook ===
|
|
387
|
+
(function() {
|
|
388
|
+
const deepspider = window.__deepspider__;
|
|
389
|
+
if (!deepspider) return;
|
|
390
|
+
|
|
391
|
+
// 加密特征检测
|
|
392
|
+
const cryptoPatterns = [
|
|
393
|
+
{ name: 'CryptoJS', pattern: /CryptoJS|crypto-js/i },
|
|
394
|
+
{ name: 'MD5', pattern: /\\bmd5\\b/i },
|
|
395
|
+
{ name: 'SHA', pattern: /\\bsha(1|256|512)\\b/i },
|
|
396
|
+
{ name: 'AES', pattern: /\\baes\\b/i },
|
|
397
|
+
{ name: 'RSA', pattern: /\\brsa\\b/i },
|
|
398
|
+
{ name: 'Base64', pattern: /base64|btoa|atob/i }
|
|
399
|
+
];
|
|
400
|
+
|
|
401
|
+
// Hook webpackJsonp
|
|
402
|
+
function hookWebpack() {
|
|
403
|
+
if (window.webpackJsonp && !window.webpackJsonp.__hooked__) {
|
|
404
|
+
const orig = window.webpackJsonp.push;
|
|
405
|
+
window.webpackJsonp.push = function(chunk) {
|
|
406
|
+
deepspider.log('env', { action: 'webpack.chunk', id: chunk[0] });
|
|
407
|
+
return orig.apply(this, arguments);
|
|
408
|
+
};
|
|
409
|
+
window.webpackJsonp.__hooked__ = true;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// 定期检查
|
|
414
|
+
const check = setInterval(hookWebpack, 100);
|
|
415
|
+
setTimeout(function() { clearInterval(check); }, 5000);
|
|
416
|
+
|
|
417
|
+
console.log('[DeepSpider] Webpack Hook 已启用');
|
|
418
|
+
})();
|
|
419
|
+
`;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* eval/Function Hook - 捕获动态代码执行 + debugger 绕过
|
|
424
|
+
*/
|
|
425
|
+
function getEvalHooks() {
|
|
426
|
+
return `
|
|
427
|
+
// === Eval/Function Hook ===
|
|
428
|
+
(function() {
|
|
429
|
+
const deepspider = window.__deepspider__;
|
|
430
|
+
if (!deepspider) return;
|
|
431
|
+
|
|
432
|
+
const debuggerPattern = /\\bdebugger\\b/;
|
|
433
|
+
|
|
434
|
+
// Hook eval
|
|
435
|
+
const OriginalEval = eval;
|
|
436
|
+
window.eval = deepspider.native(function(code) {
|
|
437
|
+
let codeStr = String(code);
|
|
438
|
+
// debugger 绕过
|
|
439
|
+
if (debuggerPattern.test(codeStr)) {
|
|
440
|
+
codeStr = codeStr.replace(/\\bdebugger\\b/g, '/* debugger bypassed */');
|
|
441
|
+
deepspider.log('debug', { action: 'bypass', type: 'eval' });
|
|
442
|
+
}
|
|
443
|
+
deepspider.log('eval', {
|
|
444
|
+
action: 'eval',
|
|
445
|
+
code: codeStr.slice(0, 500)
|
|
446
|
+
});
|
|
447
|
+
return OriginalEval.call(window, codeStr);
|
|
448
|
+
}, OriginalEval);
|
|
449
|
+
|
|
450
|
+
// Hook Function constructor
|
|
451
|
+
const OriginalFunction = Function;
|
|
452
|
+
window.Function = deepspider.native(function() {
|
|
453
|
+
const args = Array.from(arguments);
|
|
454
|
+
const lastIdx = args.length - 1;
|
|
455
|
+
// debugger 绕过
|
|
456
|
+
if (lastIdx >= 0 && typeof args[lastIdx] === 'string' && debuggerPattern.test(args[lastIdx])) {
|
|
457
|
+
args[lastIdx] = args[lastIdx].replace(/\\bdebugger\\b/g, '/* debugger bypassed */');
|
|
458
|
+
deepspider.log('debug', { action: 'bypass', type: 'Function' });
|
|
459
|
+
}
|
|
460
|
+
deepspider.log('eval', {
|
|
461
|
+
action: 'Function',
|
|
462
|
+
args: args.map(a => String(a).slice(0, 200))
|
|
463
|
+
});
|
|
464
|
+
return OriginalFunction.apply(this, args);
|
|
465
|
+
}, OriginalFunction);
|
|
466
|
+
window.Function.prototype = OriginalFunction.prototype;
|
|
467
|
+
|
|
468
|
+
// Hook setTimeout/setInterval 字符串参数
|
|
469
|
+
const OriginalSetTimeout = setTimeout;
|
|
470
|
+
const OriginalSetInterval = setInterval;
|
|
471
|
+
|
|
472
|
+
window.setTimeout = deepspider.native(function(handler, delay) {
|
|
473
|
+
if (typeof handler === 'string') {
|
|
474
|
+
// debugger 绕过
|
|
475
|
+
if (debuggerPattern.test(handler)) {
|
|
476
|
+
handler = handler.replace(/\\bdebugger\\b/g, '/* debugger bypassed */');
|
|
477
|
+
deepspider.log('debug', { action: 'bypass', type: 'setTimeout' });
|
|
478
|
+
}
|
|
479
|
+
deepspider.log('eval', {
|
|
480
|
+
action: 'setTimeout',
|
|
481
|
+
code: handler.slice(0, 500),
|
|
482
|
+
delay: delay
|
|
483
|
+
});
|
|
484
|
+
return OriginalSetTimeout.call(window, handler, delay);
|
|
485
|
+
}
|
|
486
|
+
return OriginalSetTimeout.apply(window, arguments);
|
|
487
|
+
}, OriginalSetTimeout);
|
|
488
|
+
|
|
489
|
+
window.setInterval = deepspider.native(function(handler, delay) {
|
|
490
|
+
if (typeof handler === 'string') {
|
|
491
|
+
// debugger 绕过
|
|
492
|
+
if (debuggerPattern.test(handler)) {
|
|
493
|
+
deepspider.log('debug', { action: 'bypass', type: 'setInterval' });
|
|
494
|
+
return OriginalSetInterval.call(window, function(){}, delay);
|
|
495
|
+
}
|
|
496
|
+
deepspider.log('eval', {
|
|
497
|
+
action: 'setInterval',
|
|
498
|
+
code: handler.slice(0, 500),
|
|
499
|
+
delay: delay
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
// 检测高频 debugger 函数
|
|
503
|
+
if (typeof handler === 'function' && delay < 500) {
|
|
504
|
+
const code = handler.toString();
|
|
505
|
+
if (debuggerPattern.test(code)) {
|
|
506
|
+
deepspider.log('debug', { action: 'bypass', type: 'setInterval-func' });
|
|
507
|
+
return OriginalSetInterval.call(window, function(){}, delay);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return OriginalSetInterval.apply(window, arguments);
|
|
511
|
+
}, OriginalSetInterval);
|
|
512
|
+
|
|
513
|
+
console.log('[DeepSpider] Eval/Function Hook 已启用');
|
|
514
|
+
})();
|
|
515
|
+
`;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* 加密函数 Hook (CryptoJS + JSEncrypt + 国密 + Web Crypto API)
|
|
520
|
+
* 使用 Object.defineProperty 拦截全局变量赋值,在加密库加载时立即 Hook
|
|
521
|
+
*/
|
|
522
|
+
function getCryptoHooks() {
|
|
523
|
+
return `
|
|
524
|
+
// === Crypto Hook ===
|
|
525
|
+
(function() {
|
|
526
|
+
const deepspider = window.__deepspider__;
|
|
527
|
+
if (!deepspider) return;
|
|
528
|
+
|
|
529
|
+
// Hook CryptoJS 的方法
|
|
530
|
+
function hookCryptoJS(CryptoJS) {
|
|
531
|
+
if (CryptoJS.__deepspider_hooked__) return;
|
|
532
|
+
CryptoJS.__deepspider_hooked__ = true;
|
|
533
|
+
|
|
534
|
+
// 对称加密算法
|
|
535
|
+
['AES', 'DES', 'TripleDES', 'RC4', 'Rabbit'].forEach(cipher => {
|
|
536
|
+
if (!CryptoJS[cipher]) return;
|
|
537
|
+
['encrypt', 'decrypt'].forEach(method => {
|
|
538
|
+
if (CryptoJS[cipher][method]) {
|
|
539
|
+
const original = CryptoJS[cipher][method];
|
|
540
|
+
CryptoJS[cipher][method] = deepspider.native(function(data, key, options) {
|
|
541
|
+
const entry = deepspider.log('crypto', {
|
|
542
|
+
algo: 'CryptoJS.' + cipher + '.' + method,
|
|
543
|
+
data: String(data).slice(0, 100),
|
|
544
|
+
keyLen: key ? String(key).length : 0,
|
|
545
|
+
options: options ? Object.keys(options) : []
|
|
546
|
+
});
|
|
547
|
+
deepspider.linkCrypto(entry);
|
|
548
|
+
return original.apply(this, arguments);
|
|
549
|
+
}, original);
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
// 哈希算法
|
|
555
|
+
['MD5', 'SHA1', 'SHA256', 'SHA512', 'SHA3', 'RIPEMD160'].forEach(algo => {
|
|
556
|
+
if (CryptoJS[algo]) {
|
|
557
|
+
const original = CryptoJS[algo];
|
|
558
|
+
CryptoJS[algo] = deepspider.native(function() {
|
|
559
|
+
const entry = deepspider.log('crypto', {
|
|
560
|
+
algo: 'CryptoJS.' + algo,
|
|
561
|
+
inputLen: arguments[0] ? String(arguments[0]).length : 0
|
|
562
|
+
});
|
|
563
|
+
deepspider.linkCrypto(entry);
|
|
564
|
+
return original.apply(this, arguments);
|
|
565
|
+
}, original);
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
// HMAC 算法
|
|
570
|
+
['HmacMD5', 'HmacSHA1', 'HmacSHA256', 'HmacSHA512'].forEach(algo => {
|
|
571
|
+
if (CryptoJS[algo]) {
|
|
572
|
+
const original = CryptoJS[algo];
|
|
573
|
+
CryptoJS[algo] = deepspider.native(function() {
|
|
574
|
+
const entry = deepspider.log('crypto', {
|
|
575
|
+
algo: 'CryptoJS.' + algo,
|
|
576
|
+
inputLen: arguments[0] ? String(arguments[0]).length : 0
|
|
577
|
+
});
|
|
578
|
+
deepspider.linkCrypto(entry);
|
|
579
|
+
return original.apply(this, arguments);
|
|
580
|
+
}, original);
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
console.log('[DeepSpider] CryptoJS Hook 已启用');
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Hook JSEncrypt
|
|
588
|
+
function hookJSEncrypt(JSEncrypt) {
|
|
589
|
+
if (JSEncrypt.__deepspider_hooked__) return;
|
|
590
|
+
JSEncrypt.__deepspider_hooked__ = true;
|
|
591
|
+
|
|
592
|
+
const proto = JSEncrypt.prototype;
|
|
593
|
+
if (proto.encrypt) {
|
|
594
|
+
const origEnc = proto.encrypt;
|
|
595
|
+
proto.encrypt = deepspider.native(function(data) {
|
|
596
|
+
const entry = deepspider.log('crypto', { algo: 'RSA.encrypt', data: String(data).slice(0, 100) });
|
|
597
|
+
deepspider.linkCrypto(entry);
|
|
598
|
+
return origEnc.apply(this, arguments);
|
|
599
|
+
}, origEnc);
|
|
600
|
+
}
|
|
601
|
+
console.log('[DeepSpider] RSA Hook 已启用');
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Hook SM2
|
|
605
|
+
function hookSM2(sm2) {
|
|
606
|
+
if (sm2.__deepspider_hooked__) return;
|
|
607
|
+
sm2.__deepspider_hooked__ = true;
|
|
608
|
+
|
|
609
|
+
if (sm2.doEncrypt) {
|
|
610
|
+
const origEnc = sm2.doEncrypt;
|
|
611
|
+
sm2.doEncrypt = deepspider.native(function(msg, pubKey) {
|
|
612
|
+
const entry = deepspider.log('crypto', { algo: 'SM2.encrypt', msg: String(msg).slice(0, 100) });
|
|
613
|
+
deepspider.linkCrypto(entry);
|
|
614
|
+
return origEnc.apply(this, arguments);
|
|
615
|
+
}, origEnc);
|
|
616
|
+
console.log('[DeepSpider] SM2 Hook 已启用');
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// Hook node-forge
|
|
621
|
+
function hookForge(forge) {
|
|
622
|
+
if (forge.__deepspider_hooked__) return;
|
|
623
|
+
forge.__deepspider_hooked__ = true;
|
|
624
|
+
|
|
625
|
+
// MD/SHA
|
|
626
|
+
['md5', 'sha1', 'sha256', 'sha512'].forEach(function(algo) {
|
|
627
|
+
if (forge.md && forge.md[algo]) {
|
|
628
|
+
const orig = forge.md[algo].create;
|
|
629
|
+
forge.md[algo].create = function() {
|
|
630
|
+
const md = orig.apply(this, arguments);
|
|
631
|
+
const origUpdate = md.update;
|
|
632
|
+
md.update = function(data) {
|
|
633
|
+
deepspider.log('crypto', { algo: 'forge.' + algo, inputLen: data?.length });
|
|
634
|
+
return origUpdate.apply(this, arguments);
|
|
635
|
+
};
|
|
636
|
+
return md;
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// AES
|
|
642
|
+
if (forge.cipher) {
|
|
643
|
+
const origCreate = forge.cipher.createCipher;
|
|
644
|
+
if (origCreate) {
|
|
645
|
+
forge.cipher.createCipher = function(algo, key) {
|
|
646
|
+
deepspider.log('crypto', { algo: 'forge.cipher.' + algo, keyLen: key?.length });
|
|
647
|
+
return origCreate.apply(this, arguments);
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
console.log('[DeepSpider] Forge Hook 已启用');
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Hook jsrsasign
|
|
655
|
+
function hookJsrsasign(KJUR) {
|
|
656
|
+
if (KJUR.__deepspider_hooked__) return;
|
|
657
|
+
KJUR.__deepspider_hooked__ = true;
|
|
658
|
+
|
|
659
|
+
if (KJUR.crypto && KJUR.crypto.Signature) {
|
|
660
|
+
const origSign = KJUR.crypto.Signature.prototype.sign;
|
|
661
|
+
if (origSign) {
|
|
662
|
+
KJUR.crypto.Signature.prototype.sign = function() {
|
|
663
|
+
deepspider.log('crypto', { algo: 'jsrsasign.sign' });
|
|
664
|
+
return origSign.apply(this, arguments);
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
console.log('[DeepSpider] jsrsasign Hook 已启用');
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// 使用 defineProperty 拦截全局变量赋值
|
|
672
|
+
function watchGlobal(name, hookFn) {
|
|
673
|
+
let value = window[name];
|
|
674
|
+
if (value) {
|
|
675
|
+
hookFn(value);
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
try {
|
|
680
|
+
Object.defineProperty(window, name, {
|
|
681
|
+
configurable: true,
|
|
682
|
+
enumerable: true,
|
|
683
|
+
get: function() { return value; },
|
|
684
|
+
set: function(newVal) {
|
|
685
|
+
value = newVal;
|
|
686
|
+
if (newVal) {
|
|
687
|
+
hookFn(newVal);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
} catch (e) {
|
|
692
|
+
// 如果 defineProperty 失败,回退到轮询
|
|
693
|
+
const check = setInterval(function() {
|
|
694
|
+
if (window[name]) {
|
|
695
|
+
clearInterval(check);
|
|
696
|
+
hookFn(window[name]);
|
|
697
|
+
}
|
|
698
|
+
}, 50);
|
|
699
|
+
setTimeout(function() { clearInterval(check); }, 10000);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
watchGlobal('CryptoJS', hookCryptoJS);
|
|
704
|
+
watchGlobal('JSEncrypt', hookJSEncrypt);
|
|
705
|
+
watchGlobal('sm2', hookSM2);
|
|
706
|
+
watchGlobal('forge', hookForge);
|
|
707
|
+
watchGlobal('KJUR', hookJsrsasign);
|
|
708
|
+
|
|
709
|
+
// Hook Web Crypto API (原生加密)
|
|
710
|
+
if (window.crypto && window.crypto.subtle) {
|
|
711
|
+
const subtle = window.crypto.subtle;
|
|
712
|
+
['encrypt', 'decrypt', 'sign', 'verify', 'digest'].forEach(function(method) {
|
|
713
|
+
if (subtle[method]) {
|
|
714
|
+
const original = subtle[method].bind(subtle);
|
|
715
|
+
subtle[method] = deepspider.native(function(algorithm) {
|
|
716
|
+
const algoName = typeof algorithm === 'string' ? algorithm : algorithm.name;
|
|
717
|
+
deepspider.log('crypto', {
|
|
718
|
+
algo: 'WebCrypto.' + method,
|
|
719
|
+
algorithm: algoName
|
|
720
|
+
});
|
|
721
|
+
return original.apply(subtle, arguments);
|
|
722
|
+
}, original);
|
|
723
|
+
}
|
|
724
|
+
});
|
|
725
|
+
console.log('[DeepSpider] Web Crypto API Hook 已启用');
|
|
726
|
+
}
|
|
727
|
+
})();
|
|
728
|
+
`;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Canvas 指纹检测 Hook
|
|
733
|
+
*/
|
|
734
|
+
function getCanvasHooks() {
|
|
735
|
+
return `
|
|
736
|
+
// === Canvas Hook ===
|
|
737
|
+
(function() {
|
|
738
|
+
const deepspider = window.__deepspider__;
|
|
739
|
+
if (!deepspider) return;
|
|
740
|
+
|
|
741
|
+
// toDataURL Hook
|
|
742
|
+
const origToDataURL = HTMLCanvasElement.prototype.toDataURL;
|
|
743
|
+
HTMLCanvasElement.prototype.toDataURL = deepspider.native(function() {
|
|
744
|
+
const result = origToDataURL.apply(this, arguments);
|
|
745
|
+
deepspider.log('env', {
|
|
746
|
+
action: 'canvas.toDataURL',
|
|
747
|
+
width: this.width,
|
|
748
|
+
height: this.height,
|
|
749
|
+
hash: result.slice(0, 50)
|
|
750
|
+
});
|
|
751
|
+
return result;
|
|
752
|
+
}, origToDataURL);
|
|
753
|
+
|
|
754
|
+
// getImageData Hook
|
|
755
|
+
const origGetImageData = CanvasRenderingContext2D.prototype.getImageData;
|
|
756
|
+
CanvasRenderingContext2D.prototype.getImageData = deepspider.native(function(x, y, w, h) {
|
|
757
|
+
const result = origGetImageData.apply(this, arguments);
|
|
758
|
+
deepspider.log('env', {
|
|
759
|
+
action: 'canvas.getImageData',
|
|
760
|
+
x: x, y: y, w: w, h: h
|
|
761
|
+
});
|
|
762
|
+
return result;
|
|
763
|
+
}, origGetImageData);
|
|
764
|
+
|
|
765
|
+
console.log('[DeepSpider] Canvas Hook 已启用');
|
|
766
|
+
})();
|
|
767
|
+
`;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* Navigator/Screen 环境检测 Hook
|
|
772
|
+
*/
|
|
773
|
+
function getNavigatorHooks() {
|
|
774
|
+
return `
|
|
775
|
+
// === Navigator Hook ===
|
|
776
|
+
(function() {
|
|
777
|
+
const deepspider = window.__deepspider__;
|
|
778
|
+
if (!deepspider) return;
|
|
779
|
+
|
|
780
|
+
// 监控 navigator 属性访问
|
|
781
|
+
const navProps = ['userAgent', 'platform', 'language', 'languages', 'hardwareConcurrency', 'deviceMemory', 'webdriver'];
|
|
782
|
+
navProps.forEach(function(prop) {
|
|
783
|
+
const desc = Object.getOwnPropertyDescriptor(Navigator.prototype, prop);
|
|
784
|
+
if (desc && desc.get) {
|
|
785
|
+
const origGet = desc.get;
|
|
786
|
+
Object.defineProperty(Navigator.prototype, prop, {
|
|
787
|
+
get: function() {
|
|
788
|
+
const val = origGet.call(this);
|
|
789
|
+
deepspider.log('env', { action: 'navigator.' + prop, value: String(val).slice(0, 100) });
|
|
790
|
+
return val;
|
|
791
|
+
},
|
|
792
|
+
configurable: true
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
console.log('[DeepSpider] Navigator Hook 已启用');
|
|
798
|
+
})();
|
|
799
|
+
`;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* DOM 查询监控
|
|
804
|
+
*/
|
|
805
|
+
function getDOMHooks() {
|
|
806
|
+
return `
|
|
807
|
+
// === DOM Hook ===
|
|
808
|
+
(function() {
|
|
809
|
+
const deepspider = window.__deepspider__;
|
|
810
|
+
if (!deepspider) return;
|
|
811
|
+
|
|
812
|
+
const methods = [
|
|
813
|
+
{ obj: Document.prototype, name: 'getElementById' },
|
|
814
|
+
{ obj: Document.prototype, name: 'getElementsByClassName' },
|
|
815
|
+
{ obj: Document.prototype, name: 'getElementsByTagName' },
|
|
816
|
+
{ obj: Document.prototype, name: 'querySelector' },
|
|
817
|
+
{ obj: Document.prototype, name: 'querySelectorAll' },
|
|
818
|
+
{ obj: Element.prototype, name: 'querySelector' },
|
|
819
|
+
{ obj: Element.prototype, name: 'querySelectorAll' }
|
|
820
|
+
];
|
|
821
|
+
|
|
822
|
+
methods.forEach(function(m) {
|
|
823
|
+
const original = m.obj[m.name];
|
|
824
|
+
if (!original) return;
|
|
825
|
+
|
|
826
|
+
m.obj[m.name] = deepspider.native(function() {
|
|
827
|
+
const selector = arguments[0];
|
|
828
|
+
const result = original.apply(this, arguments);
|
|
829
|
+
deepspider.log('dom', {
|
|
830
|
+
action: m.name,
|
|
831
|
+
selector: String(selector),
|
|
832
|
+
found: result ? (result.length !== undefined ? result.length : 1) : 0
|
|
833
|
+
});
|
|
834
|
+
return result;
|
|
835
|
+
}, original);
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
console.log('[DeepSpider] DOM Hook 已启用');
|
|
839
|
+
})();
|
|
840
|
+
`;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Proxy/Reflect Hook - 监控现代混淆常用的 Proxy 操作
|
|
845
|
+
*/
|
|
846
|
+
function getProxyHooks() {
|
|
847
|
+
return `
|
|
848
|
+
// === Proxy Hook ===
|
|
849
|
+
(function() {
|
|
850
|
+
const deepspider = window.__deepspider__;
|
|
851
|
+
if (!deepspider) return;
|
|
852
|
+
|
|
853
|
+
const OriginalProxy = Proxy;
|
|
854
|
+
|
|
855
|
+
// 创建 trap 包装器(使用 IIFE 避免闭包问题)
|
|
856
|
+
function wrapTrap(trapName, trapFn) {
|
|
857
|
+
return function() {
|
|
858
|
+
deepspider.log('env', {
|
|
859
|
+
action: 'Proxy.' + trapName,
|
|
860
|
+
args: Array.from(arguments).slice(0, 2).map(function(a) {
|
|
861
|
+
return String(a).slice(0, 50);
|
|
862
|
+
})
|
|
863
|
+
});
|
|
864
|
+
return trapFn.apply(this, arguments);
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
window.Proxy = deepspider.native(function(target, handler) {
|
|
869
|
+
deepspider.log('env', {
|
|
870
|
+
action: 'Proxy.create',
|
|
871
|
+
targetType: typeof target,
|
|
872
|
+
traps: handler ? Object.keys(handler) : []
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
// 包装 handler
|
|
876
|
+
const wrappedHandler = {};
|
|
877
|
+
if (handler) {
|
|
878
|
+
for (const trap in handler) {
|
|
879
|
+
if (typeof handler[trap] === 'function') {
|
|
880
|
+
wrappedHandler[trap] = wrapTrap(trap, handler[trap]);
|
|
881
|
+
} else {
|
|
882
|
+
wrappedHandler[trap] = handler[trap];
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
return new OriginalProxy(target, wrappedHandler);
|
|
888
|
+
}, OriginalProxy);
|
|
889
|
+
|
|
890
|
+
// 保留静态方法
|
|
891
|
+
window.Proxy.revocable = OriginalProxy.revocable;
|
|
892
|
+
|
|
893
|
+
console.log('[DeepSpider] Proxy Hook 已启用');
|
|
894
|
+
})();
|
|
895
|
+
`;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* Error.stack 保护 - 隐藏 Hook 相关的调用栈
|
|
900
|
+
*/
|
|
901
|
+
function getErrorStackHooks() {
|
|
902
|
+
return `
|
|
903
|
+
// === Error Stack Hook ===
|
|
904
|
+
(function() {
|
|
905
|
+
const deepspider = window.__deepspider__;
|
|
906
|
+
if (!deepspider) return;
|
|
907
|
+
|
|
908
|
+
const stackDesc = Object.getOwnPropertyDescriptor(Error.prototype, 'stack');
|
|
909
|
+
|
|
910
|
+
if (stackDesc && stackDesc.get) {
|
|
911
|
+
const origGet = stackDesc.get;
|
|
912
|
+
Object.defineProperty(Error.prototype, 'stack', {
|
|
913
|
+
get: function() {
|
|
914
|
+
let stack = origGet.call(this);
|
|
915
|
+
if (stack && typeof stack === 'string') {
|
|
916
|
+
// 过滤掉 DeepSpider 相关的栈帧
|
|
917
|
+
stack = stack.split('\\n').filter(function(line) {
|
|
918
|
+
return !/__deepspider__|DeepSpider|deepspider\\.native/.test(line);
|
|
919
|
+
}).join('\\n');
|
|
920
|
+
}
|
|
921
|
+
return stack;
|
|
922
|
+
},
|
|
923
|
+
configurable: true
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
console.log('[DeepSpider] Error Stack Hook 已启用');
|
|
928
|
+
})();
|
|
929
|
+
`;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
export default getDefaultHookScript;
|