PHP AST学习
前一阵和前同事交流在检测webshell方面的相关方法,其中提出了使用lex yacc做一套语法解析来解析字节码段来判断是否存在webshell。
后来在查找相关资料中,找到了github开源的一个工具:PHP-Parser。能够把php文件解析AST(抽象语法树)
Project: https://github.com/nikic/PHP-Parser
安装:
php composer.phar require nikic/php-parser
例如:
<?php use PhpParser\Error; use PhpParser\NodeDumper; use PhpParser\ParserFactory; $code = <<<'CODE' <?php function test($foo) { var_dump($foo); } CODE; $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); try { $ast = $parser->parse($code); } catch (Error $error) { echo "Parse error: {$error->getMessage()}\n"; return; } $dumper = new NodeDumper; echo $dumper->dump($ast) . "\n";
转储AST为:
array( 0: Stmt_Function( byRef: false name: Identifier( name: test ) params: array( 0: Param( type: null byRef: false variadic: false var: Expr_Variable( name: foo ) default: null ) ) returnType: null stmts: array( 0: Stmt_Expression( expr: Expr_FuncCall( name: Name( parts: array( 0: var_dump ) ) args: array( 0: Arg( value: Expr_Variable( name: foo ) byRef: false unpack: false ) ) ) ) ) ) )
可以看到各个节点的含义,相比较查看opcode然后再去解析容易的多,opcode比较晦涩难懂。
如果做得好,再进行回归成原始的代码,例如webshell中存在很多字符串拼接、函数拼接等操作。回归最终原始代码,再去检测会变得容易的多。
关于php-parser的文档也有很多:
https://github.com/nikic/PHP-Parser/tree/master/doc
我个人的目前思路:
1、获取web目录
2、对每个php文件生成AST
3、解析AST,进行语法回归,转储原始代码 // 这个地方比较有难度
4、使用多引擎(正则、机器学习、第三方接口)进行判断文件是否异常。
【版权所有@Sevck 博客地址http://www.cnblogs.com/sevck】 可以转载,注明出处.