feat(x27cn): v1.4.0 添加一键保护和反爬功能

This commit is contained in:
violettools
2026-01-26 00:37:48 +08:00
parent 6e25f036e8
commit 9401a98384
6 changed files with 800 additions and 6 deletions

View File

@@ -352,6 +352,120 @@ x27cn encrypt secret.txt --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 提供两种安全级别:
@@ -398,6 +512,14 @@ X27CN 提供两种安全级别:
| `encrypt_with_password(data, pwd)` | 密码加密数据 |
| `decrypt_with_password(data, pwd)` | 密码解密数据 |
| `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

View File

@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
[project]
name = "x27cn"
version = "1.3.0"
description = "X27CN 代码混淆加密库 - Code obfuscation and encryption library"
version = "1.4.0"
description = "X27CN - Advanced code obfuscation, encryption and anti-crawl protection"
readme = "README.md"
license = "MIT"
requires-python = ">=3.7"
@@ -19,8 +19,9 @@ keywords = [
"encoding",
"html",
"javascript",
"加密",
"混淆"
"anti-debug",
"anti-crawl",
"code-protection"
]
classifiers = [
"Development Status :: 4 - Beta",

View File

@@ -68,7 +68,26 @@ from .password import (
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'
__all__ = [
# 核心加密
@@ -111,5 +130,20 @@ __all__ = [
'md5',
'sha256',
'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
View 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
View 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

View File

@@ -7,6 +7,8 @@ X27CN 命令行工具
x27cn obfuscate <file> [output] [--key=密钥]
x27cn minify <file> [output] [--no-mangle] [--no-node]
x27cn flatten <file> [output] [--intensity=2] [--safe]
x27cn protect <file> [output] [--level=2] [--anti-crawl] # 一键保护
x27cn anti-debug # 生成反调试代码
x27cn password hash <password>
x27cn password verify <password> <hash>
x27cn password generate [--length=16]
@@ -22,6 +24,8 @@ from .password import (
hash_password, verify_password, generate_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():
@@ -29,7 +33,7 @@ def main():
prog='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='命令')
@@ -72,6 +76,25 @@ def main():
help='扁平化强度 (1=轻, 2=中, 3=强)')
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 命令
pwd_parser = subparsers.add_parser('password', help='密码工具')
pwd_subparsers = pwd_parser.add_subparsers(dest='pwd_command', help='密码子命令')
@@ -188,6 +211,32 @@ def main():
f.write(result)
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':
if args.pwd_command == 'hash':
hashed = hash_password(args.password, iterations=args.iterations)