Blogger Information
Blog 6
fans 0
comment 0
visits 5925
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
PHPJiaMi 免扩展加密分析及解密
新月网络的博客
Original
1542 people have browsed it

0x00 前言

前几天去玩了 pwnhub 公开赛的题目,源码下载之后发现是 PHPJiaMi 加密。之前有分析过 phpjm 加密并写出过解密文件,所以研究下这个 PHPJiaMi。
PHP 免扩展加密的主流加密方法采用了 ascii 码 129-255 的乱码来实现变量名、函数名混淆,编辑器打开后就是一堆乱码,造成不可读。

加密流程:源码 -> 加密处理(压缩,替换,BASE64,转义)-> 安全处理(验证文件 MD5 值,限制 IP、限域名、限时间、防破解、防命令行调试)-> 加密程序成品,再简单的说:源码 + 加密外壳 == 加密程序 (该段出处)

0x01 解密准备

这里做演示,我写了 phpinfo() 然后去 http://www.phpjiami.com/ 生成加密文件,打开之后,果然都是一片乱码。
使用代码修复工具 http://zhaoyuanma.com/phpcodefix.html 将 ascii 不可见字符的变量修复成正常的变量名,再 PHP 代码美化,方便下一步分析。

0x02 函数分析

代码内有三个函数,由于每次加密这三个函数的顺序都不一样,这个以传参方式区分这三个函数
fun1 = ($var1, $var2 = '') = 核心函数,将乱码转成正常字符串
fun2 = (&$var1, $var2) = 校验 IP、域名,防止被破解。最后一句是解密整个 php 文件
fun3 = ($var1) = 将需要用到的函数赋值给 N 个全局变量

先从 fun1 开始逆起,在编辑器中双击变量名,该变量高亮之后,可以看到它怎么变化,在哪里被使用。
一句句语句逆下去,发现有语法错误,其实是代码修复后的 bug,用 winhex 打开定位到这句代码,发现是三元运算符

$var2 = !$var2 ? ord('乱码') : $var2;

接下来是一句很奇怪很无用的代码,再下一句是 for 循环,我猜测是给 $i 赋值

for($i=0; $i<strlen($var1); $i++)

下个 for 循环里又是一个三元运算符,手动修复后,基本 fun1 的代码就出来。
接下来就是运行 fun1 函数,但是碰到个坑点,fun1 有很多处用到乱码做运算,而乱码不能直接拷到编辑器中。
用 winhex 将 16 进制的乱码字符复制出来,在运算的时候 pack("H*","乱码") 将它还原回乱码即可。

function fun1($var1, $var2 = '')
{
   $md5 = md5(pack("H*",'FBE3FCFAF9E0'));//乱码随机字符串1
   $var2 = !$var2?ord(pack("H*",'8C')):$var2;//乱码随机字符串2
   
   $str = '';    for($i=0; $i<strlen($var1); $i++)
   {
       $str .= ord($var1{$i}) < ord(pack("H*",'F5')) ? ((ord($var1{$i}) > $var2 && ord($var1{$i}) < ord(pack("H*",'F5'))) ? chr(ord($var1{$i}) / 2) : $var1{$i}) : '';
   }
   $de1 =  base64_decode($str);
   $len = $len2 = strlen($md5);
   $str2 = '';    for($i=0; $i<strlen($de1); $i++)
   {
       $len = $len ? $len : $len2;
       $len--;
       $str2 .= $de1[$i] ^ $md5[$len];
   }    return $str2;
}

接着开始还原 fun2 代码,fun2 中前面都调用了 fun1 解密字符串,解密可得到 fun2 后面需要用到的函数名。有了 fun1,后面解密都非常顺利

function fun2(&$var1, $var2){
   $de = str_rot13(strrev(gzuncompress(stripslashes(fun1(pack('H*','8ECA349A37A639E43946ACE4B242F4EED8E8A0CC4444E639E894C2C69CB0384134EEEEC6CA3233B433ECD89CC6D435A437CE98B0D2A092909E96D030EE8EA2A4D044CADCA2DC32CCE02BAADCEEEA4537D8ACB43298F238E0428EC29646A0CAA2EECA43D2B2C442F4C4358E46429434AE44B0DACAF0AE4190C845EE32AE34C82BC49494E22BCAA49CD6D2E8CA94D2D4A6329C929A3596F2CC36CCD6CCAAF0C646D0A69EC8F02FA2A03938D234C2D2E0DCCCCAC4A8A631AC4238C4A490ECD4CCF0DAF4CAB2'))))));
   $exp = explode(',', $de);
   $var1 = $exp[$var2];
}

$de 解出来是一堆函数名,然后赋值给全局变量,后面解密都需要用到。fun2 解出来是固定的字符串

,chr,addslashes,rand,gzuncompress,assert_options,assert,file_exists,file_get_contents,substr,unpack,constant,strpos,create_function,str_rot13,md5,set_include_path,dirname,preg_replace,base64_encode,base64_decode,

接着暂且先不看 fun3,回到主代码中。

这里创建了一堆全局变量,通过 fun2 赋值,每个变量都代表一个函数名

接着还原 fun3 函数,步骤一样。

function fun3(){
   php_sapi_name() == 'cli' ? die():'';
   $file = file_get_contents(__FILE__);    if(!isset($_SERVER['HTTP_HOST']) && !isset($_SERVER['SERVER_ADDR']) && !isset($_SERVER['REMOTE_ADDR']))
   {        die();
   }
   $time = microtime(true) * 1000;    if(microtime(true) * 1000 - $time > 100)
   {        die();
   }    if(strpos(__FILE__, gtmclaei) !== 0){$exitfunc();}
   !strpos(de1(substr($file, de1('A8414145'), de1('A841AA3D'))), md5(substr($file, de1('AAA23D3D'), de1('A8414190')))) ? unkonw1() : unkonw2();
   $loc1 = fun1('A841AA45ACEE3D3D');
   $loc1 = fun1('A8414190');
   $de = str_rot13(gzuncompress(fun1(substr($file, $loc1, $loc2))));//核心解密
   return $de;
}

后面的代码已经不用再看了,fun2 解出来的就是解密后的原代码。

最后附上解密脚本 http://sec2hack.com/phpjiami.zip


Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!