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

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


Mine吧 » _kstr2混淆解密

7 评论

  1. && $node->stmts[0] instanceof PhpParser\Node\Stmt\Expression
    && $node->stmts[1] instanceof PhpParser\Node\Stmt\Expression
    && $node->stmts[2] instanceof PhpParser\Node\Stmt\Expression
    ide提示说:undefined class…博主用的php-parser是那个版本的呢?万谢

  2. 提示PhpParser\Node\Stmt\Expression 这类不存在,好像github上的代码中好像也没找到这个类。请教下博主,这个类是要自己写的吗还是?

    1. PHP-Parser 4.4的

      1. 找到了,谢谢谢谢…不过_kstr2转换出来的还是乱码。。是不是因为加密脚本和您文章里的不一样的导致的呢?不知放不方便加一下博主好友请教下..

        1. 乱码的是变量名称,替换成var1 var2 … 就好了

          1. 嗯嗯,我这转换出来的$GLOBALS数组里的下标也是乱码。。没办法,硬着头皮看了下代码,不过好像没有我想要的东西。不过还是谢谢博主了,才知道php-parser还有这个用法的

发表评论