<?php
/**
 * CTF Web (PHP) - unserialize POP chain style
 * Single file, Baota-friendly.
 *
 * entry: ?p= (serialized payload)
 */

error_reporting(0);

$FLAG 'flag{REPLACE_ME_WITH_YOURS}';

function 
hint() {
    echo 
"Hint: maybe you should look at magic methods.\n";
    echo 
"Hint: payload is a serialized object.\n";
    exit;
}

class 
Modifier {
    protected 
$var;

    public function 
append($value) {
        
// sink-like behavior (LFI style), but we won't rely on RCE for flag
        
@include($value);
    }

    public function 
__invoke() {
        
$this->append($this->var);
    }
}

class 
Show {
    public 
$source;
    public 
$str;

    public function 
__construct($file null) {
        
$this->source $file;
    }

    public function 
__toString() {
        if (isset(
$this->source)) {
            
$src $this->source;
            
// if $src is callable object, this triggers __invoke
            
$src();
            return 
"done.\n";
        }
        return 
"Show class\n";
    }
}

class 
Test {
    public 
$p;

    public function 
__construct() {
        
$this->= array();
    }

    public function 
__get($key) {
        
$function $this->p;
        
// if $this->p becomes a callable, calling it will trigger __invoke
        
return $function();
    }
}

class 
Gate {
    public 
$token 'guest';

    public function 
allow(): bool {
        
/**
         * Solvable gate (classic):
         * "magic hash" loose comparison in PHP:
         * md5('QNKCDZO') and md5('240610708') look like 0e\d+
         * so md5(token) == md5('QNKCDZO') can be true under ==
         */
        
return md5($this->token) == md5('QNKCDZO') && $this->token !== 'QNKCDZO';
    }
}

class 
Fusheng {
    private 
$name;
    private 
$group;
    private 
$gate;

    public function 
__construct() {
        
$this->name  "guest";
        
$this->group "user";
        
$this->gate  = new Gate();
    }

    public function 
__destruct() {
        global 
$FLAG;

        
// 业务味的“身份校验”
        
if (!($this->gate instanceof Gate) || !$this->gate->allow()) {
            @
ob_clean();
            echo 
"<center><p style='color:red'>系统检测:身份验证失败</p></center>\n";
            
hint();
        }

        if (
$this->name !== "admin") {
            @
ob_clean();
            echo 
"<center><p style='color:red'>系统检测:当前用户不是 admin</p></center>\n";
            
hint();
        }

        
// 通过后给 flag(不依赖文件读写/命令执行)
        
echo "Welcome back, Fusheng.\n";
        echo 
$FLAG "\n";

        
// “彩蛋”:让它看起来更像真实题
        // 触发 __toString 链(如果 group 被塞成对象)
        
echo $this->group "\n";
    }
}

// ===== entry =====
if (!isset($_GET['p'])) {
    
// 默认给源码(你正式比赛可以改成只给提示)
    
header('Content-Type: text/html; charset=utf-8');
    
highlight_file(__FILE__);
    exit;
}

$payload = (string)$_GET['p'];

// 小限制,防止塞超长
if (strlen($payload) > 2500) {
    die(
"too long\n");
}

// 核心漏洞点
@unserialize($payload, ['allowed_classes' => true]);

echo 
"received\n";