follow my dream

初识PHP-Parser

字数统计: 869阅读时长: 4 min
2020/09/13 Share

PHP-Parser 用于代码混淆的代码

learn from

http://j0k3r.top/2020/03/24/php-Deobfuscator/#0x01-php-parser

https://github.com/nikic/PHP-Parser/tree/master/doc

下载

curl -s http://getcomposer.org/installer | php

遇到权限问题时,可以输入一下命令

sudo chown -R 'user-name' /home/'user-name'/.composer

之后再在所需项目中php composer.phar require nikic/php-parser

为了更方便调用composer,可以输入一下命令

mv composer.phar /usr/local/bin/composer

如果composer require nikic/php-parse遇到长时间卡住,可以尝试更新源

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

项目: https://github.com/nikic/PHP-Parser

runoob 再次好用

生成AST

首先介绍一下PHP-Parser中定义的一些节点类型:

(1)PhpParser\Node\Stmt是语句节点,不带任何返回信息(return)的结构,如赋值语句”$a = $b” ;

(2)PhpParser\Node\Expr是表达式节点,可以返回一个值的语言结构,如$var和func()。

(3)PhpParser\Node\Scalar是常量节点,可以用来表示任何常量值。如’string’,0,以及常量表达式。

(4)还有一些节点没有包括进去,如参数节点(PhpParser\Node\Arg)。

一些节点类的名称使用了下划线,这是为了避免和PHP关键字冲突。

PHP-parser的test.php下,该代码片段会生成AST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
use PhpParser\Error;
use PhpParser\ParserFactory;
require dirname(__FILE__).'/vendor/autoload.php'; #composer require nikic/php-parse 成功后会生成这个文件,当然还有其他的文件
$code = <<<'CODE'
<?php

echo 'Hello PHP';
CODE;

$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);// 优先解析 PHP7 代码

try {
$stmts = $parser->parse($code);//使用 ParserFactory 的 parse 方法解析代码,得到一个 statement 节点数组
var_dump($stmts);
} catch (Error $e) {
echo 'Parse Error: ', $e->getMessage();//语法错误可以通过 PhpParser\Error 来捕获
}

output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/home/fe1w0/babyshop/ttt.php:15:
array(1) {
[0] =>
class PhpParser\Node\Stmt\Echo_#1131 (2) {
public $exprs =>
array(1) {
[0] =>
class PhpParser\Node\Scalar\String_#1130 (2) {
...
}
}
protected $attributes =>
array(2) {
'startLine' =>
int(3)
'endLine' =>
int(3)
}
}
}

使用 NodeDumper来查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
use PhpParser\Error;
use PhpParser\ParserFactory;
use PhpParser\NodeDumper;
require dirname(__FILE__).'/vendor/autoload.php'; #composer require nikic/php-parse 成功后会生成这个文件,当然还有其他的文件
$code = <<<'CODE'
<?php

echo 'Hello PHP';
CODE;



$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);// 优先解析 PHP7 代码

try {
$stmts = $parser->parse($code);//使用 ParserFactory 的 parse 方法解析代码,得到一个 statement 节点数组
$nodeDumper = new NodeDumper;
echo $nodeDumper->dump($stmts), "\n";
#var_dump($stmts);
} catch (Error $e) {
echo 'Parse Error: ', $e->getMessage();//语法错误可以通过 PhpParser\Error 来捕获
}

output:

1
2
3
4
5
6
7
8
9
array(
0: Stmt_Echo(
exprs: array(
0: Scalar_String(
value: Hello PHP
)
)
)
)

修改节点值 将Hello PHP改为Hello world

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?php
use PhpParser\Error;
use PhpParser\ParserFactory;
use PhpParser\NodeDumper;
use PhpParser\NodeTraverser;
use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;
use PhpParser\PrettyPrinter;


require dirname(__FILE__).'/vendor/autoload.php';

$code = <<<'CODE'
<?php

echo 'Hello PHP';

CODE;

class MyNodeVisitor extends NodeVisitorAbstract
{
public function leaveNode(Node $node) {
if ($node instanceof Node\Scalar\String_) {
$node->value = 'Hello Word';
}
}
}

class PrintNodeVisitor extends NodeVisitorAbstract
{
public function leaveNode(Node $node) {
if ($node instanceof Node\Stmt\Echo_) {
return new PhpParser\Node\Stmt\Expression( new Node\Expr\Print_(new Node\Scalar\String_(($node->exprs)[0]->value)) );
}
}
}

$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);

try {
$stmts = $parser->parse($code);
$traverser = new NodeTraverser;
// 添加 node visitors
$traverser->addVisitor(new MyNodeVisitor);
$traverser->addVisitor(new PrintNodeVisitor);
// 遍历 AST
$new_stmts = $traverser->traverse($stmts);
// 将 AST 转为 PHP 代码
$prettyPrinter = new PrettyPrinter\Standard;
$new_code = $prettyPrinter->prettyPrintFile($new_stmts);
echo $code.PHP_EOL;
echo "--After parser:--\n\n".$new_code;

} catch (Error $e) {
echo 'Parse Error: ', $e->getMessage();
}

解混淆[缺失ing]

CATALOG
  1. 1. PHP-Parser 用于代码混淆的代码
    1. 1.1. 下载
    2. 1.2. 生成AST
    3. 1.3. 解混淆[缺失ing]