Files
hello_js_reverse_skill/references/anti-debug.md
T
白夜 b5cf8b121a feat(v2.4.0): JSVMP 双路径攻克体系 + jsdom 环境补丁知识库
基于实战经验重构 JSVMP 分析框架:

- SKILL.md: 新增路径选择决策树(路径 A 算法追踪 vs 路径 B 环境伪装)
- SKILL.md: 路径 B「环境伪装六步法」完整方法论(采集→对比→分级→补丁→验证→端到端)
- SKILL.md: 新增场景 10「JSVMP + jsdom 环境伪装」、解法模式 E
- SKILL.md: 标注三板斧适用边界与局限,经验法则扩充至 22 条
- references/jsdom-env-patches.md: 新增 jsdom 环境补丁知识库(Function.toString 三层防御 / plugins 完整模拟 / DOM 布局属性 / 30+ API 存根)
- cases/: 新增经验库系统(模板 + 首个 JSVMP 实战案例含 58 项环境检测差异全表)
- references/jsvmp-analysis.md: JSVMP 专项分析详细指南
- references/troubleshooting.md: 常见问题排查指南
- templates/python-request/: Python 项目模板
- 各 references 文档增强、Python 技术栈支持、MCP v1.1 适配(44→52 工具)

Made-with: Cursor
2026-04-02 18:10:05 +08:00

342 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 反调试对抗手册
## 概述
现代网站常采用多种反调试技术阻止逆向分析。本手册涵盖常见反调试手段及其绕过策略。
## 1. debugger 语句
### 表现
```javascript
// 无限 debugger 循环
setInterval(function() { debugger; }, 100);
// 条件 debugger
(function check() {
debugger;
check();
})();
// 隐藏 debugger(通过 constructor)
(function() {
var a = new Function("debugger");
setInterval(a, 1000);
})();
```
### 绕过方案
**方案 A:MCP 一键绕过**
```
[camoufox-reverse] bypass_debugger_trap()
或
[camoufox-reverse] inject_hook_preset(preset="debugger_bypass")
或手动注入:
[camoufox-reverse] add_init_script(script=反debugger脚本)
```
```javascript
// 覆写 Function 构造器,过滤 debugger
const _Function = Function;
Function = function() {
const body = arguments[arguments.length - 1];
if (typeof body === 'string' && body.indexOf('debugger') !== -1) {
arguments[arguments.length - 1] = body.replace(/debugger/g, '');
}
return _Function.apply(this, arguments);
};
Function.prototype = _Function.prototype;
// 覆写定时器,过滤 debugger
const _setInterval = setInterval;
setInterval = function(fn, ms) {
if (typeof fn === 'function' && fn.toString().indexOf('debugger') !== -1) {
return -1;
}
if (typeof fn === 'string' && fn.indexOf('debugger') !== -1) {
return -1;
}
return _setInterval.apply(this, arguments);
};
```
**方案 B:加载前拦截 debugger 构造**
```
[camoufox-reverse] add_init_script(script=反debugger脚本)
```
## 2. 开发者工具检测
### 2.1 窗口尺寸检测
```javascript
setInterval(function() {
if (window.outerHeight - window.innerHeight > 200 ||
window.outerWidth - window.innerWidth > 200) {
// DevTools 已打开
document.body.innerHTML = '';
}
}, 500);
```
**绕过**:
```javascript
// 注入后锁定尺寸
Object.defineProperty(window, 'outerHeight', { get: () => window.innerHeight });
Object.defineProperty(window, 'outerWidth', { get: () => window.innerWidth });
```
### 2.2 console.log 计时检测
```javascript
setInterval(function() {
var start = Date.now();
console.log('check');
console.clear();
if (Date.now() - start > 10) {
// DevTools 已打开(console.log 在 DevTools 打开时较慢)
window.location = 'about:blank';
}
}, 1000);
```
**绕过**:
```javascript
// 覆写 console 方法为空操作
const noop = function() {};
console.log = noop;
console.clear = noop;
```
### 2.3 toString 检测
```javascript
var devtools = /./;
devtools.toString = function() {
// 只有在 DevTools 打开时,console.log 才会调用对象的 toString
isDevToolsOpen = true;
return '';
};
console.log(devtools);
```
**绕过**:
```javascript
// 覆写 console.log,阻止 toString 调用检测
const _log = console.log;
console.log = function() {
// 不调用 toString
};
```
## 3. 代码完整性检测
### 3.1 函数 toString 检测
```javascript
function critical() {
// 重要逻辑
}
if (critical.toString().indexOf('\n') !== -1) {
// 代码被格式化,触发反调试
while(true) {}
}
```
**绕过**:
```javascript
// 保存原始 toString 结果
const origToString = critical.toString();
Object.defineProperty(critical, 'toString', {
value: function() { return origToString; }
});
```
### 3.2 源码长度检测
```javascript
if (someFunction.toString().length !== 1234) {
// 代码被修改
throw new Error('Integrity check failed');
}
```
**绕过**:不修改原始函数,使用 `add_init_script` 在页面脚本执行之前收集所需数据。
## 4. 时间差检测
```javascript
var t1 = Date.now();
// ... 执行代码 ...
var t2 = Date.now();
if (t2 - t1 > 100) {
// 可能在断点处暂停了
window.location = 'about:blank';
}
```
**绕过**:
```javascript
// Hook Date.now 返回连续值
const _now = Date.now;
let fakeTime = _now();
Date.now = function() {
fakeTime += 1;
return fakeTime;
};
// 或使用 performance.now
const _perfNow = performance.now;
performance.now = function() {
return _perfNow.call(performance);
};
```
## 5. 环境检测
### 5.1 Node.js 环境检测
```javascript
if (typeof process !== 'undefined' && process.versions && process.versions.node) {
throw new Error('Node.js detected');
}
if (typeof module !== 'undefined' && module.exports) {
throw new Error('CommonJS detected');
}
if (typeof global !== 'undefined') {
throw new Error('Non-browser detected');
}
```
**绕过**:在 vm 沙箱中删除这些全局变量。
### 5.2 浏览器指纹检测
```javascript
if (!window.chrome || !window.chrome.runtime) {
throw new Error('Not Chrome');
}
if (navigator.webdriver) {
throw new Error('WebDriver detected');
}
if (navigator.plugins.length === 0) {
throw new Error('Headless browser detected');
}
```
**绕过**:补全环境变量(参考 `environment-patch.md`)。
### 5.3 Selenium / Puppeteer 检测
```javascript
const checks = [
'webdriver' in navigator,
'_Selenium_IDE_Recorder' in window,
'callSelenium' in document,
'__webdriver_script_fn' in document,
'$cdc_asdjflasutopfhvcZLmcfl_' in document,
'_phantom' in window,
'callPhantom' in window
];
if (checks.some(Boolean)) {
throw new Error('Automation detected');
}
```
**绕过**:
```javascript
// 清除自动化指纹
delete navigator.webdriver;
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
delete window._Selenium_IDE_Recorder;
// ... 逐个清除
```
## 6. Object.defineProperty 篡改
```javascript
// 改变属性定义行为
const _defineProperty = Object.defineProperty;
Object.defineProperty = function(obj, prop, descriptor) {
if (prop === 'cookie') {
return ""; // 阻止 Cookie Hook
}
return _defineProperty.apply(this, arguments);
};
```
**绕过**:在注入脚本中保存原始引用。
```javascript
// 在所有代码之前保存原始方法
const originalDefineProperty = Object.defineProperty;
// 后续使用 originalDefineProperty 而非 Object.defineProperty
```
## 7. Proxy 检测
```javascript
// 某些代码会检测对象是否被 Proxy 包装
try {
new Proxy({}, {});
} catch(e) {
// 环境异常
}
```
**注意**:使用 Proxy 做 Hook 时,确保 Proxy 行为与原始对象一致。
## 通用反反调试注入脚本
以下脚本适合通过 `add_init_script` 在页面加载前注入:
```javascript
(function() {
'use strict';
// 保存原始方法引用
const originals = {
defineProperty: Object.defineProperty,
getOwnPropertyDescriptor: Object.getOwnPropertyDescriptor,
setInterval: window.setInterval,
setTimeout: window.setTimeout,
Function: window.Function,
eval: window.eval,
dateNow: Date.now,
};
// 1. 拦截 debugger
const _Function = originals.Function;
window.Function = function() {
let body = arguments[arguments.length - 1];
if (typeof body === 'string' && body.includes('debugger')) {
arguments[arguments.length - 1] = body.replace(/debugger\s*;?/g, '');
}
return _Function.apply(this, arguments);
};
window.Function.prototype = _Function.prototype;
// 2. 过滤 debugger 定时器
const _setInterval = originals.setInterval;
window.setInterval = function(fn, ms) {
if (typeof fn === 'function' && fn.toString().includes('debugger')) return -1;
if (typeof fn === 'string' && fn.includes('debugger')) return -1;
return _setInterval.apply(this, arguments);
};
const _setTimeout = originals.setTimeout;
window.setTimeout = function(fn, ms) {
if (typeof fn === 'function' && fn.toString().includes('debugger')) return -1;
if (typeof fn === 'string' && fn.includes('debugger')) return -1;
return _setTimeout.apply(this, arguments);
};
// 3. 隐藏 webdriver 属性
originals.defineProperty.call(Object, navigator, 'webdriver', {
get: () => undefined, configurable: true
});
console.log('[AntiDebug] 反反调试脚本已注入');
})();
```