分类: 破解

  • _kstr2混淆解密

    老规矩,先分析代码。代码的一开始就定义了一个_kstr2的函数,这个函数就是将传入的字符串,转换成明码字符串;从上图中也可以看出,代码中大量调用了这个函数,我们需要找出这些函数调用,并经过_kstr2函数运算后得出的明码替换在原来的位置就好差不多了;我们可以用正则匹配,执行_kstr2函数后,再替换到相应的位置;或者也可以用PHP-Parser遍历ast节点,找出相应节点,并替换成明码字符;正则替换比较容易,写个正则表达式,循环替换就ok,不过可能会有些意外情况,需要多调试几次;用 PHP-Parser 遍历ast节点就相对容易一些,下面给出部分代码:

    class ConstGlobalNodeVisitor extends NodeVisitorAbstract{
        public $constVars,$globalVars;
        public function leaveNode(Node $node){
    	//删除_kstr2函数定义代码
            if ($node instanceof PhpParser\Node\Stmt\If_
                && $node->cond instanceof PhpParser\Node\Expr\BooleanNot
                && $node->cond->expr instanceof PhpParser\Node\Expr\FuncCall
                && $node->cond->expr->name instanceof PhpParser\Node\Name
                && $node->cond->expr->name->parts[0] === 'function_exists'
                && $node->cond->expr->args[0] instanceof PhpParser\Node\Arg
                && $node->cond->expr->args[0]->value instanceof Node\Scalar\String_
                && $node->cond->expr->args[0]->byRef === false
                && $node->cond->expr->args[0]->unpack === false
                && $node->stmts[0] instanceof PhpParser\Node\Stmt\Expression
                && $node->stmts[1] instanceof PhpParser\Node\Stmt\Expression
                && $node->stmts[2] instanceof PhpParser\Node\Stmt\Expression
                && $node->stmts[3] instanceof PhpParser\Node\Stmt\If_
                && $node->stmts[4] instanceof PhpParser\Node\Stmt\Function_
            ) {
    			return NodeTraverser::REMOVE_NODE;
    	}
    	//替换_kstr2函数调用为正常代码
    	if ($node instanceof PhpParser\Node\Expr\FuncCall
    		&& $node->name instanceof PhpParser\Node\Name
    		&& $node->name->parts[0] === "_kstr2"
    		&& $node->args[0] instanceof PhpParser\Node\Arg
    		&& $node->args[0]->value  instanceof PhpParser\Node\Scalar\String_
    		&& $node->args[0]->byRef === false
    		&& $node->args[0]->unpack === false){
    			return new Node\Scalar\String_(_kstr2($node->args[0]->value->value));
    	}
        }
    }
    //其中_kstr2函数来自网络https://www.php.cn/php-ask-432462.html,有兴趣的朋友可以过去查看。

    然后将上述节点遍历类加入Php-Parser的节点遍历中,代码如下:

    $code = file_get_contents($file);
    $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
    
    try {
        $ast = $parser->parse($code);
    } catch (Error $error) {
        echo "Parse error: {$error->getMessage()}\n";
        return;
    }
    $nodeVisitor = new ConstGlobalNodeVisitor();
    $traverser = new NodeTraverser();
    $traverser->addVisitor($nodeVisitor);
    $ast = $traverser->traverse($ast);
    $prettyPrinter = new Standard;
    $code = $prettyPrinter->prettyPrintFile($ast);
    echo $code;

    经过处理后的代码如下图:

    可以看到还有一些GLOBALS变量和define常量,都可以加到节点遍历中,替换成相应的值,最后发现还有一些变量名混淆,替换成arg,替换后最终得到的解密文件部分截图如下:

    仅记录一下解密过程,最终解密代码就不放出了,以免泛滥。这种加密比较简单,解起来也很顺利,没有什么梗。如果此文侵犯到了您的商业利益,请联系站长删除。

  • PHP免费在线解密

    先上链接: http://decode.zwtt8.com/

    能解一些简单的eval混淆加密,像 V盾、PHPJM、zym等,还有一些不常见的eval,小伙伴们都可以去试一下。

    解密方法整理自网络,调试通过,请使用本工具的小伙伴,不要侵犯别人的商业利益,解密后的代码仅供参考和借鉴,请不要发布授权程序的破解版,作者开发不易,请支持正版。否则一切后果,自行承担。

    如若有侵权情况,请联系站长删除,谢谢合作。

  • PHP代码格式化

    经常用到php代码格式化,原来都是在本地搭建的站点里调用php-parser来格式化,有点不方便,每次还要复制文件到网站目录,然后还要改程序,索性花点时间做个工具,挂在网上,有需要的小伙伴可以看过来了。

    格式化部分利用php-parser来实现的,前台UI使用了layui,挺方便的,代码编辑器本来是想用layui的,但是没有编辑功能,百度找到了一款codemirror的编辑器,确实有点强,最终花了半天时间做出来了。

    附上链接:http://decode.zwtt8.com/format.html

    感兴趣的小伙伴可以去看下。

  • PHP-Parser常用节点构造方法

    函数调用

    new PhpParser\Node\Expr\FuncCall(
    	new Node\Name($funcName)//函数名
    	,array($arg1, $arg2)//函数参数
    );

    类成员调用

    new PhpParser\Node\Expr\MethodCall(
    	new PhpParser\Node\Expr\Variable($className)//类实例变量名
    	, new PhpParser\Node\Identifier($O0[1]->value->value)//类成员函数
    	, $_p//成员函数参数
    );

    字符串

    new Node\Scalar\String_('hello world');

    更多节点构造,可参考PhpParser源码中PhpParser/Node目录中的相关文件。

  • 搭建xcache的zend解密程序

    在某论坛上发现zend解密是由xcache的组件完成的,iis中部署了一个php5.4.9的环境,配置好zendloder.dll和php_xcache.dll后,就可以解密了。

    在配置环境的时候遇到一些问题,大部分是php版本和相应组件版本不符造成的。期间想搜索一些相关的搭建经验或者教程,发现百度上根本没有,所以只能自己动手慢慢摸索了。

    百度上有一个免费解zend加密的站,不过只能一个个文件解,不支持批量解密,问了一下批量解密还挺贵,所以决定在此记录一下过程:

    主要记录一下centos系统的编译安装过程,xcache的官方页面有相关说明( http://xcache.lighttpd.net/wiki/BuildingFromSource ),本人也是根据这里的步骤安装。

    zend解密需要安装cacher coverager  disassembler 模块,否则会报错Fatal error: Call to undefined function xcache_dasm_file 编译语句如下:

    ./configure –enable-xcache –enable-xcache-coverager –enable-xcache-disassembler –with-php-config=/www/server/php/54/bin/php-config

    编译成功,也修改了xcache.so的路径,但是phpinfo()显示根本没有相应模块,很是纳闷儿。

    最后把php卸载重新安装,xcache重新编译,就好了,有可能phpinfo已经被xcache给缓存了,造成上述问题。

  • PHP混淆解密之pack还原大法

    先看一段代码:

    图中代码已经格式化,可以看到有大量pack,当然,不只截图中的这些,手动替换的话,肯定要换到手软。当然了,肯定有自动替换的方法,mine就想到了一个比较笨的办法,下边详细说下。

    分析下代码,上边是pack参数的数组,存在Globals变量中,这些数组就不管了,我们直接把有pack的代码行,变成一个字符串,然后把pack部分分离出来,接到代码中,例如:

    echo'$GLOBALS["'.pack("H*", $GLOBALS[AAAAA____][0x5]).'"] = "'.pack("H*", $GLOBALS[AAAAA____][06]).'";';

    这样就会把这一行代码直接打印出来,打印出来后pack就被替换成真正的字符了,当然必须得自动化处理,代码如下:

    <?php
    $txt = file('1.php');//按行读取目标文件1.php
    foreach($txt as $t){
    	$t = str_replace("'", "\'", $t);//转义
    	$t = toPack($t);
    	echo 'echo \''.$t.'\';';
    }
    
    function toPack($t){
    	preg_match_all('/pack\([^\)]*?\)/s', $t, $pack);
    	if($pack){
    		foreach($pack[0] as $p){
    			$t = str_replace($p, '"\'.'.$p.'.\'"', $t);
    		}
    	}
    	return $t;
    }
    ?>

    经过处理后,输出的代码要替换原来的文件内容,运行一遍,才会得到去除pack的代码。

    当然了,利用这种方法还能还原一些全局变量或者其他的加密标签,你可以改造得更智能,更自动化,本文仅分享一下思路,希望对你有所启发。

  • PhpParser还可以用来解密

    接了一个解密的单子,看了下程序代码,有大量的goto语句。刚开始以为可以用正则匹配并还原代码位置,就解决问题了,到了真正处理的时候,发现这样根本行不通。网上查了很多,都没有现成的解密工具。

    这种其实也不算是加密,只是打乱了代码的顺序,理论上是可以手动还原的,但实际上,手动的话,会让你感到怀疑人生,因为代码量太大了。

    发现有人用PhpParser来解密,这个工具本来是用来格式化php代码的。

    以下内容来自网络:

    单纯的if语句:这种单一存在的语句在混淆器中处理后,其中的condition会被反向 也就是条件反向的处理,所以处理if语句前需要遍历一次语法树进行condition的反向还原,即de_cond
    
    复杂的if语句:比如if..else..和if..elseif..else等,这种if语句的处理只需正常处理即可
    
    嵌套if语句:编程过程中,语句的嵌套是不可少的,而在混淆器处理过的代码中是没有嵌套可言的,一切都是在外层存在的,在处理if过程中,加入一个节点嗅探,如果嗅探到所嵌套的节点有if语法,则让本次混淆节点再走一遍综合if解析 ([funcion parse_if_stmt])
    
    正常stmt混淆:比如echo "hello world";会被混淆成label xxxx: echo "hello world"; goto next_label;,也就是三个语法块为一条语句,然后使用这三个语法点构成一个混淆节点,类似$tunk[] = array($label,$stmt,$goto),其他语句相同
    
    这里还原难度最大的还是if语句的还原,以为还涉及嵌套的if。下面是if语句的语句处理点:
    
    解析elseif语法:如果当前节点的下一个节点为if语法块,则进行elseif的还原
    
    解析else语法:如果遇到的混淆中间节点为goto的,则认定为else语句结束点并进行结束处理。
    
    检测是否为跳点:由于混淆器内部会有多余的label进行干扰,需要构建一个跳点检测器进行跳点处理,处理foreach等loop语句的干扰节点,遇到这些节点后将跳过一个混淆节点。
    
    建立节点监听器:最后需要有一个语法树的traverse,你可以建立一个自己的节点监听器,监听过来的语法,然后处理如function、ClassMethod、TryCatch等节点的混淆语法树。
    
    最后说说我写解密脚本过程遇到的问题吧。
    
    对于上面提到的正常的stmt混淆的还原还是比较简单的,写脚本的第一天就完成了这一步。
    
    最让人头疼的还是处理if语句,外层的还原还是很简单的,但是遇到嵌套的处理时就非常头大了,我一共用了3天写这个脚本,其中两天都是在处理if语句。