标签: PHP-Parser

  • _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代码格式化

    经常用到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目录中的相关文件。