@sgysldz/anti-debug 1.0.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/README.md +173 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +257 -0
- package/dist/index.js +1 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# anti-debug
|
|
2
|
+
|
|
3
|
+
浏览器端**防调试 / 降低窥探便利度**的轻量工具库(TypeScript)。通过启发式检测「调试器暂停」与「DevTools 可能已打开」,并在命中时回调业务逻辑;可选弱化 `console` 输出。
|
|
4
|
+
|
|
5
|
+
> **重要**:前端代码**无法**做到不可被逆向或不可被阅读。本库仅**提高成本**,不能替代服务端鉴权、密钥不下发、构建混淆、关闭生产 Source Map 等工程措施。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 功能概览
|
|
10
|
+
|
|
11
|
+
| 能力 | 说明 |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| **定时守护** | `startAntiDebugGuard` 按间隔执行多项检测,命中时调用 `onThreat(reason)` |
|
|
14
|
+
| **debugger 耗时** | `detectDebuggerTiming`:利用 `debugger` 断点处前后时间差异常 |
|
|
15
|
+
| **窗口 / 视口** | `detectDevToolsByDimensions`:`outer-inner` + 根元素 / `visualViewport` 差值(**不依赖断点**) |
|
|
16
|
+
| **console 耗时(可选)** | `detectDevToolsByConsoleTiming`:DevTools 打开时常更慢(默认关,防误报) |
|
|
17
|
+
| **本机跳过** | `skipInDevelopment` + `isLikelyLocalDevHost`,避免本地开发时被频繁打断 |
|
|
18
|
+
| **noop console** | `installNoopConsole`:可选替换常见 `console.*` 为空实现 |
|
|
19
|
+
| **快捷键 / 右键** | `installDevToolsUiBlock` 或 `startAntiDebugGuard({ uiBlock: true })`:拦 F12、Ctrl+Shift+I/J/C 等;可选拦右键、Ctrl+U |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 安装
|
|
24
|
+
|
|
25
|
+
在 monorepo 中依赖工作区包(示例):
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"anti-debug": "workspace:*"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pnpm add anti-debug@workspace:* -F your-app
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 快速开始
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { startAntiDebugGuard, installNoopConsole } from "anti-debug"
|
|
45
|
+
|
|
46
|
+
// 可选:弱化控制台(记得在需要调试时注释掉或条件编译)
|
|
47
|
+
const restoreConsole = installNoopConsole()
|
|
48
|
+
|
|
49
|
+
const guard = startAntiDebugGuard({
|
|
50
|
+
intervalMs: 2500,
|
|
51
|
+
// 本地 localhost 不跑守护,正式域名照常检测
|
|
52
|
+
skipInDevelopment: true,
|
|
53
|
+
// 拦 F12、Ctrl+Shift+I/J/C 等;默认不拦整页右键,需则传 { blockContextMenu: true }
|
|
54
|
+
uiBlock: true,
|
|
55
|
+
onThreat(reason) {
|
|
56
|
+
// reason: 'debugger-timing' | 'devtools-dimensions' | 'devtools-console-timing'
|
|
57
|
+
// 自行实现:跳转、清 DOM、上报等(本库不内置网络请求)
|
|
58
|
+
window.location.replace("/")
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
// 单页应用卸载或不再需要时
|
|
63
|
+
// guard.stop();
|
|
64
|
+
// restoreConsole();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## API 说明
|
|
70
|
+
|
|
71
|
+
### `startAntiDebugGuard(options?)`
|
|
72
|
+
|
|
73
|
+
- **环境**:仅在存在 `window` 的浏览器中启动 `setInterval`;Node / 无 `window` 时返回 `{ stop: () => {} }`,不抛错。
|
|
74
|
+
- **`intervalMs`**:轮询间隔,默认 `2000`。
|
|
75
|
+
- **`immediate`**:是否在挂载后立即执行第一次检测,默认 `true`。
|
|
76
|
+
- **`skipInDevelopment`**:为 `true` 且当前 hostname 为常见本机地址(见下)时,**不启动**守护。
|
|
77
|
+
- **`checks`**:可关闭 `debuggerTiming` / `devToolsDimensions`;`devToolsConsoleTiming` 默认**关闭**,需显式 `true`。
|
|
78
|
+
- **`devToolsThresholds`**:微调 `widthGap` / `heightGap` / `layoutGap` / `consoleTimingMs`(漏报时可略调低前两项)。
|
|
79
|
+
- **`uiBlock`**:`true` 或 `DevToolsUiBlockOptions` 对象;与 `skipInDevelopment` 同时生效时,本机 hostname 下**不**安装(与轮询一致)。`stop()` 时会一并卸载快捷键监听。
|
|
80
|
+
- **`onThreat(reason)`**:有检测为阳性时调用;未传则仅轮询,不执行任何默认破坏操作。
|
|
81
|
+
|
|
82
|
+
### `AntiDebugReason`(`reason` 取值)
|
|
83
|
+
|
|
84
|
+
| 值 | 含义 |
|
|
85
|
+
| ------------------------- | -------------------------------------------------------- |
|
|
86
|
+
| `debugger-timing` | `detectDebuggerTiming` 认为执行在断点/调试器下被显著拖慢 |
|
|
87
|
+
| `devtools-dimensions` | 视口 / 尺寸启发式认为像已打开 DevTools(dock 场景为主) |
|
|
88
|
+
| `devtools-console-timing` | 可选;`console` 单次调用耗时偏高(与「停用断点」无关) |
|
|
89
|
+
|
|
90
|
+
### `detectDebuggerTiming(thresholdMs?)`
|
|
91
|
+
|
|
92
|
+
- 默认 `thresholdMs = 120`。耗时超过该值返回 `true`。
|
|
93
|
+
- 内含 **`debugger` 语句**:若被 ESLint 禁止,需在项目规则中对本库或本行做例外。
|
|
94
|
+
|
|
95
|
+
### `detectDevToolsByDimensions(options?)` 或 `(widthGap, heightGap)`
|
|
96
|
+
|
|
97
|
+
- **对象形式**:可传 `widthGapThreshold`、`heightGapThreshold`、`layoutGapThreshold`(默认 `160` / `300` / `100`),并包含对 `innerWidth - clientWidth`、`visualViewport` 与内视口的辅助判断。
|
|
98
|
+
- **两数字形式**:与旧版兼容,等价于仅调整 outer-inner 阈值。
|
|
99
|
+
- **「停用断点」**:不会执行 `debugger`,故 **`debugger-timing` 会漏报**;可依赖本项与可选的 `detectDevToolsByConsoleTiming`。
|
|
100
|
+
- DevTools **独立窗口 undock** 时主页面尺寸往往不变 → 纯前端**无法可靠**检测,只能依赖服务端或其它手段。
|
|
101
|
+
|
|
102
|
+
### `detectDevToolsByConsoleTiming(thresholdMs?)`
|
|
103
|
+
|
|
104
|
+
- 默认 `5` ms;仅建议在 `checks: { devToolsConsoleTiming: true }` 时由守护调用;单独使用亦可。
|
|
105
|
+
- 可能有误报,请结合业务与 `devToolsThresholds.consoleTimingMs` 调整。
|
|
106
|
+
|
|
107
|
+
### `isLikelyLocalDevHost()`
|
|
108
|
+
|
|
109
|
+
在 `location` 存在时,匹配:`localhost`、`127.0.0.1`、`[::1]`、`0.0.0.0`,以及以 `.local` 结尾的主机名。
|
|
110
|
+
|
|
111
|
+
### `installNoopConsole(options?)`
|
|
112
|
+
|
|
113
|
+
- 默认替换常见输出类方法;返回**卸载函数**,务必在测试或需要控制台时调用恢复。
|
|
114
|
+
|
|
115
|
+
### `installDevToolsUiBlock(options?)`
|
|
116
|
+
|
|
117
|
+
- 在 `window` 上注册**捕获阶段** `keydown`,默认拦截:**F12**;**Ctrl+Shift+I/J/C/K/E**(Windows/Linux);**Cmd+Option+I/J/C**、**Cmd+Shift+C**(Mac 常见)。
|
|
118
|
+
- 可选:`blockContextMenu: true` 拦截整页右键;`blockViewSource: true` 拦截 **Ctrl+U** 查看源代码。
|
|
119
|
+
- **无法**拦截:浏览器菜单「更多工具 → 开发者工具」、扩展、远程调试、从书签/其它页已打开的 DevTools 等。
|
|
120
|
+
- 返回卸载函数;也可通过 `startAntiDebugGuard({ uiBlock: true })` 自动安装并在 `stop()` 时卸载。
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 局限与误报
|
|
125
|
+
|
|
126
|
+
1. **「Deactivate breakpoints / 停用断点」与「Resume」**:`debugger` 不暂停时,`debugger-timing` **必然漏报**——这是浏览器行为,不是库 bug。请依赖 **`devtools-dimensions`**,并视情况开启 **`devToolsConsoleTiming`** 或调低 `devToolsThresholds.widthGap` / `heightGap`。
|
|
127
|
+
2. **DevTools 独立窗口**:主页面 `outer/inner` 可能不变 → 尺寸类检测**常漏报**;纯前端无完美对策。
|
|
128
|
+
3. **尺寸 / console 检测**:分屏、缩放、扩展、省电模式等 → 误报或漏报均可能存在。
|
|
129
|
+
4. **性能**:轮询与 `debugger` / `console` 检测占用主线程,间隔不宜过小。
|
|
130
|
+
5. **合规与体验**:过度惩罚可能伤害正常用户;请谨慎设计 `onThreat`。
|
|
131
|
+
6. **快捷键拦截**:仅挡常见快捷键;无障碍与高级用户仍可通过菜单或其它方式打开 DevTools,勿当作安全边界。
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 构建
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
pnpm --filter anti-debug build
|
|
139
|
+
pnpm --filter anti-debug check-types
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
产物目录 `dist/` **仅两个文件**(单文件分发):
|
|
143
|
+
|
|
144
|
+
- `index.js`:单入口 `rolldown` 打成一个 chunk,再经 `javascript-obfuscator` 处理;
|
|
145
|
+
- `index.d.ts`:`dts-bundle-generator` 自 `src/index.ts` 合并生成的单文件类型声明(与 `package.json` 的 `types` / `exports` 对齐)。
|
|
146
|
+
|
|
147
|
+
构建开始时会清空 `dist/`,避免历史构建遗留的多份 `.d.ts`。
|
|
148
|
+
|
|
149
|
+
若根目录 `.gitignore` 忽略了 `dist/`,则构建产物不入库;克隆后需先执行 `pnpm --filter anti-debug build`,依赖方才能解析类型与运行时代码。
|
|
150
|
+
|
|
151
|
+
### 压缩与混淆说明
|
|
152
|
+
|
|
153
|
+
1. **Rolldown(Oxc Minifier)**:`minify` 开启完整压缩与名称混淆;**必须**设置 `compress.dropDebugger: false`,否则默认会删除源码中的 `debugger`,`detectDebuggerTiming` 会失效。
|
|
154
|
+
2. **javascript-obfuscator**:对打包结果做字符串阵列、Base64 编码等增强混淆;未开启控制流平坦化/自防御等,以降低体积与误伤风险。
|
|
155
|
+
|
|
156
|
+
若只需 Rolldown 压缩、不要第二层混淆,可将 `package.json` 中 `build` 改为仅 `rolldown -c`。
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 与其他措施的关系
|
|
161
|
+
|
|
162
|
+
| 措施 | 说明 |
|
|
163
|
+
| ---- | ---------------------------------------- |
|
|
164
|
+
| 本库 | 运行时启发式,可组合埋点与温和响应 |
|
|
165
|
+
| 构建 | 压缩、混淆、关闭生产 Source Map |
|
|
166
|
+
| 架构 | 敏感逻辑与密钥放在服务端;前端仅展示结果 |
|
|
167
|
+
| 合规 | 遵循当地法律与用户协议,勿用于恶意目的 |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 许可证
|
|
172
|
+
|
|
173
|
+
ISC(与 `package.json` 保持一致)。
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(_0x2b6053,_0xa30b78){const _0x593e1a=_0x2b6053();function _0x4ccb13(_0x123707,_0x4f3177){return _0x3386(_0x4f3177-0x2c4,_0x123707);}while(!![]){try{const _0x1285bc=parseInt(_0x4ccb13(0x4c8,0x4a3))/0x1+parseInt(_0x4ccb13(0x487,0x4b5))/0x2*(parseInt(_0x4ccb13(0x4cc,0x4bb))/0x3)+-parseInt(_0x4ccb13(0x457,0x472))/0x4*(parseInt(_0x4ccb13(0x496,0x477))/0x5)+parseInt(_0x4ccb13(0x4bc,0x499))/0x6+-parseInt(_0x4ccb13(0x4d6,0x4b1))/0x7+parseInt(_0x4ccb13(0x484,0x48a))/0x8+-parseInt(_0x4ccb13(0x4d1,0x4a9))/0x9;if(_0x1285bc===_0xa30b78)break;else _0x593e1a['push'](_0x593e1a['shift']());}catch(_0xd48c2a){_0x593e1a['push'](_0x593e1a['shift']());}}}(_0x4341,0x3e989),Object[_0x56192b(0xe3,0x103)](exports,Symbol[_0x56192b(0xf6,0xd0)],{'value':_0x56192b(0xa4,0xca)}));function _0x56192b(_0x4ada05,_0x186e9d){return _0x3386(_0x4ada05- -0x10c,_0x186e9d);}function e(_0x5db8d8=0x78){function _0x27dbc9(_0xf8eb4f,_0x52c940){return _0x56192b(_0x52c940- -0x176,_0xf8eb4f);}if(typeof performance>'u')return!0x1;let _0x459335=performance[_0x27dbc9(-0x6c,-0x7c)]();debugger;return performance[_0x27dbc9(-0x8a,-0x7c)]()-_0x459335>_0x5db8d8;}function t(_0x3b30d9,_0xe36594,_0x3d43bc){if(typeof window>'u')return!0x1;function _0x35b214(_0x217d1,_0xef607){return _0x56192b(_0xef607-0x66,_0x217d1);}let _0x5a0bc8=window[_0x35b214(0xfb,0x127)]-window['innerWidth'],_0x515535=window[_0x35b214(0x153,0x124)]-window['innerHeight'];if(_0x5a0bc8>_0x3b30d9||_0x515535>_0xe36594)return!0x0;let _0x3d269e=document['documentElement'];if(_0x3d269e){let _0x11ba2d=window[_0x35b214(0xf7,0x123)]-_0x3d269e[_0x35b214(0x167,0x13a)],_0x513d3d=window[_0x35b214(0x17b,0x14d)]-_0x3d269e[_0x35b214(0x11e,0x11b)];if(_0x11ba2d>_0x3d43bc||_0x513d3d>_0x3d43bc)return!0x0;}let _0x5c484a=window[_0x35b214(0x12c,0x113)];if(_0x5c484a&&window[_0x35b214(0x131,0x123)]>0x1e0){let _0x39ced5=Math[_0x35b214(0x138,0x126)](window[_0x35b214(0x14a,0x123)]-_0x5c484a[_0x35b214(0x116,0x10e)]),_0x434711=Math[_0x35b214(0x14e,0x126)](window['innerHeight']-_0x5c484a[_0x35b214(0x15f,0x140)]);if(_0x39ced5>_0x3d43bc||_0x434711>_0x3d43bc)return!0x0;}return!0x1;}function n(_0x3463ae,_0x35c51e=0x12c){function _0x5db6fd(_0x52903e,_0x26d35){return _0x56192b(_0x26d35-0xdd,_0x52903e);}if(typeof _0x3463ae=='number')return t(_0x3463ae,_0x35c51e,0x64);let _0x1b7ddf=_0x3463ae??{};return t(_0x1b7ddf['widthGapThreshold']??0xa0,_0x1b7ddf['heightGapThreshold']??0x12c,_0x1b7ddf[_0x5db6fd(0x1a6,0x1b5)]??0x64);}function r(_0x6bceae=0x5){if(typeof performance>'u'||typeof console>'u')return!0x1;function _0x1c26ac(_0x53962f,_0x1fdea9){return _0x56192b(_0x1fdea9- -0x187,_0x53962f);}let _0x202f40=performance[_0x1c26ac(-0x6f,-0x8d)]();return console[_0x1c26ac(-0x80,-0x8f)](''),performance['now']()-_0x202f40>_0x6bceae;}function _0x3386(_0x3db30c,_0x46c6b4){_0x3db30c=_0x3db30c-0x1ad;const _0x4341cd=_0x4341();let _0x338605=_0x4341cd[_0x3db30c];if(_0x3386['dOWJBg']===undefined){var _0xd6d4a9=function(_0x41e15a){const _0x17d6be='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x5db8d8='',_0x459335='';for(let _0x3b30d9=0x0,_0xe36594,_0x3d43bc,_0x5a0bc8=0x0;_0x3d43bc=_0x41e15a['charAt'](_0x5a0bc8++);~_0x3d43bc&&(_0xe36594=_0x3b30d9%0x4?_0xe36594*0x40+_0x3d43bc:_0x3d43bc,_0x3b30d9++%0x4)?_0x5db8d8+=String['fromCharCode'](0xff&_0xe36594>>(-0x2*_0x3b30d9&0x6)):0x0){_0x3d43bc=_0x17d6be['indexOf'](_0x3d43bc);}for(let _0x515535=0x0,_0x3d269e=_0x5db8d8['length'];_0x515535<_0x3d269e;_0x515535++){_0x459335+='%'+('00'+_0x5db8d8['charCodeAt'](_0x515535)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x459335);};_0x3386['CBBBnq']=_0xd6d4a9,_0x3386['ZNCBfq']={},_0x3386['dOWJBg']=!![];}const _0x4277b2=_0x4341cd[0x0],_0x35c8a6=_0x3db30c+_0x4277b2,_0xb8be36=_0x3386['ZNCBfq'][_0x35c8a6];return!_0xb8be36?(_0x338605=_0x3386['CBBBnq'](_0x338605),_0x3386['ZNCBfq'][_0x35c8a6]=_0x338605):_0x338605=_0xb8be36,_0x338605;}function i(){function _0x41efcb(_0x6a5685,_0xc4af7b){return _0x56192b(_0x6a5685- -0x25d,_0xc4af7b);}if(typeof location>'u')return!0x1;let _0x3de022=location['hostname'][_0x41efcb(-0x18c,-0x184)]();return _0x3de022===_0x41efcb(-0x1ad,-0x1b6)||_0x3de022===_0x41efcb(-0x186,-0x19e)||_0x3de022===_0x41efcb(-0x188,-0x172)||_0x3de022===_0x41efcb(-0x190,-0x1bc)||_0x3de022[_0x41efcb(-0x187,-0x179)](_0x41efcb(-0x1ba,-0x19b));}function _0x4341(){const _0x4eff03=['Bgf5B3v0r2fW','yMXVy2Tgmti','DMLZDwfSvMLLD3bVCNq','A2v5zg93BG','Aw5ZDgfSBerLDLrVB2XZvwLcBg9JAW','Bg9JywXOB3n0','Aw5ZDgfSBe5VB3bdB25ZB2XL','CMvTB3zLrxzLBNrmAxn0zw5LCG','ChjLDMvUDerLzMf1Bhq','Bg9N','y2XPzw50sgvPz2H0','ywX0s2v5','zgv2vg9VBhndB25ZB2XLvgLTAw5N','B25uAhjLyxq','zgvIDwDNzxjuAw1PBMC','mJqXndGXnLDbEuHjAq','z3jVDxa','Aw5MBW','Aw5UzxjxAwr0Aa','B3v0zxjizwLNAhq','C2HPzNrlzxK','ywjZ','B3v0zxjxAwr0Aa','C2v0','rJeY','DwLcBg9JAW','z3jVDxbdB2XSyxbZzwq','zgLY','s2v5rq','DhjHy2u','oty2mdz1uxLyDvG','D2LKDgHhyxa','yMLUza','zgv2vg9VBhneAw1LBNnPB25Z','mc4WlJaUma','C3rHCNrbBNrPrgvIDwDhDwfYza','yMXVy2TwAwv3u291CMnL','Aw50zxj2ywXnCW','Dg9mB3DLCKnHC2u','y29UC29SzvrPBwLUz01Z','mZyWmZj1yNfVB2y','y2XPzw50v2LKDgG','wZO6mv0','zw5KC1DPDgG','mti3lJaUmc4X','Bgf5B3v0r2fWvgHYzxnOB2XK','mZGWnte5mxvMwMrIDW','AgvPz2H0','Aw5JBhvKzxm','yMXVy2TlzxLIB2fYzfnOB3j0y3v0CW','zgv0zwn0rgvIDwDNzxjuAw1PBMC','C3rVCfbYB3bHz2f0Aw9U','zgv0zwn0rgv2vg9VBhncEunVBNnVBgvuAw1PBMC','y2HLy2TZ','nJq5mtGWA1fqt3L5','Bwv0yuTLEq','zgvMAw5LuhjVCgvYDhK','zxjYB3i','ng9iu0PqrG','s2v5sW','Aw5UzxjizwLNAhq','zgv2Dg9VBhmTzgLTzw5ZAw9UCW','z3jVDxbfBMq','z2v0','nZmZotK1t2LQrKfN','y3rYBeTLEq','zNvUy3rPB24','s2v5sq','zgLYEg1S','ywrKrxzLBNrmAxn0zw5LCG','Aw1TzwrPyxrL','s2v5qW','C2TPCeLUrgv2zwXVCg1LBNq','A2v5','s2v5vq','Dg9tDhjPBMDuywC','D2fYBG','zgvIDwC','s2v5sG','BM93','y29Kzq','zgv2Dg9VBhmTy29UC29Szs10Aw1PBMC','Bwv0Ag9KCW','yxnZzxj0','mJe5nJrfz3LovuG','lMXVy2fS','tw9KDwXL','AgvPz2H0r2fW','zgv0zwn0rgv2vg9VBhncEurPBwvUC2LVBNm','nJvoCKjSugG','D2LKDgG','yMXVy2TdB250zxH0twvUDq','zgvIDwDNzxiTDgLTAw5N'];_0x4341=function(){return _0x4eff03;};return _0x4341();}const a=[_0x56192b(0xee,0xd9),_0x56192b(0xf9,0xd8),_0x56192b(0xf2,0x110),_0x56192b(0xe6,0xbb),_0x56192b(0xc7,0xdd)];function o(_0x3d1045){function _0x54e1a5(_0x27ee7c,_0x243552){return _0x56192b(_0x243552-0x2fe,_0x27ee7c);}return _0x3d1045[_0x54e1a5(0x417,0x3ea)]&&_0x3d1045['shiftKey']&&!_0x3d1045[_0x54e1a5(0x398,0x3b4)]&&!_0x3d1045[_0x54e1a5(0x3cd,0x3e0)]?a[_0x54e1a5(0x3ab,0x3d9)](_0x3d1045[_0x54e1a5(0x3d8,0x3f9)]):!!(_0x3d1045[_0x54e1a5(0x3b3,0x3e0)]&&_0x3d1045[_0x54e1a5(0x39b,0x3b4)]&&!_0x3d1045['shiftKey']&&['KeyI',_0x54e1a5(0x404,0x3f7),_0x54e1a5(0x3f4,0x3f0)]['includes'](_0x3d1045[_0x54e1a5(0x3fe,0x3f9)])||_0x3d1045[_0x54e1a5(0x3c3,0x3e0)]&&_0x3d1045[_0x54e1a5(0x3d4,0x3bd)]&&_0x3d1045[_0x54e1a5(0x3ea,0x3f9)]===_0x54e1a5(0x40b,0x3f0));}function s(_0x3159f9){function _0x2e09a9(_0xeecde9,_0x19d9e3){return _0x56192b(_0xeecde9- -0x278,_0x19d9e3);}return{'blockF12':_0x3159f9[_0x2e09a9(-0x1cc,-0x1ac)]!==!0x1,'blockKeyboardShortcuts':_0x3159f9[_0x2e09a9(-0x19c,-0x1bb)]!==!0x1,'blockContextMenu':_0x3159f9[_0x2e09a9(-0x1cf,-0x1f6)]===!0x0,'blockViewSource':_0x3159f9[_0x2e09a9(-0x1a9,-0x1cb)]===!0x0};}function c(_0xad65c5={}){if(typeof window>'u')return()=>{};function _0x4fc8b9(_0x17ff73,_0x54ef8a){return _0x56192b(_0x17ff73-0x40e,_0x54ef8a);}let _0x105494=s(_0xad65c5),_0x50512c=_0x2e380b=>{if(_0x105494[_0x225760(-0x101,-0xe2)]&&(_0x2e380b[_0x225760(-0x78,-0x93)]===_0x225760(-0x9e,-0xcb)||_0x2e380b[_0x225760(-0x77,-0x9a)]===_0x225760(-0xa7,-0xcb))){_0x2e380b[_0x225760(-0xbc,-0xdb)](),_0x2e380b['stopPropagation']();return;}if(_0x105494[_0x225760(-0x96,-0xbf)]&&_0x2e380b['ctrlKey']&&!_0x2e380b[_0x225760(-0xd3,-0xcf)]&&!_0x2e380b['altKey']&&!_0x2e380b[_0x225760(-0xad,-0xac)]&&_0x2e380b[_0x225760(-0xaf,-0x93)]===_0x225760(-0x76,-0x99)){_0x2e380b[_0x225760(-0xf6,-0xdb)](),_0x2e380b['stopPropagation']();return;}function _0x225760(_0x7fc532,_0x2c42cf){return _0x3386(_0x2c42cf- -0x29a,_0x7fc532);}_0x105494['blockKeyboardShortcuts']&&o(_0x2e380b)&&(_0x2e380b[_0x225760(-0xfa,-0xdb)](),_0x2e380b[_0x225760(-0xc6,-0xb0)]());},_0x2132e3=_0x5ba940=>{_0x5ba940['preventDefault']();};return window[_0x4fc8b9(0x4fe,0x521)]('keydown',_0x50512c,!0x0),_0x105494['blockContextMenu']&&window[_0x4fc8b9(0x4fe,0x4d7)]('contextmenu',_0x2132e3,!0x0),()=>{function _0x334c79(_0x130729,_0xa1587c){return _0x4fc8b9(_0x130729- -0xde,_0xa1587c);}window[_0x334c79(0x3e2,0x3bc)](_0x334c79(0x3de,0x3fd),_0x50512c,!0x0),_0x105494[_0x334c79(0x3d9,0x3e5)]&&window[_0x334c79(0x3e2,0x3b4)]('contextmenu',_0x2132e3,!0x0);};}function l(_0x471422){function _0x21672f(_0x4578f5,_0x3b09e7){return _0x56192b(_0x4578f5-0x47c,_0x3b09e7);}return{'debuggerTiming':_0x471422?.[_0x21672f(0x535,0x52b)]!==!0x1,'devToolsDimensions':_0x471422?.[_0x21672f(0x548,0x54e)]!==!0x1,'devToolsConsoleTiming':_0x471422?.[_0x21672f(0x533,0x536)]===!0x0};}function u(_0x47748f){function _0x3aa84e(_0x7f702a,_0x3331a3){return _0x56192b(_0x3331a3- -0x290,_0x7f702a);}return{'widthGapThreshold':_0x47748f?.[_0x3aa84e(-0x1c7,-0x1c6)],'heightGapThreshold':_0x47748f?.[_0x3aa84e(-0x20f,-0x1eb)],'layoutGapThreshold':_0x47748f?.[_0x3aa84e(-0x1df,-0x1e5)]};}function d(_0x8b8142,_0x579db1){function _0x2be7d4(_0x4af0bd,_0x3751db){return _0x56192b(_0x3751db-0x24f,_0x4af0bd);}return _0x8b8142[_0x2be7d4(0x2f9,0x308)]&&e()?_0x2be7d4(0x2de,0x2f9):_0x8b8142[_0x2be7d4(0x328,0x31b)]&&n(u(_0x579db1))?_0x2be7d4(0x349,0x337):_0x8b8142[_0x2be7d4(0x304,0x306)]&&r(_0x579db1?.[_0x2be7d4(0x33c,0x321)]??0x5)?_0x2be7d4(0x375,0x34b):null;}function f(_0x586ee8={}){if(typeof window>'u')return{'stop':()=>{}};function _0x3d9d6d(_0x3a0bef,_0x14b881){return _0x56192b(_0x3a0bef- -0x208,_0x14b881);}let _0x4bd1f3=_0x586ee8[_0x3d9d6d(-0x138,-0x164)]??0x7d0,_0x1c2840=_0x586ee8[_0x3d9d6d(-0x117,-0x133)]!==!0x1;if(_0x586ee8[_0x3d9d6d(-0x115,-0xf4)]===!0x0&&i())return{'stop':()=>{}};let _0x3fbcc9;_0x586ee8[_0x3d9d6d(-0x144,-0x12f)]&&(_0x3fbcc9=c(_0x586ee8[_0x3d9d6d(-0x144,-0x135)]===!0x0?{}:_0x586ee8[_0x3d9d6d(-0x144,-0x162)]));let _0x193893=l(_0x586ee8[_0x3d9d6d(-0x128,-0x120)]),_0x17d2c3,_0x46d811=()=>{function _0x51661e(_0x3a6641,_0x317801){return _0x3d9d6d(_0x3a6641-0x300,_0x317801);}let _0x3a777f=d(_0x193893,_0x586ee8['devToolsThresholds']);_0x3a777f&&_0x586ee8[_0x51661e(0x1b0,0x184)]&&_0x586ee8[_0x51661e(0x1b0,0x1d6)](_0x3a777f);};return _0x1c2840&&_0x46d811(),_0x17d2c3=setInterval(_0x46d811,_0x4bd1f3),{'stop':()=>{_0x17d2c3!==void 0x0&&(clearInterval(_0x17d2c3),_0x17d2c3=void 0x0),_0x3fbcc9?.(),_0x3fbcc9=void 0x0;}};}const p=[_0x56192b(0xb4,0xce),_0x56192b(0xf8,0x10d),_0x56192b(0xbc,0x96),_0x56192b(0xf7,0x123),_0x56192b(0xe4,0xdc),_0x56192b(0xc8,0xca),_0x56192b(0xc6,0x9b),_0x56192b(0xef,0xda),'table',_0x56192b(0xbb,0xad),_0x56192b(0xc5,0xe2),_0x56192b(0xe9,0xd5),_0x56192b(0xa1,0xcc)];function m(_0x35d388={}){if(typeof console>'u')return()=>{};let _0x1e5e1a=_0x35d388[_0x58bc42(-0x119,-0x10c)]??p,_0x2e088f=new Map();for(let _0x5ce026 of _0x1e5e1a){let _0x449434=console[_0x5ce026];typeof _0x449434==_0x58bc42(-0x146,-0x11c)&&(_0x2e088f[_0x58bc42(-0x149,-0x147)](_0x5ce026,_0x449434[_0x58bc42(-0x150,-0x13e)](console)),console[_0x5ce026]=()=>{});}function _0x58bc42(_0x35dd06,_0x1444ed){return _0x56192b(_0x1444ed- -0x209,_0x35dd06);}return()=>{function _0x7350a4(_0x26292c,_0x5aa9e2){return _0x58bc42(_0x26292c,_0x5aa9e2-0x2af);}for(let _0x5edb8b of _0x1e5e1a){let _0x43689e=_0x2e088f[_0x7350a4(0x171,0x190)](_0x5edb8b);_0x43689e&&(console[_0x5edb8b]=_0x43689e);}};}exports[_0x56192b(0xdd,0xc5)]=e,exports[_0x56192b(0xdf,0x109)]=r,exports[_0x56192b(0xa6,0xab)]=n,exports[_0x56192b(0xaf,0xaf)]=c,exports[_0x56192b(0xb1,0xb9)]=m,exports['isLikelyLocalDevHost']=i,exports[_0x56192b(0xce,0xb1)]=f;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 当 {@link startAntiDebugGuard} 中某项检测判定为「可疑」时,通过
|
|
3
|
+
* {@link AntiDebugOptions.onThreat} 传入的原因标识,便于区分策略或埋点。
|
|
4
|
+
*/
|
|
5
|
+
export type AntiDebugReason =
|
|
6
|
+
/** {@link detectDebuggerTiming} 认为执行在断点/调试器下被显著拖慢 */
|
|
7
|
+
"debugger-timing"
|
|
8
|
+
/** {@link detectDevToolsByDimensions} 认为窗口/视口尺寸特征像已打开 DevTools */
|
|
9
|
+
| "devtools-dimensions"
|
|
10
|
+
/** {@link detectDevToolsByConsoleTiming} 认为 `console` 调用异常偏慢(与断点无关;默认不启用) */
|
|
11
|
+
| "devtools-console-timing";
|
|
12
|
+
/**
|
|
13
|
+
* 分项开关:可单独关闭某一类检测,减轻误报或降低性能开销。
|
|
14
|
+
*
|
|
15
|
+
* 默认两项均为开启(等价于未传 `checks` 或各字段为 `true`)。
|
|
16
|
+
* 显式设为 `false` 可关闭对应检测。
|
|
17
|
+
*/
|
|
18
|
+
export interface AntiDebugChecks {
|
|
19
|
+
/**
|
|
20
|
+
* 是否启用「debugger 耗时」检测。
|
|
21
|
+
* @default true(未传或 `undefined` 时视为开启)
|
|
22
|
+
*/
|
|
23
|
+
debuggerTiming?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* 是否启用「窗口 / 视口 / 根元素尺寸差」检测(DevTools dock 场景;**不依赖断点**)。
|
|
26
|
+
* @default true
|
|
27
|
+
*/
|
|
28
|
+
devToolsDimensions?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* 是否启用「console 调用耗时」检测(DevTools 打开时常更慢;**与「停用断点」无关**)。
|
|
31
|
+
* 误报相对多,默认关闭;需更强提示时再开。
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
devToolsConsoleTiming?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* {@link installDevToolsUiBlock} / {@link AntiDebugOptions.uiBlock} 的配置。
|
|
38
|
+
*
|
|
39
|
+
* 未写字段在实现里按「尽量拦截快捷键、尽量不挡右键」处理。
|
|
40
|
+
*/
|
|
41
|
+
export interface DevToolsUiBlockOptions {
|
|
42
|
+
/**
|
|
43
|
+
* 是否拦截 **F12**。
|
|
44
|
+
* @default true
|
|
45
|
+
*/
|
|
46
|
+
blockF12?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 是否拦截常见组合键(如 Ctrl+Shift+I/J/C、Mac Cmd+Opt+I 等)。
|
|
49
|
+
* @default true
|
|
50
|
+
*/
|
|
51
|
+
blockKeyboardShortcuts?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* 是否拦截**整个页面**的右键菜单(含非 DevTools 场景)。
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
blockContextMenu?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* 是否拦截 **Ctrl+U**(查看网页源代码)。
|
|
59
|
+
* @default false
|
|
60
|
+
*/
|
|
61
|
+
blockViewSource?: boolean;
|
|
62
|
+
}
|
|
63
|
+
/** {@link AntiDebugOptions.devToolsThresholds} 的字段说明 */
|
|
64
|
+
export interface AntiDebugDevToolsThresholds {
|
|
65
|
+
/** 传给 {@link detectDevToolsByDimensions} 的 `widthGapThreshold` */
|
|
66
|
+
widthGap?: number;
|
|
67
|
+
/** 传给 {@link detectDevToolsByDimensions} 的 `heightGapThreshold` */
|
|
68
|
+
heightGap?: number;
|
|
69
|
+
/** 传给 {@link detectDevToolsByDimensions} 的 `layoutGapThreshold` */
|
|
70
|
+
layoutGap?: number;
|
|
71
|
+
/** 传给 {@link detectDevToolsByConsoleTiming} 的毫秒阈值 */
|
|
72
|
+
consoleTimingMs?: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* {@link startAntiDebugGuard} 的完整配置。
|
|
76
|
+
*
|
|
77
|
+
* **注意**:所有检测均为启发式,不能替代服务端鉴权或代码混淆;
|
|
78
|
+
* 仅用于提高前端被随意调试、窥探的成本。
|
|
79
|
+
*/
|
|
80
|
+
export interface AntiDebugOptions {
|
|
81
|
+
/**
|
|
82
|
+
* 两次完整检测轮询之间的间隔(毫秒)。
|
|
83
|
+
* 过小会增加主线程占用与用户耗电感知;过大则反应变慢。
|
|
84
|
+
* @default 2000
|
|
85
|
+
*/
|
|
86
|
+
intervalMs?: number;
|
|
87
|
+
/**
|
|
88
|
+
* 是否在启动守护后立即执行第一次检测(不等待首个 `interval`)。
|
|
89
|
+
* 若设为 `false`,仅按 `intervalMs` 周期执行。
|
|
90
|
+
* @default true
|
|
91
|
+
*/
|
|
92
|
+
immediate?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* 任一启用的检测返回阳性时调用。常见用途:
|
|
95
|
+
* - 跳转空白页或登录页
|
|
96
|
+
* - 移除敏感 DOM、清空内存中的临时密钥展示
|
|
97
|
+
* - 向自有服务端上报(需自行实现请求,本库不内置网络)
|
|
98
|
+
*
|
|
99
|
+
* 未提供时,检测仍会周期性执行,但不会触发任何回调(可用于仅做埋点以外的场景时自行组合)。
|
|
100
|
+
*/
|
|
101
|
+
onThreat?: (reason: AntiDebugReason) => void;
|
|
102
|
+
/**
|
|
103
|
+
* 为 `true` 时:若当前页面 hostname 被 {@link isLikelyLocalDevHost}
|
|
104
|
+
* 判为常见本机开发地址(如 `localhost`),则**不启动**守护,避免本地调试时被频繁打断。
|
|
105
|
+
*
|
|
106
|
+
* 部署到正式域名后,该判断通常为 `false`,检测会正常生效。
|
|
107
|
+
* 若你希望连本机也强制执行检测,保持默认(`false`)即可。
|
|
108
|
+
* @default false
|
|
109
|
+
*/
|
|
110
|
+
skipInDevelopment?: boolean;
|
|
111
|
+
/** 见 {@link AntiDebugChecks} */
|
|
112
|
+
checks?: AntiDebugChecks;
|
|
113
|
+
/**
|
|
114
|
+
* 微调 DevTools 相关启发式阈值(漏报多时可略调低 `widthGap` / `heightGap`;误报多则调大)。
|
|
115
|
+
* 未指定的项使用库内默认值。
|
|
116
|
+
*/
|
|
117
|
+
devToolsThresholds?: AntiDebugDevToolsThresholds;
|
|
118
|
+
/**
|
|
119
|
+
* 是否拦截 F12 / 常见打开 DevTools 的快捷键(及可选右键、Ctrl+U)。
|
|
120
|
+
* - `true`:使用默认(拦 F12 + 快捷键;**不**默认拦右键,避免整站右键失效)。
|
|
121
|
+
* - 对象:见 {@link DevToolsUiBlockOptions}。
|
|
122
|
+
*
|
|
123
|
+
* 与 {@link skipInDevelopment} 同时为真且处于本机 hostname 时,**不会**安装(与轮询检测一致)。
|
|
124
|
+
*/
|
|
125
|
+
uiBlock?: boolean | DevToolsUiBlockOptions;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* {@link startAntiDebugGuard} 的返回值:用于在适当时机停止轮询(例如单页应用卸载、用户登出)。
|
|
129
|
+
*/
|
|
130
|
+
export interface AntiDebugHandle {
|
|
131
|
+
/**
|
|
132
|
+
* 清除内部 `setInterval`,之后不再执行检测。
|
|
133
|
+
* 可重复调用,无副作用。
|
|
134
|
+
*/
|
|
135
|
+
stop: () => void;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* 启动防调试守护:在浏览器主线程上以 `setInterval` 周期性执行检测。
|
|
139
|
+
*
|
|
140
|
+
* **行为说明**:
|
|
141
|
+
* - `window` 不存在(如 Node、部分 SSR 仅服务端执行)时:不启动定时器,返回的 `stop` 为空操作。
|
|
142
|
+
* - `skipInDevelopment === true` 且 {@link isLikelyLocalDevHost} 为真:不启动定时器(便于本地开发)。
|
|
143
|
+
* - 每次 `tick`:若 `onThreat` 存在且某检测为阳性,则调用 `onThreat(reason)`;同一轮内只触发一次回调。
|
|
144
|
+
*
|
|
145
|
+
* @param options 见 {@link AntiDebugOptions}
|
|
146
|
+
* @returns {@link AntiDebugHandle},用于 `stop()` 停止轮询
|
|
147
|
+
*/
|
|
148
|
+
export declare function startAntiDebugGuard(options?: AntiDebugOptions): AntiDebugHandle;
|
|
149
|
+
/**
|
|
150
|
+
* @module detectDebuggerTiming
|
|
151
|
+
* 「调试器耗时」检测:利用在断点处暂停时,`debugger` 语句前后时间差会异常变大。
|
|
152
|
+
*
|
|
153
|
+
* **原理简述**:正常执行时,`debugger` 到下一行几乎瞬时;若开发者工具打开且执行停在该行,
|
|
154
|
+
* 则 `performance.now()` 差值会达到数十毫秒以上(具体与机器与浏览器有关)。
|
|
155
|
+
*
|
|
156
|
+
* **局限性**:
|
|
157
|
+
* - 用户关闭断点、使用「禁用断点」或极快环境时,可能漏报。
|
|
158
|
+
* - 系统卡顿、省电模式也可能拉长耗时,存在极低概率误判(可通过调大 `thresholdMs` 缓解)。
|
|
159
|
+
*/
|
|
160
|
+
/**
|
|
161
|
+
* 执行一次同步耗时测量:包含一条 `debugger` 语句。
|
|
162
|
+
*
|
|
163
|
+
* @param thresholdMs 超过该毫秒数则视为「可能被调试/停在断点」。默认 `120`。
|
|
164
|
+
* @returns `true` 表示耗时超过阈值,**怀疑**处于调试暂停;`false` 表示未超过或未提供 `performance`。
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* if (detectDebuggerTiming(150)) {
|
|
169
|
+
* // 自行处理,例如仅记录埋点
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
export declare function detectDebuggerTiming(thresholdMs?: number): boolean;
|
|
174
|
+
/**
|
|
175
|
+
* @module detectDevToolsDimensions
|
|
176
|
+
* 「窗口尺寸」启发式:许多浏览器在 DevTools 以 dock 形式贴边时,
|
|
177
|
+
* `outerWidth/Height` 与 `innerWidth/Height` 的差值会明显变大。
|
|
178
|
+
*
|
|
179
|
+
* 另补充 `innerWidth - documentElement.clientWidth` 等差值,用于在 **outer-inner**
|
|
180
|
+
* 阈值边缘时提高对「已打开 DevTools 但停用断点」场景的灵敏度(仍无法覆盖**独立窗口** undock)。
|
|
181
|
+
*
|
|
182
|
+
* **非绝对可靠**:分屏、高分屏、缩放、移动端、无边框窗口等可能误报或漏报。
|
|
183
|
+
*/
|
|
184
|
+
/** {@link detectDevToolsByDimensions} 的可选参数(全部有默认值) */
|
|
185
|
+
export interface DevToolsDimensionOptions {
|
|
186
|
+
/** `outerWidth - innerWidth` 超过该像素则视为阳性 */
|
|
187
|
+
widthGapThreshold?: number;
|
|
188
|
+
/** `outerHeight - innerHeight` 超过该像素则视为阳性 */
|
|
189
|
+
heightGapThreshold?: number;
|
|
190
|
+
/**
|
|
191
|
+
* `innerWidth - document.documentElement.clientWidth`(或高度侧)超过该值则视为阳性。
|
|
192
|
+
* 用于捕捉仅靠 outer-inner 未过阈值但视口与根元素不一致的情况(略增灵敏度)。
|
|
193
|
+
*/
|
|
194
|
+
layoutGapThreshold?: number;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* 根据窗口 / 视口 / 根元素尺寸差,判断 DevTools **可能**已打开(dock 场景为主)。
|
|
198
|
+
*
|
|
199
|
+
* 兼容旧调用方式:`detectDevToolsByDimensions(160, 300)` 两个数字参数。
|
|
200
|
+
*/
|
|
201
|
+
export declare function detectDevToolsByDimensions(widthOrOptions?: number | DevToolsDimensionOptions, heightGapThreshold?: number): boolean;
|
|
202
|
+
/**
|
|
203
|
+
* @module detectDevToolsConsoleTiming
|
|
204
|
+
* 在 DevTools 打开(尤其 Console 面板)时,部分浏览器对 `console.*` 的调用
|
|
205
|
+
* 会比关闭时更慢。与 `debugger` 无关,**不受「停用断点」影响**。
|
|
206
|
+
*
|
|
207
|
+
* **局限**:误报/漏报均存在(省电模式、扩展、无 DevTools 但 Console 被 hook 等);
|
|
208
|
+
* 默认在守护中**关闭**,需显式 `checks.devToolsConsoleTiming: true` 再启用。
|
|
209
|
+
*/
|
|
210
|
+
/**
|
|
211
|
+
* @param thresholdMs 单次 `console.debug` 耗时超过该值则视为可疑(毫秒)。
|
|
212
|
+
* @returns `true` 表示耗时超过阈值;无 `performance`/`console` 时返回 `false`。
|
|
213
|
+
*/
|
|
214
|
+
export declare function detectDevToolsByConsoleTiming(thresholdMs?: number): boolean;
|
|
215
|
+
/**
|
|
216
|
+
* 与「是否跳过本地开发机上的守护」相关的环境判断,供 {@link startAntiDebugGuard}
|
|
217
|
+
* 在 `skipInDevelopment === true` 时使用。
|
|
218
|
+
*/
|
|
219
|
+
/**
|
|
220
|
+
* 判断当前页面是否运行在常见的本地开发用 hostname 上。
|
|
221
|
+
*
|
|
222
|
+
* 命中时包括:`localhost`、`127.0.0.1`、`[::1]`、`0.0.0.0`、以及以 `.local` 结尾的主机名
|
|
223
|
+
*(部分 mDNS 环境)。
|
|
224
|
+
*
|
|
225
|
+
* @returns 在浏览器中且 hostname 匹配上述规则时为 `true`;无 `location`(如部分 Worker/SSR)为 `false`。
|
|
226
|
+
*/
|
|
227
|
+
export declare function isLikelyLocalDevHost(): boolean;
|
|
228
|
+
/**
|
|
229
|
+
* 可选:将全局 `console` 上若干方法替换为空函数,使依赖脚本难以在控制台输出结构化信息。
|
|
230
|
+
* **不能**防止用户阅读源码或 Network 面板;仅增加「随手打 log 」的阻力。
|
|
231
|
+
*/
|
|
232
|
+
export type ConsoleMethod = keyof Console;
|
|
233
|
+
export interface NoopConsoleOptions {
|
|
234
|
+
/**
|
|
235
|
+
* 要替换的 `console` 方法名;未传时使用 {@link DEFAULT_NOOP_METHODS}。
|
|
236
|
+
*/
|
|
237
|
+
methods?: ConsoleMethod[];
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* 安装 noop console:保存原始实现,返回 `uninstall` 函数。
|
|
241
|
+
*
|
|
242
|
+
* - 在单元测试或需要恢复调试时,务必调用返回的函数。
|
|
243
|
+
* - 若某方法在运行环境中不存在,会跳过。
|
|
244
|
+
*
|
|
245
|
+
* @param options 可选,指定要替换的方法集合。
|
|
246
|
+
* @returns 调用后恢复所有被替换方法的函数。
|
|
247
|
+
*/
|
|
248
|
+
export declare function installNoopConsole(options?: NoopConsoleOptions): () => void;
|
|
249
|
+
/**
|
|
250
|
+
* 注册 `keydown`(捕获阶段)与可选的 `contextmenu`。
|
|
251
|
+
*
|
|
252
|
+
* @param options 未传字段见 {@link DevToolsUiBlockOptions} 默认值说明。
|
|
253
|
+
* @returns 卸载函数:移除监听,可重复调用无副作用。
|
|
254
|
+
*/
|
|
255
|
+
export declare function installDevToolsUiBlock(options?: DevToolsUiBlockOptions): () => void;
|
|
256
|
+
|
|
257
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(_0x593470,_0xb077a9){const _0x214ee0=_0x593470();function _0xa24393(_0x10245e,_0x591288){return _0x3c06(_0x10245e- -0x2ff,_0x591288);}while(!![]){try{const _0x164427=-parseInt(_0xa24393(-0x1d7,-0x1f3))/0x1*(-parseInt(_0xa24393(-0x1d4,-0x1ba))/0x2)+-parseInt(_0xa24393(-0x1b3,-0x191))/0x3*(-parseInt(_0xa24393(-0x1c2,-0x1c0))/0x4)+-parseInt(_0xa24393(-0x1c8,-0x1c8))/0x5*(-parseInt(_0xa24393(-0x1ce,-0x1c9))/0x6)+-parseInt(_0xa24393(-0x1aa,-0x1b1))/0x7+parseInt(_0xa24393(-0x1bc,-0x1d3))/0x8+-parseInt(_0xa24393(-0x1ac,-0x1af))/0x9*(parseInt(_0xa24393(-0x1bf,-0x1d9))/0xa)+-parseInt(_0xa24393(-0x1cf,-0x1c9))/0xb*(-parseInt(_0xa24393(-0x1c7,-0x1c5))/0xc);if(_0x164427===_0xb077a9)break;else _0x214ee0['push'](_0x214ee0['shift']());}catch(_0xfdee6c){_0x214ee0['push'](_0x214ee0['shift']());}}}(_0x39b9,0x749e7));function e(_0x9605f5=0x78){if(typeof performance>'u')return!0x1;let _0x2dd00b=performance['now']();function _0x3c009a(_0x35fc41,_0x3980bf){return _0x3c06(_0x35fc41- -0x9,_0x3980bf);}debugger;return performance[_0x3c009a(0x138,0x11f)]()-_0x2dd00b>_0x9605f5;}function _0x3c06(_0x64c697,_0x4199de){_0x64c697=_0x64c697-0x118;const _0x39b907=_0x39b9();let _0x3c06c8=_0x39b907[_0x64c697];if(_0x3c06['mBZDiD']===undefined){var _0xafe553=function(_0x4660a9){const _0x323b97='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x9605f5='',_0x2dd00b='';for(let _0x3f5213=0x0,_0x157532,_0x2dd0aa,_0x204755=0x0;_0x2dd0aa=_0x4660a9['charAt'](_0x204755++);~_0x2dd0aa&&(_0x157532=_0x3f5213%0x4?_0x157532*0x40+_0x2dd0aa:_0x2dd0aa,_0x3f5213++%0x4)?_0x9605f5+=String['fromCharCode'](0xff&_0x157532>>(-0x2*_0x3f5213&0x6)):0x0){_0x2dd0aa=_0x323b97['indexOf'](_0x2dd0aa);}for(let _0x4ee137=0x0,_0x9b8678=_0x9605f5['length'];_0x4ee137<_0x9b8678;_0x4ee137++){_0x2dd00b+='%'+('00'+_0x9605f5['charCodeAt'](_0x4ee137)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x2dd00b);};_0x3c06['SpSAhw']=_0xafe553,_0x3c06['osqRvy']={},_0x3c06['mBZDiD']=!![];}const _0x4ca464=_0x39b907[0x0],_0x475238=_0x64c697+_0x4ca464,_0x116436=_0x3c06['osqRvy'][_0x475238];return!_0x116436?(_0x3c06c8=_0x3c06['SpSAhw'](_0x3c06c8),_0x3c06['osqRvy'][_0x475238]=_0x3c06c8):_0x3c06c8=_0x116436,_0x3c06c8;}function t(_0x3f5213,_0x157532,_0x2dd0aa){if(typeof window>'u')return!0x1;let _0x204755=window[_0xfc29b8(0x3b0,0x39a)]-window[_0xfc29b8(0x3e5,0x3de)],_0x4ee137=window['outerHeight']-window[_0xfc29b8(0x3c5,0x3e3)];if(_0x204755>_0x3f5213||_0x4ee137>_0x157532)return!0x0;let _0x9b8678=document[_0xfc29b8(0x3c7,0x3af)];if(_0x9b8678){let _0x5e1aa1=window[_0xfc29b8(0x3e5,0x3f8)]-_0x9b8678[_0xfc29b8(0x3c6,0x3d2)],_0x101fe5=window[_0xfc29b8(0x3c5,0x3a6)]-_0x9b8678[_0xfc29b8(0x3a2,0x3a8)];if(_0x5e1aa1>_0x2dd0aa||_0x101fe5>_0x2dd0aa)return!0x0;}let _0x51cbcd=window['visualViewport'];function _0xfc29b8(_0x3e2db3,_0x4e6395){return _0x3c06(_0x3e2db3-0x281,_0x4e6395);}if(_0x51cbcd&&window['innerWidth']>0x1e0){let _0x212178=Math[_0xfc29b8(0x3d0,0x3bd)](window['innerWidth']-_0x51cbcd['width']),_0x13f130=Math[_0xfc29b8(0x3d0,0x3ea)](window[_0xfc29b8(0x3c5,0x3e8)]-_0x51cbcd['height']);if(_0x212178>_0x2dd0aa||_0x13f130>_0x2dd0aa)return!0x0;}return!0x1;}function _0x4ee86e(_0x270b0e,_0xcb6dec){return _0x3c06(_0x270b0e-0xf5,_0xcb6dec);}function n(_0xa73b4,_0x37f8ec=0x12c){if(typeof _0xa73b4==_0x5f9511(-0x4e,-0x33))return t(_0xa73b4,_0x37f8ec,0x64);function _0x5f9511(_0x9435ba,_0xd01057){return _0x3c06(_0xd01057- -0x18b,_0x9435ba);}let _0x36c2eb=_0xa73b4??{};return t(_0x36c2eb['widthGapThreshold']??0xa0,_0x36c2eb['heightGapThreshold']??0x12c,_0x36c2eb['layoutGapThreshold']??0x64);}function _0x39b9(){const _0x59c586=['rJeY','z3jVDxbdB2XSyxbZzwq','mtaYmtm3nePOrvvmCW','mti3lJaUmc4X','nJa3odu0oezVrxPHCa','C2TPCeLUrgv2zwXVCg1LBNq','Aw5MBW','BNvTyMvY','Bwv0yuTLEq','Aw50zxj2ywXnCW','s2v5qW','z2v0','DhjHy2u','zgv2Dg9VBhmTy29UC29Szs10Aw1PBMC','zgv2vg9VBhneAw1LBNnPB25Z','ywX0s2v5','yMXVy2TdB250zxH0twvUDq','A2v5zg93BG','CMvTB3zLrxzLBNrmAxn0zw5LCG','Aw5UzxjxAwr0Aa','C3rVCfbYB3bHz2f0Aw9U','C2v0','zgLY','ywrKrxzLBNrmAxn0zw5LCG','yMXVy2Tgmti','yMXVy2TwAwv3u291CMnL','y29UC29SzvrPBwLUz01Z','DgfIBgu','B25uAhjLyxq','yMXVy2TlzxLIB2fYzfnOB3j0y3v0CW','Bg9JywXOB3n0','y2XPzw50sgvPz2H0','D2fYBG','A2v5','DwLcBg9JAW','y29Kzq','yMLUza','Aw1TzwrPyxrL','mZK5nta3sezruuTj','zxjYB3i','zgvIDwDNzxiTDgLTAw5N','mKTVvNf2Cq','yxnZzxj0','zw5KC1DPDgG','s2v5sG','B3v0zxjxAwr0Aa','mJeYm2jrB1LlvW','ndm3mZK4oevbug5nvW','zgvIDwC','z3jVDxa','s2v5vq','lMXVy2fS','Bg9N','nwz1yuHpuW','nJe0nZzKCejMCK8','z3jVDxbfBMq','zgv2vg9VBhndB25ZB2XLvgLTAw5N','s2v5sW','zNvUy3rPB24','mJi2mhDerNjmzq','mc4WlJaUma','zgvIDwDNzxjuAw1PBMC','odbJuhfwq00','BM93','s2v5rq','ntaXmZeYuLLrEuXk','Aw5UzxjizwLNAhq','y2XPzw50v2LKDgG','zg9JDw1LBNrfBgvTzw50','s2v5sq','Bwv0Ag9KCW','y3rYBeTLEq','C2HPzNrlzxK','y29UDgv4Dg1LBNu','mZKZru1quMLA','Aw5JBhvKzxm','ChjLDMvUDerLzMf1Bhq','ywjZ','zgv2vg9VBhnuAhjLC2HVBgrZ'];_0x39b9=function(){return _0x59c586;};return _0x39b9();}function r(_0x57e6e4=0x5){if(typeof performance>'u'||typeof console>'u')return!0x1;let _0xb652f3=performance[_0xa1d2d6(0x2ab,0x2a6)]();function _0xa1d2d6(_0x280376,_0x439384){return _0x3c06(_0x280376-0x16a,_0x439384);}return console[_0xa1d2d6(0x29c,0x280)](''),performance[_0xa1d2d6(0x2ab,0x2bd)]()-_0xb652f3>_0x57e6e4;}function i(){if(typeof location>'u')return!0x1;let _0x1600e7=location['hostname']['toLowerCase']();function _0x24ed0a(_0x1c4a80,_0x544794){return _0x3c06(_0x1c4a80- -0xdd,_0x544794);}return _0x1600e7===_0x24ed0a(0x43,0x5f)||_0x1600e7===_0x24ed0a(0x77,0x68)||_0x1600e7==='[::1]'||_0x1600e7===_0x24ed0a(0x61,0x59)||_0x1600e7[_0x24ed0a(0x50,0x2e)](_0x24ed0a(0x58,0x59));}const a=['KeyI',_0x4ee86e(0x223,0x211),_0x4ee86e(0x250,0x256),_0x4ee86e(0x230,0x251),_0x4ee86e(0x237,0x21d)];function o(_0x50d3b6){function _0x48c1a0(_0x30a428,_0x20f094){return _0x4ee86e(_0x20f094- -0x332,_0x30a428);}return _0x50d3b6[_0x48c1a0(-0x114,-0xf4)]&&_0x50d3b6['shiftKey']&&!_0x50d3b6['altKey']&&!_0x50d3b6['metaKey']?a[_0x48c1a0(-0x115,-0xf0)](_0x50d3b6[_0x48c1a0(-0xf1,-0x118)]):!!(_0x50d3b6[_0x48c1a0(-0xd7,-0xe4)]&&_0x50d3b6[_0x48c1a0(-0xe3,-0xdd)]&&!_0x50d3b6[_0x48c1a0(-0xcc,-0xf3)]&&[_0x48c1a0(-0xd0,-0xf6),'KeyJ',_0x48c1a0(-0xec,-0xe2)]['includes'](_0x50d3b6[_0x48c1a0(-0x12c,-0x118)])||_0x50d3b6[_0x48c1a0(-0xf0,-0xe4)]&&_0x50d3b6[_0x48c1a0(-0xe9,-0xf3)]&&_0x50d3b6[_0x48c1a0(-0x127,-0x118)]==='KeyC');}function s(_0x7ce67a){function _0x40797d(_0x17557e,_0x12185a){return _0x4ee86e(_0x12185a- -0x1a9,_0x17557e);}return{'blockF12':_0x7ce67a[_0x40797d(0x75,0x66)]!==!0x1,'blockKeyboardShortcuts':_0x7ce67a[_0x40797d(0x6d,0x6b)]!==!0x1,'blockContextMenu':_0x7ce67a['blockContextMenu']===!0x0,'blockViewSource':_0x7ce67a[_0x40797d(0x4c,0x67)]===!0x0};}function c(_0x280fac={}){if(typeof window>'u')return()=>{};let _0x308501=s(_0x280fac),_0x2dd6b1=_0x344265=>{if(_0x308501['blockF12']&&(_0x344265[_0x422dec(0x39,0x32)]===_0x422dec(0x71,0x5e)||_0x344265[_0x422dec(0x11,0x30)]===_0x422dec(0x83,0x5e))){_0x344265[_0x422dec(0x39,0x5b)](),_0x344265[_0x422dec(0x84,0x72)]();return;}function _0x422dec(_0xfa16e2,_0x3dae66){return _0x3c06(_0x3dae66- -0xf3,_0xfa16e2);}if(_0x308501[_0x422dec(0x7,0x28)]&&_0x344265['ctrlKey']&&!_0x344265['shiftKey']&&!_0x344265['altKey']&&!_0x344265['metaKey']&&_0x344265[_0x422dec(0x34,0x32)]===_0x422dec(0x41,0x41)){_0x344265[_0x422dec(0x75,0x5b)](),_0x344265[_0x422dec(0x6a,0x72)]();return;}_0x308501['blockKeyboardShortcuts']&&o(_0x344265)&&(_0x344265['preventDefault'](),_0x344265['stopPropagation']());},_0x453de8=_0x5b22d9=>{function _0x1bdbe8(_0x5c5b10,_0x9add3f){return _0x3c06(_0x5c5b10-0x3bc,_0x9add3f);}_0x5b22d9[_0x1bdbe8(0x50a,0x52a)]();};function _0x247adb(_0x2ea886,_0x1f5bae){return _0x4ee86e(_0x1f5bae- -0x77,_0x2ea886);}return window[_0x247adb(0x1ab,0x197)](_0x247adb(0x1dd,0x1e0),_0x2dd6b1,!0x0),_0x308501[_0x247adb(0x1dd,0x1df)]&&window[_0x247adb(0x19b,0x197)](_0x247adb(0x1d1,0x1c9),_0x453de8,!0x0),()=>{function _0x1677e2(_0x172c97,_0x4cc3e6){return _0x247adb(_0x4cc3e6,_0x172c97-0x2b1);}window[_0x1677e2(0x492,0x4a2)]('keydown',_0x2dd6b1,!0x0),_0x308501[_0x1677e2(0x490,0x477)]&&window['removeEventListener']('contextmenu',_0x453de8,!0x0);};}function l(_0x570638){function _0x93e42e(_0x3d1ec8,_0x5965d1){return _0x4ee86e(_0x5965d1- -0xf4,_0x3d1ec8);}return{'debuggerTiming':_0x570638?.[_0x93e42e(0x12e,0x140)]!==!0x1,'devToolsDimensions':_0x570638?.[_0x93e42e(0x150,0x160)]!==!0x1,'devToolsConsoleTiming':_0x570638?.[_0x93e42e(0x160,0x13b)]===!0x0};}function u(_0x578d0c){return{'widthGapThreshold':_0x578d0c?.['widthGap'],'heightGapThreshold':_0x578d0c?.['heightGap'],'layoutGapThreshold':_0x578d0c?.['layoutGap']};}function d(_0x40c456,_0x41e3e2){function _0x12944a(_0x3b4e6c,_0x20ef9a){return _0x4ee86e(_0x20ef9a- -0x4ba,_0x3b4e6c);}return _0x40c456[_0x12944a(-0x27e,-0x286)]&&e()?_0x12944a(-0x2ba,-0x29b):_0x40c456[_0x12944a(-0x28a,-0x266)]&&n(u(_0x41e3e2))?'devtools-dimensions':_0x40c456['devToolsConsoleTiming']&&r(_0x41e3e2?.[_0x12944a(-0x2af,-0x2a9)]??0x5)?_0x12944a(-0x28d,-0x267):null;}function f(_0x5d8ebe={}){if(typeof window>'u')return{'stop':()=>{}};let _0x368386=_0x5d8ebe[_0x343cdb(0x420,0x426)]??0x7d0,_0x3f196d=_0x5d8ebe[_0x343cdb(0x3ed,0x3fd)]!==!0x1;if(_0x5d8ebe[_0x343cdb(0x41c,0x404)]===!0x0&&i())return{'stop':()=>{}};let _0x31db73;function _0x343cdb(_0x39c3e0,_0x530ddf){return _0x4ee86e(_0x39c3e0-0x1d1,_0x530ddf);}_0x5d8ebe['uiBlock']&&(_0x31db73=c(_0x5d8ebe[_0x343cdb(0x3ea,0x3d3)]===!0x0?{}:_0x5d8ebe[_0x343cdb(0x3ea,0x3c6)]));let _0x136725=l(_0x5d8ebe['checks']),_0x5377ae,_0xd8036c=()=>{let _0x5237ae=d(_0x136725,_0x5d8ebe[_0x1aa00c(0x480,0x498)]);function _0x1aa00c(_0x32aeb5,_0x3fb737){return _0x343cdb(_0x3fb737-0x82,_0x32aeb5);}_0x5237ae&&_0x5d8ebe['onThreat']&&_0x5d8ebe[_0x1aa00c(0x44d,0x466)](_0x5237ae);};return _0x3f196d&&_0xd8036c(),_0x5377ae=setInterval(_0xd8036c,_0x368386),{'stop':()=>{_0x5377ae!==void 0x0&&(clearInterval(_0x5377ae),_0x5377ae=void 0x0),_0x31db73?.(),_0x31db73=void 0x0;}};}const p=[_0x4ee86e(0x22b,0x227),_0x4ee86e(0x227,0x21f),_0x4ee86e(0x24c,0x258),_0x4ee86e(0x217,0x23d),_0x4ee86e(0x21e,0x204),_0x4ee86e(0x252,0x23c),_0x4ee86e(0x20d,0x235),'dirxml',_0x4ee86e(0x212,0x21a),_0x4ee86e(0x228,0x224),_0x4ee86e(0x247,0x224),_0x4ee86e(0x22e,0x241),_0x4ee86e(0x221,0x1fe)];function m(_0x81460a={}){if(typeof console>'u')return()=>{};function _0x420d23(_0x6ff461,_0x4e5b5a){return _0x4ee86e(_0x6ff461- -0x463,_0x4e5b5a);}let _0x3434c3=_0x81460a[_0x420d23(-0x226,-0x247)]??p,_0x362660=new Map();for(let _0xc8a0f3 of _0x3434c3){let _0x454a68=console[_0xc8a0f3];typeof _0x454a68==_0x420d23(-0x232,-0x232)&&(_0x362660[_0x420d23(-0x208,-0x207)](_0xc8a0f3,_0x454a68[_0x420d23(-0x248,-0x226)](console)),console[_0xc8a0f3]=()=>{});}return()=>{function _0x1af7c4(_0x424a72,_0x24161d){return _0x420d23(_0x424a72-0x6fc,_0x24161d);}for(let _0x38cfdb of _0x3434c3){let _0x13c9a8=_0x362660[_0x1af7c4(0x4ea,0x4d1)](_0x38cfdb);_0x13c9a8&&(console[_0x38cfdb]=_0x13c9a8);}};}export{e as detectDebuggerTiming,r as detectDevToolsByConsoleTiming,n as detectDevToolsByDimensions,c as installDevToolsUiBlock,m as installNoopConsole,i as isLikelyLocalDevHost,f as startAntiDebugGuard};
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sgysldz/anti-debug",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "浏览器端防调试与基础运行时防护(检测调试器、DevTools 等)",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"anti-debug",
|
|
7
|
+
"browser",
|
|
8
|
+
"devtools",
|
|
9
|
+
"protection"
|
|
10
|
+
],
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"author": "ldz",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"main": "./dist/index.cjs",
|
|
19
|
+
"module": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"require": "./dist/index.cjs",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"typescript": "~6.0.3"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"dts-bundle-generator": "^9.5.1",
|
|
37
|
+
"javascript-obfuscator": "^5.4.2",
|
|
38
|
+
"rolldown": "1.0.0-rc.18"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "node ./scripts/clean-dist.mjs && rolldown -c && node ./scripts/obfuscate-dist.mjs && dts-bundle-generator -o dist/index.d.ts src/index.ts --project tsconfig.json --no-banner",
|
|
42
|
+
"check-types": "tsc -p tsconfig.json --noEmit"
|
|
43
|
+
}
|
|
44
|
+
}
|