web21

爆破什么的,都是基操

抓包进行爆破

可以发现这个base64编码就是我们输入的账号密码

payload的配置和处理设置之后

开始爆破(注:字典是由题目下载的)

滚动到页面最下方,找到 Payload Encoding(Payload 编码)取消勾选 “Url-encode these characters...”(URL编码这些字符)。

  • 原因:如果不取消,Base64 结尾的 = 会被自动编码为 %3d,导致服务器无法识别。

得到flag

web22

域名也可以爆破的,试试爆破这个ctf.show的子域名

失效了

web23

还爆破?这么多代码,告辞!

import hashlib

for i in range(10000000):
    token = str(i)
    m = hashlib.md5(token.encode()).hexdigest()
    if m[1] == m[14] and m[14] == m[17]:
        if m[1] in '123456789' and m[31] == '3':
            print(token)
            break

你需要提交一个 token,它的 MD5 加密值必须同时满足以下条件:

  1. 第 2、15、18 个字符完全一样。

  2. 这个相同的字符必须是 1-9 之间的数字。

  3. 最后一个字符(第 32 个字符)必须是 '3'

得到flag

web24

爆个🔨

mt_rand() 产生的其实是伪随机数

伪随机的运作原理

你可以把伪随机数生成器想象成一台极其复杂的绞肉机(数学公式)

  1. 种子(Seed): 你必须先往机器里扔一块初始的肉(数字),这块肉就叫做“种子”。

  2. 生成: 机器经过一顿复杂的搅动(算法计算),吐出一小块肉(第一个随机数)。

  3. 循环: 机器内部会保留一部分刚才计算的状态,当你请求第二个随机数时,它会基于刚才的状态继续搅动,吐出第二块肉。

致命的逻辑在于: 因为数学公式是固定的,所以只要你往机器里扔的“种子”完全一样,机器每次搅动吐出来的结果序列就必定一模一样。

<?php
mt_srand(372619038);
echo mt_rand();
?>

得到flag

web25

爆个🔨,不爆了

相比上一题,这道题的难度提升在于:种子变成了未知数(由未知的 $flag 计算而来)。

既然我们不知道种子,怎么预测随机数呢?这题的核心考点是:利用信息泄露(Information Leak)配合工具逆向破解出种子。

分析主要代码逻辑:

步骤 A:确定密码本(初始化种子)

PHP

$r = $_GET['r'];
mt_srand(hexdec(substr(md5($flag), 0,8)));
  • 第一行:把你输入的参数赋值给变量 $r

  • 第二行:这是全题最绕的地方。它在调用 mt_srand() 函数设置随机数种子。

    • md5($flag):把神秘的 flag 变成一串 32 位的十六进制字符串。

    • substr(..., 0, 8):切片,只切下前 8 个字符。

    • hexdec(...):把这 8 个十六进制字符转换成普通的十进制数字。

    • 结果:用这个由 flag 算出来的固定数字作为种子。因为种子固定,接下来生成的随机数序列也就固定了。

步骤 B:第一道大门(输入比对)

PHP

$rand = intval($r) - intval(mt_rand());
if((!$rand)){
    // ... 进门后的代码
}else{
    echo $rand;
}
  • 代码调用了第一次 mt_rand(),生成了序列里的第一个随机数

  • 然后用你输入的数字减去这个随机数:$rand = r - \text{第一个随机数}$。

  • if((!$rand)):在 PHP 中,! 代表取反。只有当 $rand 的结果为 0 时(也就是你输入的 $r$ 刚好等于第一个随机数),!0 才会变成 True,你才能成功通过第一道大门。

  • else { echo $rand; }:如果你猜错了,代码会执行 else,把你输入的数字和正确答案的差值打印在屏幕上。(这就是上一题中我们传入 ?r=0 就能套出正确答案的漏洞所在)

步骤 C:第二道大门(Cookie 终极校验)

PHP

if($_COOKIE['token'] == (mt_rand() + mt_rand())){
    echo $flag;
}
  • 当你成功通过第一道大门后,代码会连续再调用两次随机数函数,也就是生成了序列里的第二个随机数第三个随机数,并把它们加在一起。

  • 它会去检查你浏览器的 Cookie 里,有没有一个叫做 token 的东西。

  • 通关条件:你提交的 Cookie 中的 token 值,必须等于那第二个和第三个随机数的和。如果相等,执行 echo $flag;,游戏结束,打印出你想要的 Flag。

解题:

第一步:代码逻辑分析与寻找突破口

  1. 种子初始化mt_srand(hexdec(substr(md5($flag), 0, 8))); 系统用 flag 生成了一个固定的种子。因为 flag 是固定的,所以这个未知种子也是固定的

  2. 第一层判断(计算差值)

    PHP

    $rand = intval($r) - intval(mt_rand());
    if((!$rand)){ ... } else { echo $rand; }
    

    代码将你传入的 r 减去生成的第一个随机数。如果差值不是 0(即你没猜对),它会执行 else 分支,直接把你算错的差值 echo 打印出来! 💡 突破口就在这里: 如果你故意传入 ?r=0,那么 $rand = 0 - mt_rand()。网页上就会打印出一个负数(比如 -12345678)。去掉负号,你就能知道服务器生成的第一个随机数是多少了!

  3. 第二层判断(Cookie 校验)

    PHP

    if($_COOKIE['token']==(mt_rand()+mt_rand())) { echo $flag; }
    

    如果你在第一层传入了正确的 r,代码会接着生成第二个第三个随机数,并将它们相加。你必须在请求的 Cookie 中带上一个名为 token 的字段,其值等于这个和,才能拿到 flag。

所以第一个随机数是1783215097

第二步使用工具破解种子(php_mt_seed)

Ubuntu 20.04 LTS (本题环境)PHP 7.4 🌟

发现可能是478823514也有可能是2894621996

<?php
mt_srand(478823514);
$r = mt_rand();
$a = mt_rand();
$b = mt_rand();
echo $r;
echo "\n";
$cook = $a + $b;
echo $cook;
?>

说明第一个不对

我们尝试第二个

<?php
mt_srand(2894621996);
$r = mt_rand();
$a = mt_rand();
$b = mt_rand();
echo $r;
echo "\n";
$cook = $a + $b;
echo $cook;
?>

得到flag

web26

这个可以爆

把几个数据全删除得到flag

前端通过输入框限制你必须填,但你通过 Burp Suite 抓包直接把参数值清空,绕过了前端的限制。而后端又没有对“参数为空”做出严格的拦截和报错,反而当成“什么都没发生”或者“默认通关”处理,从而导致了 flag 的泄露。

web27

CTFshow菜鸡学院招生啦!

点击录取名单,可以看到学生的名单

开始爆破日期,找到正确的日期了

得到flag

主要:

在 Burp Suite(底层是 Java)的日期格式化规则中,大小写有着完全不同的含义:

  • MM(大写):代表 月份 (Month)

  • mm(小写):代表 分钟 (Minute)

web28

大海捞针

得到flag

爆破结束了

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐