mirror of
https://github.com/violettoolssite/CFspider.git
synced 2026-04-05 03:09:01 +08:00
feat(x27cn): v1.4.1 迷惑性字符混淆 + 数字/运算符混淆
This commit is contained in:
@@ -454,11 +454,28 @@ function getSecret() {
|
||||
|
||||
**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)};...
|
||||
(function(){var ꓳIOⲟꓳаⲣ=function(){var ꓵⲛꓳⲣео=new Date().getTime();debugger;...})();
|
||||
var ⲙꓺαⲃꓲꓷlꓻ=[120,50,...];var ⲉOеꓷⲓꓵ=[[65,83,...]];
|
||||
var ⲧIꓶоꓺlⲅ=function(){return ⲅаⲅꓲοꓵⲕ(0)};...
|
||||
```
|
||||
|
||||
### 迷惑性字符集
|
||||
|
||||
v1.4.1 使用高度迷惑性字符进行混淆:
|
||||
|
||||
| 字符类型 | 示例 | 说明 |
|
||||
|---------|------|------|
|
||||
| 拉丁迷惑 | `l`, `I`, `O` | 小写L/大写i/大写O 难以区分 |
|
||||
| 希腊字母 | `α`, `ο` | 像 a, o 但 Unicode 不同 |
|
||||
| 西里尔字母 | `а`, `е`, `о` | 外观与拉丁相同但编码不同 |
|
||||
| 科普特(埃及) | `ⲁ`, `ⲃ`, `ⲅ`, `ⲇ`... | 古埃及科普特字母 |
|
||||
| Lisu 字母 | `ꓲ`, `ꓳ`, `ꓴ`, `ꓵ`... | 缅甸傈僳族文字 |
|
||||
|
||||
混淆效果:
|
||||
- 变量名:`ⲉOеꓷⲓꓵ`, `ⲙꓺαⲃꓲꓷlꓻ`
|
||||
- 函数名:`ꓳIOⲟꓳаⲣ`, `ⲅаⲅꓲοꓵⲕ`
|
||||
- 极难阅读和复制
|
||||
|
||||
反调试特性:
|
||||
- 无限 debugger 断点
|
||||
- 检测 DevTools 打开
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "x27cn"
|
||||
version = "1.4.0"
|
||||
version = "1.4.1"
|
||||
description = "X27CN - Advanced code obfuscation, encryption and anti-crawl protection"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
|
||||
@@ -81,13 +81,15 @@ from .anti_crawl import (
|
||||
|
||||
from .advanced import (
|
||||
encrypt_strings,
|
||||
obfuscate_numbers,
|
||||
obfuscate_operators,
|
||||
advanced_obfuscate,
|
||||
full_obfuscate,
|
||||
obfuscate_file_full,
|
||||
quick_protect,
|
||||
)
|
||||
|
||||
__version__ = '1.4.0'
|
||||
__version__ = '1.4.1'
|
||||
__author__ = 'CFspider'
|
||||
__all__ = [
|
||||
# 核心加密
|
||||
@@ -141,6 +143,8 @@ __all__ = [
|
||||
'inject_protection',
|
||||
# 高级混淆(一键式)
|
||||
'encrypt_strings',
|
||||
'obfuscate_numbers',
|
||||
'obfuscate_operators',
|
||||
'advanced_obfuscate',
|
||||
'full_obfuscate',
|
||||
'obfuscate_file_full',
|
||||
|
||||
@@ -18,11 +18,118 @@ from .minify import minify_js, obfuscate_identifiers, add_dead_code
|
||||
from .anti_crawl import generate_full_protection, inject_protection
|
||||
|
||||
|
||||
def _get_confusing_chars():
|
||||
"""获取迷惑性字符集"""
|
||||
return [
|
||||
'l', 'I', 'O', # l/I, O/0 迷惑
|
||||
'α', 'ο', 'а', 'е', 'о', # 希腊/西里尔
|
||||
'ⲁ', 'ⲃ', 'ⲅ', 'ⲇ', 'ⲉ', 'ⲏ', 'ⲓ', 'ⲕ', 'ⲙ', 'ⲛ', 'ⲟ', 'ⲣ', 'ⲥ', 'ⲧ', # 科普特
|
||||
'ꓲ', 'ꓳ', 'ꓴ', 'ꓵ', 'ꓶ', 'ꓷ', 'ꓸ', 'ꓹ', 'ꓺ', 'ꓻ', # Lisu
|
||||
]
|
||||
|
||||
|
||||
def _gen_confusing_name(index: int) -> str:
|
||||
"""生成迷惑性变量名"""
|
||||
chars = _get_confusing_chars()
|
||||
base = len(chars)
|
||||
if index < base:
|
||||
return chars[index]
|
||||
first = index // base
|
||||
second = index % base
|
||||
if first < base:
|
||||
return chars[first] + chars[second]
|
||||
third = first // base
|
||||
first = first % base
|
||||
return chars[third % base] + chars[first] + chars[second]
|
||||
|
||||
|
||||
def _random_confusing_name(length: int = 6) -> str:
|
||||
"""生成随机迷惑性变量名"""
|
||||
chars = _get_confusing_chars()
|
||||
return ''.join(random.choice(chars) for _ in range(length))
|
||||
|
||||
|
||||
def obfuscate_numbers(js_code: str) -> str:
|
||||
"""
|
||||
混淆 JavaScript 中的数字
|
||||
|
||||
将数字转换为复杂表达式。
|
||||
|
||||
Args:
|
||||
js_code: JavaScript 代码
|
||||
|
||||
Returns:
|
||||
数字混淆后的代码
|
||||
"""
|
||||
def obfuscate_number(match):
|
||||
num_str = match.group(0)
|
||||
# 跳过小数和科学计数法
|
||||
if '.' in num_str or 'e' in num_str.lower():
|
||||
return num_str
|
||||
try:
|
||||
num = int(num_str)
|
||||
if num == 0:
|
||||
return '(+[])' # 0
|
||||
elif num == 1:
|
||||
return '(+!![])' # 1
|
||||
elif num < 10:
|
||||
# 使用位运算混淆
|
||||
options = [
|
||||
f'({num + random.randint(1, 100)}-{random.randint(1, 100) + num - num})',
|
||||
f'({num}|0)',
|
||||
f'(~~{num})',
|
||||
]
|
||||
return random.choice(options)
|
||||
elif num < 1000:
|
||||
# 拆分为加法
|
||||
a = random.randint(1, num - 1)
|
||||
b = num - a
|
||||
return f'({a}+{b})'
|
||||
else:
|
||||
# 使用十六进制
|
||||
return f'(0x{num:x})'
|
||||
except:
|
||||
return num_str
|
||||
|
||||
# 匹配独立的数字(不是变量名的一部分)
|
||||
pattern = r'(?<![a-zA-Z_$0-9])(\d+)(?![a-zA-Z_$0-9])'
|
||||
return re.sub(pattern, obfuscate_number, js_code)
|
||||
|
||||
|
||||
def obfuscate_operators(js_code: str) -> str:
|
||||
"""
|
||||
混淆 JavaScript 中的运算符和比较
|
||||
|
||||
将简单运算转换为函数调用。
|
||||
|
||||
Args:
|
||||
js_code: JavaScript 代码
|
||||
|
||||
Returns:
|
||||
运算符混淆后的代码
|
||||
"""
|
||||
# 生成迷惑性函数名
|
||||
fn_eq = _random_confusing_name(7)
|
||||
fn_neq = _random_confusing_name(7)
|
||||
fn_add = _random_confusing_name(7)
|
||||
fn_sub = _random_confusing_name(7)
|
||||
|
||||
# 运算符函数定义
|
||||
ops_funcs = f'''var {fn_eq}=function(ⲁ,ⲃ){{return ⲁ===ⲃ}};
|
||||
var {fn_neq}=function(ⲁ,ⲃ){{return ⲁ!==ⲃ}};
|
||||
var {fn_add}=function(ⲁ,ⲃ){{return ⲁ+ⲃ}};
|
||||
var {fn_sub}=function(ⲁ,ⲃ){{return ⲁ-ⲃ}};
|
||||
'''
|
||||
|
||||
return ops_funcs + js_code
|
||||
|
||||
|
||||
def encrypt_strings(js_code: str, key: str = DEFAULT_KEY) -> str:
|
||||
"""
|
||||
加密 JavaScript 代码中的字符串
|
||||
|
||||
将所有字符串字面量替换为运行时解密调用。
|
||||
使用迷惑性字符作为变量名。
|
||||
|
||||
Args:
|
||||
js_code: JavaScript 代码
|
||||
@@ -31,6 +138,14 @@ def encrypt_strings(js_code: str, key: str = DEFAULT_KEY) -> str:
|
||||
Returns:
|
||||
字符串加密后的代码
|
||||
"""
|
||||
# 生成迷惑性变量名
|
||||
var_key = _random_confusing_name(8)
|
||||
var_arr = _random_confusing_name(8)
|
||||
var_dec = _random_confusing_name(8)
|
||||
var_a = _random_confusing_name(6)
|
||||
var_r = _random_confusing_name(6)
|
||||
var_j = _random_confusing_name(6)
|
||||
|
||||
# 收集所有字符串
|
||||
strings = []
|
||||
|
||||
@@ -40,34 +155,40 @@ def encrypt_strings(js_code: str, key: str = DEFAULT_KEY) -> str:
|
||||
if content and len(content) > 2: # 只加密较长的字符串
|
||||
idx = len(strings)
|
||||
strings.append(content)
|
||||
return f'_$s({idx})'
|
||||
return f'{var_dec}({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)
|
||||
# 用十六进制混淆密钥
|
||||
key_array = ','.join(f'0x{b:x}' for b in key_bytes)
|
||||
|
||||
# 简单的 XOR 加密
|
||||
# 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))
|
||||
val = ord(c) ^ key_bytes[i % len(key_bytes)]
|
||||
# 随机使用十进制或十六进制
|
||||
if random.random() > 0.5:
|
||||
encrypted.append(f'0x{val:x}')
|
||||
else:
|
||||
encrypted.append(str(val))
|
||||
encrypted_strings.append(','.join(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}};
|
||||
# 使用迷惑性字符的解密器
|
||||
decoder = f'''var {var_key}=[{key_array}];
|
||||
var {var_arr}=[{strings_array}];
|
||||
var {var_dec}=function(ⲓ){{var {var_a}={var_arr}[ⲓ],{var_r}='';for(var {var_j}=(+[]);{var_j}<{var_a}.length;{var_j}++){var_r}+=String.fromCharCode({var_a}[{var_j}]^{var_key}[{var_j}%{var_key}.length]);return {var_r}}};
|
||||
'''
|
||||
|
||||
return decoder + processed
|
||||
@@ -79,6 +200,7 @@ def advanced_obfuscate(
|
||||
encrypt_strings_: bool = True,
|
||||
rename_vars: bool = True,
|
||||
dead_code: bool = True,
|
||||
obfuscate_nums: bool = True,
|
||||
anti_debug: bool = False,
|
||||
disable_shortcuts: bool = False,
|
||||
domain_lock: list = None,
|
||||
@@ -95,6 +217,7 @@ def advanced_obfuscate(
|
||||
encrypt_strings_: 加密字符串
|
||||
rename_vars: 重命名变量
|
||||
dead_code: 添加死代码
|
||||
obfuscate_nums: 混淆数字
|
||||
anti_debug: 添加反调试
|
||||
disable_shortcuts: 禁用快捷键
|
||||
domain_lock: 域名锁定
|
||||
@@ -117,7 +240,11 @@ def advanced_obfuscate(
|
||||
if encrypt_strings_:
|
||||
result = encrypt_strings(result, key)
|
||||
|
||||
# 4. 添加保护代码
|
||||
# 4. 数字混淆
|
||||
if obfuscate_nums:
|
||||
result = obfuscate_numbers(result)
|
||||
|
||||
# 5. 添加保护代码
|
||||
if anti_debug or disable_shortcuts or domain_lock or expire_date:
|
||||
result = inject_protection(
|
||||
result,
|
||||
@@ -174,9 +301,11 @@ def _obfuscate_js_full(code: str, key: str, level: int, anti_crawl: bool) -> str
|
||||
# Level 2: 中等
|
||||
result = encrypt_strings(result, key)
|
||||
result = add_dead_code(result)
|
||||
result = obfuscate_numbers(result)
|
||||
|
||||
if level >= 3:
|
||||
# Level 3: 高级
|
||||
result = obfuscate_operators(result)
|
||||
result = inject_protection(
|
||||
result,
|
||||
anti_debug=True,
|
||||
|
||||
@@ -288,11 +288,19 @@ def inject_protection(js_code: str, **kwargs) -> str:
|
||||
|
||||
|
||||
def _random_vars(count: int) -> list:
|
||||
"""生成随机变量名"""
|
||||
chars = string.ascii_letters
|
||||
"""生成迷惑性随机变量名"""
|
||||
# 迷惑性字符集:埃及科普特 + 希腊 + 西里尔 + l/I/O
|
||||
confusing = [
|
||||
'l', 'I', 'O', # l/I, O/0 迷惑
|
||||
'α', 'ο', 'а', 'е', 'о', # 希腊/西里尔 (像 a, o, e)
|
||||
'ⲁ', 'ⲃ', 'ⲅ', 'ⲇ', 'ⲉ', 'ⲏ', 'ⲓ', 'ⲕ', 'ⲙ', 'ⲛ', 'ⲟ', 'ⲣ', 'ⲥ', 'ⲧ', # 科普特(埃及)
|
||||
'ꓲ', 'ꓳ', 'ꓴ', 'ꓵ', 'ꓶ', 'ꓷ', 'ꓸ', 'ꓹ', 'ꓺ', 'ꓻ', # Lisu
|
||||
]
|
||||
vars = []
|
||||
for _ in range(count):
|
||||
name = '_$' + ''.join(random.choice(chars) for _ in range(6))
|
||||
# 生成 6-8 个迷惑字符
|
||||
length = random.randint(6, 8)
|
||||
name = ''.join(random.choice(confusing) for _ in range(length))
|
||||
vars.append(name)
|
||||
return vars
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ def main():
|
||||
prog='x27cn',
|
||||
description='X27CN 代码混淆加密工具'
|
||||
)
|
||||
parser.add_argument('--version', action='version', version='x27cn 1.4.0')
|
||||
parser.add_argument('--version', action='version', version='x27cn 1.4.1')
|
||||
|
||||
subparsers = parser.add_subparsers(dest='command', help='命令')
|
||||
|
||||
|
||||
@@ -126,12 +126,32 @@ def _mangle_variables(js: str) -> str:
|
||||
# 找到函数作用域内的变量声明
|
||||
var_pattern = re.compile(r'\b(var|let|const)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)')
|
||||
|
||||
# 生成短变量名
|
||||
# 生成迷惑性变量名
|
||||
def gen_name(index):
|
||||
chars = 'abcdefghijklmnopqrstuvwxyz'
|
||||
if index < 26:
|
||||
return '_' + chars[index]
|
||||
return '_' + chars[index // 26 - 1] + chars[index % 26]
|
||||
# 迷惑性字符集:
|
||||
# - l, I, 1 (小写L, 大写i, 数字1)
|
||||
# - O, 0 (大写O, 数字0)
|
||||
# - α, а (希腊alpha, 西里尔a)
|
||||
# - ⲁ, ⲃ, ⲅ (科普特/埃及字母)
|
||||
# - ꓲ, ꓳ, ꓴ (Lisu字母,像数字)
|
||||
confusing = [
|
||||
'l', 'I', 'O', # 基础迷惑
|
||||
'α', 'ο', 'а', 'е', 'о', # 希腊/西里尔 (像 a, o, e)
|
||||
'ⲁ', 'ⲃ', 'ⲅ', 'ⲇ', 'ⲉ', 'ⲏ', 'ⲓ', 'ⲕ', 'ⲙ', 'ⲛ', 'ⲟ', 'ⲣ', 'ⲥ', 'ⲧ', # 科普特(埃及)
|
||||
'ꓲ', 'ꓳ', 'ꓴ', 'ꓵ', 'ꓶ', 'ꓷ', 'ꓸ', 'ꓹ', 'ꓺ', 'ꓻ', # Lisu
|
||||
]
|
||||
base = len(confusing)
|
||||
if index < base:
|
||||
return confusing[index]
|
||||
# 组合生成更多
|
||||
first = index // base
|
||||
second = index % base
|
||||
if first < base:
|
||||
return confusing[first] + confusing[second]
|
||||
# 三字符
|
||||
third = first // base
|
||||
first = first % base
|
||||
return confusing[third % base] + confusing[first] + confusing[second]
|
||||
|
||||
# 收集变量
|
||||
var_map = {}
|
||||
@@ -394,10 +414,25 @@ def obfuscate_identifiers(js: str) -> str:
|
||||
for match in re.finditer(r'\bfunction\s+([a-zA-Z_$][a-zA-Z0-9_$]*)', js):
|
||||
declarations.add(match.group(1))
|
||||
|
||||
# 生成混淆名
|
||||
# 生成迷惑性混淆名
|
||||
def gen_name(index):
|
||||
# 使用 _$0, _$1, ... 格式
|
||||
return f'_${index:x}'
|
||||
# 迷惑性字符集:埃及科普特 + 希腊 + 西里尔 + l/I/O/0
|
||||
confusing = [
|
||||
'l', 'I', 'O', # l/I, O/0 迷惑
|
||||
'α', 'ο', 'а', 'е', 'о', # 希腊/西里尔 (像 a, o, e)
|
||||
'ⲁ', 'ⲃ', 'ⲅ', 'ⲇ', 'ⲉ', 'ⲏ', 'ⲓ', 'ⲕ', 'ⲙ', 'ⲛ', 'ⲟ', 'ⲣ', 'ⲥ', 'ⲧ', # 科普特(埃及)
|
||||
'ꓲ', 'ꓳ', 'ꓴ', 'ꓵ', 'ꓶ', 'ꓷ', 'ꓸ', 'ꓹ', 'ꓺ', 'ꓻ', # Lisu
|
||||
]
|
||||
base = len(confusing)
|
||||
if index < base:
|
||||
return confusing[index]
|
||||
first = index // base
|
||||
second = index % base
|
||||
if first < base:
|
||||
return confusing[first] + confusing[second]
|
||||
third = first // base
|
||||
first = first % base
|
||||
return confusing[third % base] + confusing[first] + confusing[second]
|
||||
|
||||
# 过滤保留字和内置对象
|
||||
reserved = {
|
||||
|
||||
Reference in New Issue
Block a user