QnQSec CTF 2025部分wp
字数 3331 2025-11-07 08:41:54

CTF 题目解法详解与教学指南

概述

本文档基于 QnQSec CTF 2025 部分题目的解法,系统性地总结各类 CTF 题型的解题思路、技术要点和实现方法。内容涵盖 Misc、Hardware、Crypto 和 Reverse 等多个方向,旨在为 CTF 参赛者提供全面的技术参考。


1. Misc 类题目

1.1 Echoes of the Unknown

题目类型:音频隐写
技术要点

  • 使用传统隐写工具(如 Stegsolve、Audacity 等)进行分析
  • 重点检查音频的波形图,可能隐藏可视信息
  • 波形图可能直接包含 Flag 文本

解题步骤

  1. 用音频编辑软件打开题目提供的音频文件
  2. 查看波形图显示模式
  3. 直接识别波形图中的 Flag 文本

答案QnQSec{h1dd3n_1n_4ud1o}

1.2 Catch Me

题目类型:GIF 分帧与二维码识别
技术要点

  • GIF 文件包含多帧图像,每帧可能包含部分信息
  • 需要编写脚本进行分帧处理
  • 批量识别二维码内容

解题步骤

  1. 使用 Python 的 PIL/Pillow 库对 GIF 进行分帧
from PIL import Image

def extract_frames(gif_path):
    with Image.open(gif_path) as img:
        frames = []
        for frame in range(img.n_frames):
            img.seek(frame)
            frames.append(img.copy())
        return frames
  1. 对每帧图像进行二维码识别
import pyzbar.pyzbar as pyzbar

def decode_qr_from_frames(frames):
    results = []
    for frame in frames:
        decoded = pyzbar.decode(frame)
        if decoded:
            results.append(decoded[0].data.decode())
    return results
  1. 组合所有二维码内容得到完整 Flag

答案QnQSec{C4TCH_M3_1F_Y0U_C4N}

1.3 John Cena

题目类型:GIF 隐写
技术要点

  • 关注 GIF 的最后一帧(可能隐藏信息)
  • 使用 Stegsolve 等工具分析图像隐写

解题步骤

  1. 对 GIF 进行分帧,检查每一帧
  2. 发现最后一帧为全白图像(可疑)
  3. 使用 Stegsolve 分析该帧,发现隐藏的 Flag

答案QnQSec{HOW_CAN_YOU_SEE_ME?}

1.4 HeartBroken

题目类型:PDF 签名提取
技术要点

  • 使用 PyMuPDF 库处理 PDF 文件
  • 提取 PDF 中嵌入的图像/签名信息

解题步骤

  1. 使用 PyMuPDF 打开 PDF 文件
import fitz  # PyMuPDF

def extract_images_from_pdf(pdf_path):
    doc = fitz.open(pdf_path)
    images = []
    for page_num in range(len(doc)):
        page = doc.load_page(page_num)
        image_list = page.get_images(full=True)
        for image_index, img in enumerate(image_list):
            xref = img[0]
            pix = fitz.Pixmap(doc, xref)
            if pix.n - pix.alpha > 3:  # 检查是否为 RGB 图像
                pix.save(f"image_{page_num}_{image_index}.png")
            pix = None
    doc.close()
  1. 分析提取出的图像,找到 Flag

答案QnQSec{I_4ctually_st1ll_l0v3_y0u_Rima!!}


2. Hardware 类题目

2.1 SmartCoffee

题目类型:固件/EEPROM 分析
技术要点

  • 对嵌入式设备固件进行静态分析
  • 识别和提取 EEPROM 数据区
  • 对混淆数据进行暴力破解

解题步骤

  1. 分析固件反汇编,找到 33 字节的 EEPROM 数据区(byte_20E0[33]

  2. 数据被标记为"likely obfuscated",需要尝试常见变换:

    • 单字节 XOR 操作
    • 加/减常量操作
    • 位循环移位(ROL/ROR)
    • 按位取反(NOT)
    • 两字节重复密钥模式
  3. 编写爆破脚本系统尝试所有可能变换

def brute_force_eeprom(data):
    results = []
    for key in range(256):  # 单字节 XOR 密钥
        decrypted = bytes([b ^ key for b in data])
        if b'QnQSec{' in decrypted:
            results.append(decrypted)
    
    # 尝试其他变换...
    return results
  1. 在 XOR 密钥 0x3B 时找到可读 Flag

答案QnQSec{3x_s3snum_c4n_d0_h4rdw4r3}


3. Crypto 类题目

3.1 myLFSR?

题目类型:GF(3) 上的 LFSR 密码分析
技术要点

  • LFSR(线性反馈移位寄存器)在 GF(3) 上工作
  • 利用已知明文攻击恢复初始状态和掩码
  • 基数为 3 的异或操作

数学原理

  • LFSR 状态向量长度:40
  • 输出:state[0](最低位)
  • 状态更新:右移并在末尾追加 b = sum(state[i]*mask[i]) mod 3
  • 加密:明文转换为基数为 3 的展开,与密钥流逐位异或

解题步骤

  1. 将已知明文 b'\xff'*k 转换为基数为 3 的展开
  2. 通过密文与明文的异或得到密钥流片段
  3. 利用 LFSR 的线性特性建立方程组
  4. 求解初始状态和反馈多项式系数
  5. 生成完整密钥流,解密 Flag

核心代码思路

def solve_lfsr_gf3(gift_ct, known_plaintext, key_length=40):
    # 将明文转换为三进制展开
    pt_gift = expand_to_base3(known_plaintext, key_length)
    
    # 获取密钥流
    stream = [pt_gift[i] ^ gift_ct[i] for i in range(len(pt_gift))]
    
    # 建立线性方程组求解 mask
    # ... 线性代数求解过程
    
    return initial_state, mask

答案QnQSec{i_L1K3_B3RleK4mP_m4Ss3y_0n_m0d_3_f1elD}

3.2 Mandatory RSA

题目类型:RSA Wiener 攻击
技术要点

  • 识别大公钥指数 e 的情况
  • 使用 Wiener 攻击恢复私钥
  • 常规 RSA 解密

解题步骤

  1. 观察 RSA 参数,发现 e 很大,符合 Wiener 攻击条件
  2. 使用连分数展开攻击:
def wiener_attack(e, n):
    # 连分数展开 e/n
    # 检查每个收敛分数是否满足 RSA 条件
    # 返回可能的 d 值
    pass
  1. 找到正确的私钥 d 后正常解密

答案QnQSec{I_l0v3_Wi3n3r5_@nD_i_l0v3_Nut5!!!!}

3.3 myPrime

题目类型:结构化素数与椭圆曲线密码分析
技术要点

  • 识别特殊结构的素数:p = pp² + pp + 3
  • 利用模运算信息恢复素数
  • AES-CTR 模式解密

数学推导

  1. s = pp,则 p = s² + s + 3
  2. 已知 E_.order() ≡ gift (mod mod)
  3. 根据 Hasse 定理:|E(F_p)| ≈ p
  4. 建立模方程:s² + s + 3 ≡ gift (mod mod)

解题步骤

  1. 解模方程得到 s 在模 mod 下的残类
  2. 枚举合适的 t 值,使 s 落在正确范围内(约 256 位)
  3. 对每个候选 s 计算 p 并检查素数性
  4. 使用 p 的前 16 字节作为 AES 密钥解密

核心代码

def recover_prime(gift, mod):
    # 解二次方程 s² + s + (3 - gift) ≡ 0 (mod mod)
    R = (3 - gift) % mod
    discriminant = (1 + 4 * R) % mod
    
    # 求平方根(如果存在)
    sqrt_d = tonelli_shanks(discriminant, mod)
    
    s_candidates = []
    if sqrt_d is not None:
        s1 = ((-1 + sqrt_d) * pow(2, -1, mod)) % mod
        s2 = ((-1 - sqrt_d) * pow(2, -1, mod)) % mod
        s_candidates = [s1, s2]
    
    # 枚举平移倍数
    for s0 in s_candidates:
        for t in range(-10, 10):  # 小范围枚举
            s = s0 + t * mod
            if 2**255 < s < 2**257:  # 检查位数
                p = s*(s+1) + 3
                if is_prime(p) and (p % mod == gift % mod):
                    return p
    return None

答案QnQSec{H1lb3rt_cl4sS_p0lynOmiAl_w1tH_DiScR1m1nANt_5pEc1al_d3s1gn3D}


4. Reverse 类题目

4.1 baby_baby_reverse

题目类型:简单逆向工程
技术要点

  • 使用 IDA Pro 进行静态分析
  • 识别加密算法(异或加密)
  • 提取密钥和加密逻辑

解题步骤

  1. 用 IDA 打开可执行文件,分析主函数
  2. 发现输入长度要求为 41 字节(0x29)
  3. 识别加密逻辑:encrypted[i] = plaintext[i] ^ key[i % 15]
  4. 密钥字符串:"Th1s_1s_th3_k3y"
  5. 反向计算得到 Flag

解密代码

def decrypt_baby_reverse(encrypted_data):
    key = b"Th1s_1s_th3_k3y"
    key_len = len(key)
    result = bytearray()
    
    for i in range(len(encrypted_data)):
        result.append(encrypted_data[i] ^ key[i % key_len])
    
    return bytes(result)

答案QnQSec{This_1s_4n_3asy_r3v3rs3_ch4ll3ng3}

4.2 Baby_Reverse_Revenge_From_NHNC

题目类型:Shellcode 分析与 AES 解密
技术要点

  • 分析嵌入式 shellcode 的动态密钥生成
  • AES-256-CBC 模式解密
  • 逆向工程中的动态分析技巧

解题步骤

  1. 分析程序中的 shellcode 数据段
  2. 识别 shellcode 实际是在构造固定密钥
  3. 提取 shellcode 中设置的字节值:th1_1s_th3_valu3_0f_k3y + 9 个空字节
  4. 使用该密钥进行 AES-256-CBC 解密

解密代码

from Crypto.Cipher import AES

def decrypt_aes_ctr(ciphertext, key, nonce):
    cipher = AES.new(key, AES.MODE_CTR, nonce=nonce)
    return cipher.decrypt(ciphertext)

# 密钥提取
key = b"th1_1s_th3_valu3_0f_k3y" + b"\x00" * 9  # 补足 32 字节

答案QnQSec{a_s1mpl3_fil3_3ncrypt3d_r3v3rs3}


5. 通用解题技巧总结

5.1 文件格式分析

  • 音频文件:检查波形图、频谱图、元数据
  • 图像文件:分帧分析、隐写工具、通道分离
  • PDF 文件:PyMuPDF 提取嵌入对象
  • 固件文件:二进制分析、反汇编、数据区识别

5.2 密码分析模式识别

  • 流密码:寻找线性关系、已知明文攻击
  • 分组密码:识别加密模式、密钥恢复
  • 公钥密码:参数特殊性分析(如 Wiener 攻击条件)
  • 特殊结构:代数结构利用、模运算分析

5.3 逆向工程方法论

  • 静态分析:IDA Pro 反汇编、字符串搜索、交叉引用
  • 动态分析:调试器跟踪、内存转储、API 监控
  • 代码理解:识别加密函数、输入输出分析

5.4 脚本编写技巧

  • 批量处理:文件遍历、多线程/进程
  • 数据转换:进制转换、编码解码
  • 暴力破解:合理缩小搜索空间、优化算法

结语

本教学文档系统总结了 QnQSec CTF 2025 中各类题目的解题思路和技术要点。掌握这些技能需要理论与实践相结合,建议读者在实际 CTF 比赛中多加练习,不断提升分析问题和解决问题的能力。CTF 竞赛的核心在于创造性思维和系统性方法,希望本文档能为您的学习之路提供有价值的参考。

CTF 题目解法详解与教学指南 概述 本文档基于 QnQSec CTF 2025 部分题目的解法,系统性地总结各类 CTF 题型的解题思路、技术要点和实现方法。内容涵盖 Misc、Hardware、Crypto 和 Reverse 等多个方向,旨在为 CTF 参赛者提供全面的技术参考。 1. Misc 类题目 1.1 Echoes of the Unknown 题目类型 :音频隐写 技术要点 : 使用传统隐写工具(如 Stegsolve、Audacity 等)进行分析 重点检查音频的波形图,可能隐藏可视信息 波形图可能直接包含 Flag 文本 解题步骤 : 用音频编辑软件打开题目提供的音频文件 查看波形图显示模式 直接识别波形图中的 Flag 文本 答案 : QnQSec{h1dd3n_1n_4ud1o} 1.2 Catch Me 题目类型 :GIF 分帧与二维码识别 技术要点 : GIF 文件包含多帧图像,每帧可能包含部分信息 需要编写脚本进行分帧处理 批量识别二维码内容 解题步骤 : 使用 Python 的 PIL/Pillow 库对 GIF 进行分帧 对每帧图像进行二维码识别 组合所有二维码内容得到完整 Flag 答案 : QnQSec{C4TCH_M3_1F_Y0U_C4N} 1.3 John Cena 题目类型 :GIF 隐写 技术要点 : 关注 GIF 的最后一帧(可能隐藏信息) 使用 Stegsolve 等工具分析图像隐写 解题步骤 : 对 GIF 进行分帧,检查每一帧 发现最后一帧为全白图像(可疑) 使用 Stegsolve 分析该帧,发现隐藏的 Flag 答案 : QnQSec{HOW_CAN_YOU_SEE_ME?} 1.4 HeartBroken 题目类型 :PDF 签名提取 技术要点 : 使用 PyMuPDF 库处理 PDF 文件 提取 PDF 中嵌入的图像/签名信息 解题步骤 : 使用 PyMuPDF 打开 PDF 文件 分析提取出的图像,找到 Flag 答案 : QnQSec{I_4ctually_st1ll_l0v3_y0u_Rima!!} 2. Hardware 类题目 2.1 SmartCoffee 题目类型 :固件/EEPROM 分析 技术要点 : 对嵌入式设备固件进行静态分析 识别和提取 EEPROM 数据区 对混淆数据进行暴力破解 解题步骤 : 分析固件反汇编,找到 33 字节的 EEPROM 数据区( byte_20E0[33] ) 数据被标记为"likely obfuscated",需要尝试常见变换: 单字节 XOR 操作 加/减常量操作 位循环移位(ROL/ROR) 按位取反(NOT) 两字节重复密钥模式 编写爆破脚本系统尝试所有可能变换 在 XOR 密钥 0x3B 时找到可读 Flag 答案 : QnQSec{3x_s3snum_c4n_d0_h4rdw4r3} 3. Crypto 类题目 3.1 myLFSR? 题目类型 :GF(3) 上的 LFSR 密码分析 技术要点 : LFSR(线性反馈移位寄存器)在 GF(3) 上工作 利用已知明文攻击恢复初始状态和掩码 基数为 3 的异或操作 数学原理 : LFSR 状态向量长度:40 输出:state[ 0 ](最低位) 状态更新:右移并在末尾追加 b = sum(state[i]*mask[i]) mod 3 加密:明文转换为基数为 3 的展开,与密钥流逐位异或 解题步骤 : 将已知明文 b'\xff'*k 转换为基数为 3 的展开 通过密文与明文的异或得到密钥流片段 利用 LFSR 的线性特性建立方程组 求解初始状态和反馈多项式系数 生成完整密钥流,解密 Flag 核心代码思路 : 答案 : QnQSec{i_L1K3_B3RleK4mP_m4Ss3y_0n_m0d_3_f1elD} 3.2 Mandatory RSA 题目类型 :RSA Wiener 攻击 技术要点 : 识别大公钥指数 e 的情况 使用 Wiener 攻击恢复私钥 常规 RSA 解密 解题步骤 : 观察 RSA 参数,发现 e 很大,符合 Wiener 攻击条件 使用连分数展开攻击: 找到正确的私钥 d 后正常解密 答案 : QnQSec{I_l0v3_Wi3n3r5_@nD_i_l0v3_Nut5!!!!} 3.3 myPrime 题目类型 :结构化素数与椭圆曲线密码分析 技术要点 : 识别特殊结构的素数: p = pp² + pp + 3 利用模运算信息恢复素数 AES-CTR 模式解密 数学推导 : 设 s = pp ,则 p = s² + s + 3 已知 E_.order() ≡ gift (mod mod) 根据 Hasse 定理: |E(F_p)| ≈ p 建立模方程: s² + s + 3 ≡ gift (mod mod) 解题步骤 : 解模方程得到 s 在模 mod 下的残类 枚举合适的 t 值,使 s 落在正确范围内(约 256 位) 对每个候选 s 计算 p 并检查素数性 使用 p 的前 16 字节作为 AES 密钥解密 核心代码 : 答案 : QnQSec{H1lb3rt_cl4sS_p0lynOmiAl_w1tH_DiScR1m1nANt_5pEc1al_d3s1gn3D} 4. Reverse 类题目 4.1 baby_ baby_ reverse 题目类型 :简单逆向工程 技术要点 : 使用 IDA Pro 进行静态分析 识别加密算法(异或加密) 提取密钥和加密逻辑 解题步骤 : 用 IDA 打开可执行文件,分析主函数 发现输入长度要求为 41 字节(0x29) 识别加密逻辑: encrypted[i] = plaintext[i] ^ key[i % 15] 密钥字符串: "Th1s_1s_th3_k3y" 反向计算得到 Flag 解密代码 : 答案 : QnQSec{This_1s_4n_3asy_r3v3rs3_ch4ll3ng3} 4.2 Baby_ Reverse_ Revenge_ From_ NHNC 题目类型 :Shellcode 分析与 AES 解密 技术要点 : 分析嵌入式 shellcode 的动态密钥生成 AES-256-CBC 模式解密 逆向工程中的动态分析技巧 解题步骤 : 分析程序中的 shellcode 数据段 识别 shellcode 实际是在构造固定密钥 提取 shellcode 中设置的字节值: th1_1s_th3_valu3_0f_k3y + 9 个空字节 使用该密钥进行 AES-256-CBC 解密 解密代码 : 答案 : QnQSec{a_s1mpl3_fil3_3ncrypt3d_r3v3rs3} 5. 通用解题技巧总结 5.1 文件格式分析 音频文件 :检查波形图、频谱图、元数据 图像文件 :分帧分析、隐写工具、通道分离 PDF 文件 :PyMuPDF 提取嵌入对象 固件文件 :二进制分析、反汇编、数据区识别 5.2 密码分析模式识别 流密码 :寻找线性关系、已知明文攻击 分组密码 :识别加密模式、密钥恢复 公钥密码 :参数特殊性分析(如 Wiener 攻击条件) 特殊结构 :代数结构利用、模运算分析 5.3 逆向工程方法论 静态分析 :IDA Pro 反汇编、字符串搜索、交叉引用 动态分析 :调试器跟踪、内存转储、API 监控 代码理解 :识别加密函数、输入输出分析 5.4 脚本编写技巧 批量处理:文件遍历、多线程/进程 数据转换:进制转换、编码解码 暴力破解:合理缩小搜索空间、优化算法 结语 本教学文档系统总结了 QnQSec CTF 2025 中各类题目的解题思路和技术要点。掌握这些技能需要理论与实践相结合,建议读者在实际 CTF 比赛中多加练习,不断提升分析问题和解决问题的能力。CTF 竞赛的核心在于创造性思维和系统性方法,希望本文档能为您的学习之路提供有价值的参考。