标签: 逆向调试

  • _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,替换后最终得到的解密文件部分截图如下:

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