mirror of
https://github.com/violettoolssite/CFspider.git
synced 2026-04-05 11:29:03 +08:00
feat(x27cn): v1.4.0 添加一键保护和反爬功能
This commit is contained in:
122
x27cn/README.md
122
x27cn/README.md
@@ -352,6 +352,120 @@ x27cn encrypt secret.txt --password="mypassword"
|
|||||||
x27cn decrypt secret.txt.enc --password="mypassword"
|
x27cn decrypt secret.txt.enc --password="mypassword"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 反爬虫保护(v1.4.0 新增)
|
||||||
|
|
||||||
|
X27CN 现在提供一键式代码保护,包含反调试、反爬虫、域名锁定等功能。
|
||||||
|
|
||||||
|
### 一键保护(推荐)
|
||||||
|
|
||||||
|
```python
|
||||||
|
import x27cn
|
||||||
|
|
||||||
|
# 一键完整保护(混淆 + 反爬)
|
||||||
|
protected = x27cn.full_obfuscate(js_code, level=2)
|
||||||
|
|
||||||
|
# 保护级别:
|
||||||
|
# level=1: 基础 - 压缩 + 变量重命名
|
||||||
|
# level=2: 中等 - 基础 + 字符串加密 + 死代码
|
||||||
|
# level=3: 高级 - 中等 + 反调试 + 禁用快捷键
|
||||||
|
|
||||||
|
# 快速保护(一行代码)
|
||||||
|
protected = x27cn.quick_protect(js_code)
|
||||||
|
|
||||||
|
# 保护文件
|
||||||
|
x27cn.obfuscate_file_full('app.js', level=3, anti_crawl=True)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 反调试保护
|
||||||
|
|
||||||
|
```python
|
||||||
|
import x27cn
|
||||||
|
|
||||||
|
# 生成反调试代码(无限 debugger + 时间检测 + 控制台检测)
|
||||||
|
anti_debug = x27cn.generate_anti_debug()
|
||||||
|
|
||||||
|
# 生成禁用快捷键代码(F12, Ctrl+Shift+I, 右键等)
|
||||||
|
disable_shortcuts = x27cn.generate_disable_shortcuts()
|
||||||
|
|
||||||
|
# 控制台清除和警告
|
||||||
|
console_clear = x27cn.generate_console_clear()
|
||||||
|
|
||||||
|
# 组合完整保护
|
||||||
|
protection = x27cn.generate_full_protection(
|
||||||
|
anti_debug=True,
|
||||||
|
disable_shortcuts=True,
|
||||||
|
console_clear=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# 注入保护到代码
|
||||||
|
protected_code = x27cn.inject_protection(js_code, anti_debug=True)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 域名锁定
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 限制代码只能在指定域名运行
|
||||||
|
domain_lock = x27cn.generate_domain_lock(['example.com', 'test.com'])
|
||||||
|
|
||||||
|
# 或使用 full_obfuscate
|
||||||
|
protected = x27cn.full_obfuscate(js_code, domain_lock=['example.com'])
|
||||||
|
```
|
||||||
|
|
||||||
|
### 时间限制(许可证过期)
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 代码在指定日期后失效
|
||||||
|
time_bomb = x27cn.generate_time_bomb('2025-12-31')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 命令行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 一键保护(推荐)
|
||||||
|
x27cn protect app.js
|
||||||
|
|
||||||
|
# 指定保护级别
|
||||||
|
x27cn protect app.js --level=3
|
||||||
|
|
||||||
|
# 域名锁定
|
||||||
|
x27cn protect app.js --domain=example.com --domain=test.com
|
||||||
|
|
||||||
|
# 设置过期日期
|
||||||
|
x27cn protect app.js --expire=2025-12-31
|
||||||
|
|
||||||
|
# 不添加反爬
|
||||||
|
x27cn protect app.js --no-anti-crawl
|
||||||
|
|
||||||
|
# 仅生成反调试代码
|
||||||
|
x27cn anti-debug
|
||||||
|
|
||||||
|
# 生成带禁用快捷键的反调试代码
|
||||||
|
x27cn anti-debug --disable-shortcuts --console-clear
|
||||||
|
```
|
||||||
|
|
||||||
|
### 保护效果
|
||||||
|
|
||||||
|
**原始代码:**
|
||||||
|
```javascript
|
||||||
|
function getSecret() {
|
||||||
|
return "API_KEY_12345";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**level=3 保护后:**
|
||||||
|
```javascript
|
||||||
|
(function(){var _$a=function(){var _$b=new Date().getTime();debugger;...})();
|
||||||
|
var _$k=[120,50,...];var _$a=[[65,83,...]];var _$s=function(i){...};
|
||||||
|
var _$0=function(){return _$s(0)};...
|
||||||
|
```
|
||||||
|
|
||||||
|
反调试特性:
|
||||||
|
- 无限 debugger 断点
|
||||||
|
- 检测 DevTools 打开
|
||||||
|
- 时间检测(调试暂停时触发)
|
||||||
|
- 禁用 F12 / Ctrl+Shift+I / 右键
|
||||||
|
- 控制台定期清除
|
||||||
|
|
||||||
## 安全说明
|
## 安全说明
|
||||||
|
|
||||||
X27CN 提供两种安全级别:
|
X27CN 提供两种安全级别:
|
||||||
@@ -398,6 +512,14 @@ X27CN 提供两种安全级别:
|
|||||||
| `encrypt_with_password(data, pwd)` | 密码加密数据 |
|
| `encrypt_with_password(data, pwd)` | 密码加密数据 |
|
||||||
| `decrypt_with_password(data, pwd)` | 密码解密数据 |
|
| `decrypt_with_password(data, pwd)` | 密码解密数据 |
|
||||||
| `md5(text)` / `sha256(text)` | 快速哈希 |
|
| `md5(text)` / `sha256(text)` | 快速哈希 |
|
||||||
|
| `full_obfuscate(code, level)` | 一键完整混淆 |
|
||||||
|
| `quick_protect(code)` | 快速保护代码 |
|
||||||
|
| `obfuscate_file_full(path, level)` | 一键保护文件 |
|
||||||
|
| `generate_anti_debug()` | 生成反调试代码 |
|
||||||
|
| `generate_disable_shortcuts()` | 生成禁用快捷键代码 |
|
||||||
|
| `generate_domain_lock(domains)` | 生成域名锁定代码 |
|
||||||
|
| `generate_time_bomb(date)` | 生成时间限制代码 |
|
||||||
|
| `inject_protection(code, ...)` | 注入保护到代码 |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "x27cn"
|
name = "x27cn"
|
||||||
version = "1.3.0"
|
version = "1.4.0"
|
||||||
description = "X27CN 代码混淆加密库 - Code obfuscation and encryption library"
|
description = "X27CN - Advanced code obfuscation, encryption and anti-crawl protection"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
requires-python = ">=3.7"
|
requires-python = ">=3.7"
|
||||||
@@ -19,8 +19,9 @@ keywords = [
|
|||||||
"encoding",
|
"encoding",
|
||||||
"html",
|
"html",
|
||||||
"javascript",
|
"javascript",
|
||||||
"加密",
|
"anti-debug",
|
||||||
"混淆"
|
"anti-crawl",
|
||||||
|
"code-protection"
|
||||||
]
|
]
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"Development Status :: 4 - Beta",
|
"Development Status :: 4 - Beta",
|
||||||
|
|||||||
@@ -68,7 +68,26 @@ from .password import (
|
|||||||
sha512,
|
sha512,
|
||||||
)
|
)
|
||||||
|
|
||||||
__version__ = '1.3.0'
|
from .anti_crawl import (
|
||||||
|
generate_anti_debug,
|
||||||
|
generate_disable_shortcuts,
|
||||||
|
generate_console_clear,
|
||||||
|
generate_code_integrity_check,
|
||||||
|
generate_domain_lock,
|
||||||
|
generate_time_bomb,
|
||||||
|
generate_full_protection,
|
||||||
|
inject_protection,
|
||||||
|
)
|
||||||
|
|
||||||
|
from .advanced import (
|
||||||
|
encrypt_strings,
|
||||||
|
advanced_obfuscate,
|
||||||
|
full_obfuscate,
|
||||||
|
obfuscate_file_full,
|
||||||
|
quick_protect,
|
||||||
|
)
|
||||||
|
|
||||||
|
__version__ = '1.4.0'
|
||||||
__author__ = 'CFspider'
|
__author__ = 'CFspider'
|
||||||
__all__ = [
|
__all__ = [
|
||||||
# 核心加密
|
# 核心加密
|
||||||
@@ -111,5 +130,20 @@ __all__ = [
|
|||||||
'md5',
|
'md5',
|
||||||
'sha256',
|
'sha256',
|
||||||
'sha512',
|
'sha512',
|
||||||
|
# 反爬虫保护
|
||||||
|
'generate_anti_debug',
|
||||||
|
'generate_disable_shortcuts',
|
||||||
|
'generate_console_clear',
|
||||||
|
'generate_code_integrity_check',
|
||||||
|
'generate_domain_lock',
|
||||||
|
'generate_time_bomb',
|
||||||
|
'generate_full_protection',
|
||||||
|
'inject_protection',
|
||||||
|
# 高级混淆(一键式)
|
||||||
|
'encrypt_strings',
|
||||||
|
'advanced_obfuscate',
|
||||||
|
'full_obfuscate',
|
||||||
|
'obfuscate_file_full',
|
||||||
|
'quick_protect',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
290
x27cn/x27cn/advanced.py
Normal file
290
x27cn/x27cn/advanced.py
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
"""
|
||||||
|
X27CN 高级混淆加密模块
|
||||||
|
|
||||||
|
提供一键式代码混淆和保护:
|
||||||
|
- 字符串加密
|
||||||
|
- 变量名混淆
|
||||||
|
- 控制流扁平化
|
||||||
|
- 死代码注入
|
||||||
|
- 反调试保护
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
from typing import Optional
|
||||||
|
from .core import encrypt, DEFAULT_KEY
|
||||||
|
from .minify import minify_js, obfuscate_identifiers, add_dead_code
|
||||||
|
from .anti_crawl import generate_full_protection, inject_protection
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt_strings(js_code: str, key: str = DEFAULT_KEY) -> str:
|
||||||
|
"""
|
||||||
|
加密 JavaScript 代码中的字符串
|
||||||
|
|
||||||
|
将所有字符串字面量替换为运行时解密调用。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
js_code: JavaScript 代码
|
||||||
|
key: 加密密钥
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
字符串加密后的代码
|
||||||
|
"""
|
||||||
|
# 收集所有字符串
|
||||||
|
strings = []
|
||||||
|
|
||||||
|
def collect_string(match):
|
||||||
|
quote = match.group(1)
|
||||||
|
content = match.group(2)
|
||||||
|
if content and len(content) > 2: # 只加密较长的字符串
|
||||||
|
idx = len(strings)
|
||||||
|
strings.append(content)
|
||||||
|
return f'_$s({idx})'
|
||||||
|
return match.group(0)
|
||||||
|
|
||||||
|
# 匹配字符串(简化版,可能有边缘情况)
|
||||||
|
pattern = r'(["\'])([^"\'\\]*(?:\\.[^"\'\\]*)*)\1'
|
||||||
|
processed = re.sub(pattern, collect_string, js_code)
|
||||||
|
|
||||||
|
if not strings:
|
||||||
|
return js_code
|
||||||
|
|
||||||
|
# 生成解密器和字符串数组
|
||||||
|
key_bytes = key.encode('utf-8')
|
||||||
|
key_array = ','.join(str(b) for b in key_bytes)
|
||||||
|
|
||||||
|
# 简单的 XOR 加密
|
||||||
|
encrypted_strings = []
|
||||||
|
for s in strings:
|
||||||
|
encrypted = []
|
||||||
|
for i, c in enumerate(s):
|
||||||
|
encrypted.append(ord(c) ^ key_bytes[i % len(key_bytes)])
|
||||||
|
encrypted_strings.append(','.join(str(b) for b in encrypted))
|
||||||
|
|
||||||
|
strings_array = ';'.join(f'[{s}]' for s in encrypted_strings)
|
||||||
|
|
||||||
|
decoder = f'''
|
||||||
|
var _$k=[{key_array}];
|
||||||
|
var _$a=[{strings_array}];
|
||||||
|
var _$s=function(i){{var a=_$a[i],r='';for(var j=0;j<a.length;j++)r+=String.fromCharCode(a[j]^_$k[j%_$k.length]);return r}};
|
||||||
|
'''
|
||||||
|
|
||||||
|
return decoder + processed
|
||||||
|
|
||||||
|
|
||||||
|
def advanced_obfuscate(
|
||||||
|
js_code: str,
|
||||||
|
key: str = DEFAULT_KEY,
|
||||||
|
encrypt_strings_: bool = True,
|
||||||
|
rename_vars: bool = True,
|
||||||
|
dead_code: bool = True,
|
||||||
|
anti_debug: bool = False,
|
||||||
|
disable_shortcuts: bool = False,
|
||||||
|
domain_lock: list = None,
|
||||||
|
expire_date: str = None
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
高级代码混淆
|
||||||
|
|
||||||
|
应用多层混淆保护。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
js_code: JavaScript 代码
|
||||||
|
key: 加密密钥
|
||||||
|
encrypt_strings_: 加密字符串
|
||||||
|
rename_vars: 重命名变量
|
||||||
|
dead_code: 添加死代码
|
||||||
|
anti_debug: 添加反调试
|
||||||
|
disable_shortcuts: 禁用快捷键
|
||||||
|
domain_lock: 域名锁定
|
||||||
|
expire_date: 过期日期
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
混淆后的代码
|
||||||
|
"""
|
||||||
|
result = js_code
|
||||||
|
|
||||||
|
# 1. 变量重命名
|
||||||
|
if rename_vars:
|
||||||
|
result = obfuscate_identifiers(result)
|
||||||
|
|
||||||
|
# 2. 添加死代码
|
||||||
|
if dead_code:
|
||||||
|
result = add_dead_code(result)
|
||||||
|
|
||||||
|
# 3. 字符串加密
|
||||||
|
if encrypt_strings_:
|
||||||
|
result = encrypt_strings(result, key)
|
||||||
|
|
||||||
|
# 4. 添加保护代码
|
||||||
|
if anti_debug or disable_shortcuts or domain_lock or expire_date:
|
||||||
|
result = inject_protection(
|
||||||
|
result,
|
||||||
|
anti_debug=anti_debug,
|
||||||
|
disable_shortcuts=disable_shortcuts,
|
||||||
|
console_clear=anti_debug,
|
||||||
|
domain_lock=domain_lock,
|
||||||
|
expire_date=expire_date
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def full_obfuscate(
|
||||||
|
code: str,
|
||||||
|
file_type: str = 'js',
|
||||||
|
key: str = DEFAULT_KEY,
|
||||||
|
level: int = 2,
|
||||||
|
anti_crawl: bool = True
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
一键完整混淆
|
||||||
|
|
||||||
|
根据保护级别应用不同程度的混淆。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
code: 源代码
|
||||||
|
file_type: 文件类型 ('js', 'html', 'css')
|
||||||
|
key: 加密密钥
|
||||||
|
level: 混淆级别 (1-3)
|
||||||
|
1: 基础 - 压缩 + 变量重命名
|
||||||
|
2: 中等 - 基础 + 字符串加密 + 死代码
|
||||||
|
3: 高级 - 中等 + 反调试 + 禁用快捷键
|
||||||
|
anti_crawl: 添加反爬保护
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
混淆后的代码
|
||||||
|
"""
|
||||||
|
if file_type == 'html':
|
||||||
|
return _obfuscate_html_full(code, key, level, anti_crawl)
|
||||||
|
elif file_type == 'css':
|
||||||
|
return _obfuscate_css_full(code, key)
|
||||||
|
else:
|
||||||
|
return _obfuscate_js_full(code, key, level, anti_crawl)
|
||||||
|
|
||||||
|
|
||||||
|
def _obfuscate_js_full(code: str, key: str, level: int, anti_crawl: bool) -> str:
|
||||||
|
"""完整混淆 JavaScript"""
|
||||||
|
# Level 1: 基础
|
||||||
|
result = minify_js(code)
|
||||||
|
result = obfuscate_identifiers(result)
|
||||||
|
|
||||||
|
if level >= 2:
|
||||||
|
# Level 2: 中等
|
||||||
|
result = encrypt_strings(result, key)
|
||||||
|
result = add_dead_code(result)
|
||||||
|
|
||||||
|
if level >= 3:
|
||||||
|
# Level 3: 高级
|
||||||
|
result = inject_protection(
|
||||||
|
result,
|
||||||
|
anti_debug=True,
|
||||||
|
disable_shortcuts=True,
|
||||||
|
console_clear=True
|
||||||
|
)
|
||||||
|
elif anti_crawl:
|
||||||
|
# 仅反爬(无反调试)
|
||||||
|
result = inject_protection(
|
||||||
|
result,
|
||||||
|
anti_debug=False,
|
||||||
|
disable_shortcuts=True,
|
||||||
|
console_clear=False
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _obfuscate_html_full(code: str, key: str, level: int, anti_crawl: bool) -> str:
|
||||||
|
"""完整混淆 HTML"""
|
||||||
|
from .obfuscate import obfuscate_html, obfuscate_inline_js
|
||||||
|
|
||||||
|
# 先混淆内联 JS
|
||||||
|
result = obfuscate_inline_js(code, key)
|
||||||
|
|
||||||
|
if level >= 2:
|
||||||
|
# 加密整个 HTML
|
||||||
|
result = obfuscate_html(result, key)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _obfuscate_css_full(code: str, key: str) -> str:
|
||||||
|
"""完整混淆 CSS"""
|
||||||
|
from .obfuscate import obfuscate_css
|
||||||
|
from .minify import minify_css
|
||||||
|
|
||||||
|
# 压缩并加密
|
||||||
|
result = minify_css(code)
|
||||||
|
result = obfuscate_css(result, key)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def obfuscate_file_full(
|
||||||
|
input_path: str,
|
||||||
|
output_path: Optional[str] = None,
|
||||||
|
key: str = DEFAULT_KEY,
|
||||||
|
level: int = 2,
|
||||||
|
anti_crawl: bool = True
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
一键混淆文件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
input_path: 输入文件路径
|
||||||
|
output_path: 输出文件路径(可选)
|
||||||
|
key: 加密密钥
|
||||||
|
level: 混淆级别 (1-3)
|
||||||
|
anti_crawl: 添加反爬保护
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
输出文件路径
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 读取文件
|
||||||
|
with open(input_path, 'r', encoding='utf-8') as f:
|
||||||
|
code = f.read()
|
||||||
|
|
||||||
|
# 确定文件类型
|
||||||
|
ext = os.path.splitext(input_path)[1].lower()
|
||||||
|
if ext in ('.html', '.htm'):
|
||||||
|
file_type = 'html'
|
||||||
|
elif ext == '.css':
|
||||||
|
file_type = 'css'
|
||||||
|
else:
|
||||||
|
file_type = 'js'
|
||||||
|
|
||||||
|
# 混淆
|
||||||
|
result = full_obfuscate(code, file_type, key, level, anti_crawl)
|
||||||
|
|
||||||
|
# 确定输出路径
|
||||||
|
if output_path is None:
|
||||||
|
base, ext = os.path.splitext(input_path)
|
||||||
|
output_path = f"{base}.protected{ext}"
|
||||||
|
|
||||||
|
# 写入
|
||||||
|
with open(output_path, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(result)
|
||||||
|
|
||||||
|
return output_path
|
||||||
|
|
||||||
|
|
||||||
|
def quick_protect(js_code: str) -> str:
|
||||||
|
"""
|
||||||
|
快速保护 JavaScript 代码
|
||||||
|
|
||||||
|
一行代码完成混淆 + 反爬保护。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
js_code: JavaScript 代码
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
保护后的代码
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> protected = x27cn.quick_protect('alert("Hello")')
|
||||||
|
"""
|
||||||
|
return full_obfuscate(js_code, 'js', DEFAULT_KEY, level=2, anti_crawl=True)
|
||||||
|
|
||||||
298
x27cn/x27cn/anti_crawl.py
Normal file
298
x27cn/x27cn/anti_crawl.py
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
"""
|
||||||
|
X27CN 反爬虫保护模块
|
||||||
|
|
||||||
|
提供多种反爬虫和反调试保护机制:
|
||||||
|
- 无限 debugger 断点
|
||||||
|
- 控制台检测
|
||||||
|
- 时间检测(检测调试暂停)
|
||||||
|
- 窗口大小检测(检测 DevTools)
|
||||||
|
- 禁用右键和快捷键
|
||||||
|
- 代码自检(检测篡改)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
|
||||||
|
def generate_anti_debug() -> str:
|
||||||
|
"""
|
||||||
|
生成反调试代码
|
||||||
|
|
||||||
|
包含多层反调试保护:
|
||||||
|
1. 无限 debugger 断点
|
||||||
|
2. 时间检测
|
||||||
|
3. 控制台检测
|
||||||
|
4. 窗口尺寸检测
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
反调试 JavaScript 代码
|
||||||
|
"""
|
||||||
|
# 随机变量名
|
||||||
|
vars = _random_vars(10)
|
||||||
|
|
||||||
|
return f'''
|
||||||
|
(function() {{
|
||||||
|
var {vars[0]} = function() {{
|
||||||
|
var {vars[1]} = new Date().getTime();
|
||||||
|
debugger;
|
||||||
|
var {vars[2]} = new Date().getTime();
|
||||||
|
if ({vars[2]} - {vars[1]} > 100) {{
|
||||||
|
{vars[3]}();
|
||||||
|
}}
|
||||||
|
}};
|
||||||
|
|
||||||
|
var {vars[3]} = function() {{
|
||||||
|
while(true) {{
|
||||||
|
debugger;
|
||||||
|
{vars[0]}();
|
||||||
|
}}
|
||||||
|
}};
|
||||||
|
|
||||||
|
var {vars[4]} = function() {{
|
||||||
|
var {vars[5]} = /./;
|
||||||
|
{vars[5]}.toString = function() {{
|
||||||
|
{vars[3]}();
|
||||||
|
return '';
|
||||||
|
}};
|
||||||
|
console.log('%c', {vars[5]});
|
||||||
|
}};
|
||||||
|
|
||||||
|
var {vars[6]} = function() {{
|
||||||
|
var {vars[7]} = window.outerWidth - window.innerWidth > 160;
|
||||||
|
var {vars[8]} = window.outerHeight - window.innerHeight > 160;
|
||||||
|
if ({vars[7]} || {vars[8]}) {{
|
||||||
|
{vars[3]}();
|
||||||
|
}}
|
||||||
|
}};
|
||||||
|
|
||||||
|
setInterval({vars[0]}, 1000);
|
||||||
|
setInterval({vars[4]}, 2000);
|
||||||
|
setInterval({vars[6]}, 1500);
|
||||||
|
{vars[0]}();
|
||||||
|
}})();
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def generate_disable_shortcuts() -> str:
|
||||||
|
"""
|
||||||
|
生成禁用快捷键代码
|
||||||
|
|
||||||
|
禁用常用的开发者工具快捷键:
|
||||||
|
- F12
|
||||||
|
- Ctrl+Shift+I/J/C
|
||||||
|
- Ctrl+U (查看源代码)
|
||||||
|
- 右键菜单
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
禁用快捷键 JavaScript 代码
|
||||||
|
"""
|
||||||
|
vars = _random_vars(5)
|
||||||
|
|
||||||
|
return f'''
|
||||||
|
(function() {{
|
||||||
|
document.addEventListener('keydown', function({vars[0]}) {{
|
||||||
|
if ({vars[0]}.key === 'F12' ||
|
||||||
|
({vars[0]}.ctrlKey && {vars[0]}.shiftKey && ['I','i','J','j','C','c'].includes({vars[0]}.key)) ||
|
||||||
|
({vars[0]}.ctrlKey && ['U','u'].includes({vars[0]}.key))) {{
|
||||||
|
{vars[0]}.preventDefault();
|
||||||
|
{vars[0]}.stopPropagation();
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
}}, true);
|
||||||
|
|
||||||
|
document.addEventListener('contextmenu', function({vars[1]}) {{
|
||||||
|
{vars[1]}.preventDefault();
|
||||||
|
return false;
|
||||||
|
}}, true);
|
||||||
|
|
||||||
|
document.onselectstart = function() {{ return false; }};
|
||||||
|
document.ondragstart = function() {{ return false; }};
|
||||||
|
}})();
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def generate_console_clear() -> str:
|
||||||
|
"""
|
||||||
|
生成控制台清除和欺骗代码
|
||||||
|
|
||||||
|
定期清除控制台并显示警告信息。
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
控制台清除 JavaScript 代码
|
||||||
|
"""
|
||||||
|
vars = _random_vars(3)
|
||||||
|
|
||||||
|
return f'''
|
||||||
|
(function() {{
|
||||||
|
var {vars[0]} = function() {{
|
||||||
|
console.clear();
|
||||||
|
console.log('%cSTOP!', 'color:red;font-size:50px;font-weight:bold;');
|
||||||
|
console.log('%cThis browser feature is for developers only.', 'font-size:16px;');
|
||||||
|
}};
|
||||||
|
setInterval({vars[0]}, 500);
|
||||||
|
{vars[0]}();
|
||||||
|
}})();
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def generate_code_integrity_check(code: str) -> str:
|
||||||
|
"""
|
||||||
|
生成代码完整性检查
|
||||||
|
|
||||||
|
计算代码哈希,运行时检测代码是否被修改。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
code: 需要保护的代码
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
带完整性检查的代码
|
||||||
|
"""
|
||||||
|
# 计算代码哈希
|
||||||
|
code_hash = hashlib.md5(code.encode()).hexdigest()[:16]
|
||||||
|
vars = _random_vars(5)
|
||||||
|
|
||||||
|
return f'''
|
||||||
|
(function() {{
|
||||||
|
var {vars[0]} = '{code_hash}';
|
||||||
|
var {vars[1]} = function({vars[2]}) {{
|
||||||
|
var {vars[3]} = 0;
|
||||||
|
for (var i = 0; i < {vars[2]}.length; i++) {{
|
||||||
|
{vars[3]} = (({vars[3]} << 5) - {vars[3]}) + {vars[2]}.charCodeAt(i);
|
||||||
|
{vars[3]} = {vars[3]} & {vars[3]};
|
||||||
|
}}
|
||||||
|
return ({vars[3]} >>> 0).toString(16);
|
||||||
|
}};
|
||||||
|
var {vars[4]} = {vars[1]}(arguments.callee.toString());
|
||||||
|
// Integrity check placeholder
|
||||||
|
}})();
|
||||||
|
{code}
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def generate_domain_lock(domains: list) -> str:
|
||||||
|
"""
|
||||||
|
生成域名锁定代码
|
||||||
|
|
||||||
|
限制代码只能在指定域名运行。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
domains: 允许运行的域名列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
域名锁定 JavaScript 代码
|
||||||
|
"""
|
||||||
|
vars = _random_vars(4)
|
||||||
|
domains_str = ','.join(f'"{d}"' for d in domains)
|
||||||
|
|
||||||
|
return f'''
|
||||||
|
(function() {{
|
||||||
|
var {vars[0]} = [{domains_str}];
|
||||||
|
var {vars[1]} = window.location.hostname;
|
||||||
|
var {vars[2]} = false;
|
||||||
|
for (var i = 0; i < {vars[0]}.length; i++) {{
|
||||||
|
if ({vars[1]} === {vars[0]}[i] || {vars[1]}.endsWith('.' + {vars[0]}[i])) {{
|
||||||
|
{vars[2]} = true;
|
||||||
|
break;
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
if (!{vars[2]}) {{
|
||||||
|
document.body.innerHTML = '<h1>Unauthorized Domain</h1>';
|
||||||
|
throw new Error('Unauthorized domain');
|
||||||
|
}}
|
||||||
|
}})();
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def generate_time_bomb(expire_date: str) -> str:
|
||||||
|
"""
|
||||||
|
生成时间炸弹代码
|
||||||
|
|
||||||
|
代码在指定日期后失效。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
expire_date: 过期日期 (格式: YYYY-MM-DD)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
时间炸弹 JavaScript 代码
|
||||||
|
"""
|
||||||
|
vars = _random_vars(3)
|
||||||
|
|
||||||
|
return f'''
|
||||||
|
(function() {{
|
||||||
|
var {vars[0]} = new Date('{expire_date}').getTime();
|
||||||
|
var {vars[1]} = new Date().getTime();
|
||||||
|
if ({vars[1]} > {vars[0]}) {{
|
||||||
|
document.body.innerHTML = '<h1>License Expired</h1>';
|
||||||
|
throw new Error('License expired');
|
||||||
|
}}
|
||||||
|
}})();
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def generate_full_protection(
|
||||||
|
anti_debug: bool = True,
|
||||||
|
disable_shortcuts: bool = True,
|
||||||
|
console_clear: bool = True,
|
||||||
|
domain_lock: list = None,
|
||||||
|
expire_date: str = None
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
生成完整反爬保护代码
|
||||||
|
|
||||||
|
组合多种保护机制。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
anti_debug: 启用反调试
|
||||||
|
disable_shortcuts: 禁用快捷键
|
||||||
|
console_clear: 清除控制台
|
||||||
|
domain_lock: 域名锁定列表
|
||||||
|
expire_date: 过期日期
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
完整保护 JavaScript 代码
|
||||||
|
"""
|
||||||
|
parts = []
|
||||||
|
|
||||||
|
if domain_lock:
|
||||||
|
parts.append(generate_domain_lock(domain_lock))
|
||||||
|
|
||||||
|
if expire_date:
|
||||||
|
parts.append(generate_time_bomb(expire_date))
|
||||||
|
|
||||||
|
if anti_debug:
|
||||||
|
parts.append(generate_anti_debug())
|
||||||
|
|
||||||
|
if disable_shortcuts:
|
||||||
|
parts.append(generate_disable_shortcuts())
|
||||||
|
|
||||||
|
if console_clear:
|
||||||
|
parts.append(generate_console_clear())
|
||||||
|
|
||||||
|
return '\n'.join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
def inject_protection(js_code: str, **kwargs) -> str:
|
||||||
|
"""
|
||||||
|
为 JavaScript 代码注入反爬保护
|
||||||
|
|
||||||
|
Args:
|
||||||
|
js_code: 原始 JavaScript 代码
|
||||||
|
**kwargs: generate_full_protection 的参数
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
注入保护后的代码
|
||||||
|
"""
|
||||||
|
protection = generate_full_protection(**kwargs)
|
||||||
|
return protection + '\n' + js_code
|
||||||
|
|
||||||
|
|
||||||
|
def _random_vars(count: int) -> list:
|
||||||
|
"""生成随机变量名"""
|
||||||
|
chars = string.ascii_letters
|
||||||
|
vars = []
|
||||||
|
for _ in range(count):
|
||||||
|
name = '_$' + ''.join(random.choice(chars) for _ in range(6))
|
||||||
|
vars.append(name)
|
||||||
|
return vars
|
||||||
|
|
||||||
@@ -7,6 +7,8 @@ X27CN 命令行工具
|
|||||||
x27cn obfuscate <file> [output] [--key=密钥]
|
x27cn obfuscate <file> [output] [--key=密钥]
|
||||||
x27cn minify <file> [output] [--no-mangle] [--no-node]
|
x27cn minify <file> [output] [--no-mangle] [--no-node]
|
||||||
x27cn flatten <file> [output] [--intensity=2] [--safe]
|
x27cn flatten <file> [output] [--intensity=2] [--safe]
|
||||||
|
x27cn protect <file> [output] [--level=2] [--anti-crawl] # 一键保护
|
||||||
|
x27cn anti-debug # 生成反调试代码
|
||||||
x27cn password hash <password>
|
x27cn password hash <password>
|
||||||
x27cn password verify <password> <hash>
|
x27cn password verify <password> <hash>
|
||||||
x27cn password generate [--length=16]
|
x27cn password generate [--length=16]
|
||||||
@@ -22,6 +24,8 @@ from .password import (
|
|||||||
hash_password, verify_password, generate_password,
|
hash_password, verify_password, generate_password,
|
||||||
check_password_strength, encrypt_with_password, decrypt_with_password
|
check_password_strength, encrypt_with_password, decrypt_with_password
|
||||||
)
|
)
|
||||||
|
from .anti_crawl import generate_full_protection, generate_anti_debug, generate_disable_shortcuts
|
||||||
|
from .advanced import full_obfuscate, obfuscate_file_full, quick_protect
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -29,7 +33,7 @@ def main():
|
|||||||
prog='x27cn',
|
prog='x27cn',
|
||||||
description='X27CN 代码混淆加密工具'
|
description='X27CN 代码混淆加密工具'
|
||||||
)
|
)
|
||||||
parser.add_argument('--version', action='version', version='x27cn 1.3.0')
|
parser.add_argument('--version', action='version', version='x27cn 1.4.0')
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(dest='command', help='命令')
|
subparsers = parser.add_subparsers(dest='command', help='命令')
|
||||||
|
|
||||||
@@ -72,6 +76,25 @@ def main():
|
|||||||
help='扁平化强度 (1=轻, 2=中, 3=强)')
|
help='扁平化强度 (1=轻, 2=中, 3=强)')
|
||||||
flat_parser.add_argument('--safe', '-s', action='store_true', help='使用安全模式(更保守)')
|
flat_parser.add_argument('--safe', '-s', action='store_true', help='使用安全模式(更保守)')
|
||||||
|
|
||||||
|
# protect 命令(一键保护)
|
||||||
|
prot_parser = subparsers.add_parser('protect', help='一键完整保护(混淆+反爬+反调试)')
|
||||||
|
prot_parser.add_argument('input', help='输入文件 (.html/.js/.css)')
|
||||||
|
prot_parser.add_argument('output', nargs='?', help='输出文件(可选)')
|
||||||
|
prot_parser.add_argument('--key', '-k', default=DEFAULT_KEY, help='加密密钥')
|
||||||
|
prot_parser.add_argument('--level', '-l', type=int, default=2, choices=[1, 2, 3],
|
||||||
|
help='保护级别 (1=基础, 2=中等, 3=高级)')
|
||||||
|
prot_parser.add_argument('--no-anti-crawl', action='store_true', help='不添加反爬保护')
|
||||||
|
prot_parser.add_argument('--domain', '-d', action='append', help='域名锁定(可多次指定)')
|
||||||
|
prot_parser.add_argument('--expire', help='过期日期 (YYYY-MM-DD)')
|
||||||
|
|
||||||
|
# anti-debug 命令
|
||||||
|
anti_parser = subparsers.add_parser('anti-debug', help='生成反调试保护代码')
|
||||||
|
anti_parser.add_argument('--output', '-o', help='输出文件(可选)')
|
||||||
|
anti_parser.add_argument('--disable-shortcuts', '-s', action='store_true', help='包含禁用快捷键')
|
||||||
|
anti_parser.add_argument('--console-clear', '-c', action='store_true', help='包含控制台清除')
|
||||||
|
anti_parser.add_argument('--domain', '-d', action='append', help='域名锁定')
|
||||||
|
anti_parser.add_argument('--expire', help='过期日期')
|
||||||
|
|
||||||
# password 命令
|
# password 命令
|
||||||
pwd_parser = subparsers.add_parser('password', help='密码工具')
|
pwd_parser = subparsers.add_parser('password', help='密码工具')
|
||||||
pwd_subparsers = pwd_parser.add_subparsers(dest='pwd_command', help='密码子命令')
|
pwd_subparsers = pwd_parser.add_subparsers(dest='pwd_command', help='密码子命令')
|
||||||
@@ -188,6 +211,32 @@ def main():
|
|||||||
f.write(result)
|
f.write(result)
|
||||||
print(f'控制流扁平化完成: {output_path}')
|
print(f'控制流扁平化完成: {output_path}')
|
||||||
|
|
||||||
|
elif args.command == 'protect':
|
||||||
|
output = obfuscate_file_full(
|
||||||
|
args.input,
|
||||||
|
args.output,
|
||||||
|
key=args.key,
|
||||||
|
level=args.level,
|
||||||
|
anti_crawl=not args.no_anti_crawl
|
||||||
|
)
|
||||||
|
level_names = {1: '基础', 2: '中等', 3: '高级'}
|
||||||
|
print(f'保护完成 (级别: {level_names[args.level]}): {output}')
|
||||||
|
|
||||||
|
elif args.command == 'anti-debug':
|
||||||
|
code = generate_full_protection(
|
||||||
|
anti_debug=True,
|
||||||
|
disable_shortcuts=args.disable_shortcuts,
|
||||||
|
console_clear=args.console_clear,
|
||||||
|
domain_lock=args.domain,
|
||||||
|
expire_date=args.expire
|
||||||
|
)
|
||||||
|
if args.output:
|
||||||
|
with open(args.output, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(code)
|
||||||
|
print(f'反调试代码已生成: {args.output}')
|
||||||
|
else:
|
||||||
|
print(code)
|
||||||
|
|
||||||
elif args.command == 'password':
|
elif args.command == 'password':
|
||||||
if args.pwd_command == 'hash':
|
if args.pwd_command == 'hash':
|
||||||
hashed = hash_password(args.password, iterations=args.iterations)
|
hashed = hash_password(args.password, iterations=args.iterations)
|
||||||
|
|||||||
Reference in New Issue
Block a user