楚慧杯PWN、RE、Crypto与Misc部分题解
字数 3902
更新时间 2026-03-18 13:50:38
CTF逆向工程与漏洞利用(PWN)基础与实例教学文档
——基于“楚慧杯”赛题解析的实战分析
一、 文档来源
本教学文档内容基于“楚慧杯PWN、RE、Crypto与Misc部分题解”技术文章(发布于先知社区,2026年3月12日)进行归纳、提炼与系统化整理,旨在提供一套结构化的攻防技术学习路径。
二、 前言与背景
本文档面向具备一定计算机安全基础的学习者。所涉及的CTF(Capture The Flag)竞赛题目涵盖了二进制漏洞利用(PWN)、逆向工程(RE)、密码学(Crypto)与杂项(Misc)四大常见方向。通过剖析具体赛题的解题思路,我们将深入理解相关漏洞原理、逆向分析方法和自动化利用脚本的编写。
三、 二进制漏洞利用(PWN)篇
3.1 题目:house_1
- 目标程序概况:保护全开(Canary, NX, PIE等),使用libc 2.31。
- 漏洞类型:格式化字符串漏洞(Format String Vulnerability)。
- 核心利用思路:
- 信息泄露:利用格式化字符串漏洞泄露出栈上的libc地址与程序基址。解题脚本通过
%21$p和%26$p两个格式化参数分别获取了关键地址。 - 计算关键地址:根据泄露的地址,计算出
libc_base(libc基址)、程序base(程序基址)以及目标hook函数__malloc_hook的地址。 - 定位one_gadget:在libc中寻找一个能直接启动shell的代码片段(one_gadget),其地址为
libc_base + 0xe3b01。 - 覆盖hook函数:利用格式化字符串写(
fmtstr_payload)能力,分步(因每次写入2字节)将__malloc_hook函数的地址覆盖为one_gadget的地址。 - 触发执行:通过调用触发
malloc的函数(题目中发送选项b'1')来执行__malloc_hook,进而执行one_gadget获取shell。
- 信息泄露:利用格式化字符串漏洞泄露出栈上的libc地址与程序基址。解题脚本通过
- 替代方案(ROP):文档提及还可通过
read函数中的全局变量漏洞构造ROP链进行利用,该方法更为简单。 - 关键脚本函数:
fmtstr_payload(offset, writes, write_size='short'):生成格式化字符串攻击载荷。fmt_write(addr, value):自定义函数,用于向指定地址写入指定值。
四、 逆向工程(RE)篇
4.1 题目:眼见为虚_1
- 初步分析:遇到此类题目,逆向手应优先考虑TLS回调或代码自修改(SMC)技术。本题检查TLS回调未发现逻辑。
- 核心逻辑:
- 主函数分析:主函数逻辑简单,关键在
key_create部分。 - C++虚表调用:程序通过构造C++类的虚表(vtable),动态调用加密函数。这是一个典型的利用C++多态性进行代码混淆的例子。
- 双阶段加密:
- 阶段一(sub_402A18):一个魔改的TEA加密算法。与标准TEA的区别在于,本轮的
delta(或s)是累加的(s = s + 0xDEADBEEF),而非使用固定的0x9E3779B9常数轮换。加密对象是输入的state(v0,v1)。 - 阶段二(sub_402AFC):将第一阶段产生的
state(作为Mask)与输入数据进行异或处理。
- 阶段一(sub_402A18):一个魔改的TEA加密算法。与标准TEA的区别在于,本轮的
- 主函数分析:主函数逻辑简单,关键在
- 逆向解密步骤:
- 逆向实现魔改TEA算法,使用相同的key和初始
v0、v1,运行32轮,得到Mask。 - 用
Mask与密文(题目中硬编码的10个dword常量)进行异或,得到原始flag。
- 逆向实现魔改TEA算法,使用相同的key和初始
- 关键Python还原代码:文档提供了完整的逆向解密脚本,核心是模拟加密过程的反向运算。
4.2 题目:eazy_code-new
- 文件类型:PowerShell脚本,经过深度混淆。
- 混淆分析:
- 变量名混淆:使用特殊字符和数字作为变量名(如
${-``},${$%},${``*%})。 - 数字映射:混淆脚本将数字0-9映射到这些特殊变量名。
- 字符拼接:
${$%}被拼接成[char],用于将数字转换为ASCII字符,从而还原出真实的代码逻辑。
- 变量名混淆:使用特殊字符和数字作为变量名(如
- 核心逻辑还原:去除混淆后,可发现脚本包含一个
e()函数,该函数是TEA系列加密算法(可能是XXTEA)。密文是硬编码的数组ans。 - 解密方法:编写逆向的TEA解密函数(
decrypt)。算法使用固定的DELTA和KEY,对密文ans进行解密,将得到的4个uint32按小端序拼接成字节串,即可得到flag明文:yOUar3g0oD@tPw5H。
五、 密码学(Crypto)篇
5.1 题目:Flip
- 问题模型:一个类DSA的签名方案,但在模
p下运算。已知多组签名对(r_i, s_i),以及flag的每个字节y_m取值范围很小(0-7),目标是恢复flag。 - 攻击方法:格基规约攻击(Lattice Reduction Attack)。
- 攻击步骤:
- 消元:利用第一组签名
(r0, s0)的方程,将未知的私钥d表示为另一个未知数k0的函数,从而在后续方程中消去d。 - 建立线性关系:将关于
k_i和k_0的模方程转化为整数域上的方程,并引入小误差变量z_m(= y_m - 3,将取值范围[0,7]平移到[-3, 4])。 - 构造格(Lattice):构建一个包含所有小变量
z_i,m和模数进位项的矩阵。这个格中的一个短向量就对应了满足所有方程的正确解。 - 规约求解:对构造的格应用LLL算法进行规约,在规约后的基向量中即可找到
flag的各个字节y_m,从而拼接出完整flag。
- 消元:利用第一组签名
- 关键点:将密码学问题转化为寻找格中短向量的问题,利用
y_m值域很小的特点构造可行解。
5.2 题目:GCD,杠上了
- 问题模型:已知多个数
x_i = p * q_i + e_i,其中p是大素数,q_i是大整数,e_i是相对很小的误差。目标是恢复p。 - 攻击方法:正交格攻击(Orthogonal Lattice Attack)。
- 攻击原理:
- 寻找一组整数系数
c_i,使得线性组合∑c_i * x_i = 0。由于x_i的表达式,可得p * ∑c_i * q_i + ∑c_i * e_i = 0。 - 由于
p很大而e_i很小,要使得上式成立,很可能同时满足∑c_i * q_i = 0且∑c_i * e_i = 0。这意味着系数向量c与向量q正交。 - 构造格:构造一个以
x_i和放大因子N组成的矩阵,进行LLL规约。规约后得到的前k-1个短向量就近似是所需的c向量。 - 恢复q:这些
c向量张成的空间与q向量正交。通过计算这些c向量矩阵的右零空间(Right Kernel),其基向量就是q_i向量的倍数。 - 恢复p:得到
q_0后,计算p = round(x_0 / q_0),即可利用四舍五入消除小误差e_0,得到精确的p。
- 寻找一组整数系数
六、 杂项(Misc)篇
6.1 题目:go-gane
- 文件分析:给定的
exe是一个自解压程序,内含另一个可执行文件和一个CAB压缩包。 - 提取过程:
- 使用十六进制编辑器(如010 Editor)查找CAB文件头标志
MSCF,将其之后的数据提取为payload.cab。 - 解压CAB文件,得到游戏资源文件。
- 使用十六进制编辑器(如010 Editor)查找CAB文件头标志
- 游戏类型识别:通过文件目录结构(如
Graphics,Audio等)和文件后缀(.rvdata2),识别出该游戏由RPG Maker VX Ace引擎制作。 .rvdata2文件:本质是Ruby的Marshal序列化格式存储的游戏数据。MapXXX.rvdata2:存储地图事件,可能隐藏提示和逻辑。Scripts.rvdata2:存储游戏脚本,可能包含自定义逻辑。Weapons.rvdata2/Items.rvdata2等:存储游戏数据库,常直接包含字符串信息。
- 获取Flag:
- 后半部分:通过实际运行游戏并退出,可直接在游戏界面获得flag的后半段(一个类似UUID的字符串)。
- 前半部分:
- 方法一(Fuzzing):使用字符串搜索工具(如
strings)或十六进制编辑器直接搜索Data/Weapons.rvdata2等数据文件,发现了flag的前半部分。 - 方法二(Ruby脚本解析):使用Ruby的
Marshal.load函数直接反序列化.rvdata2文件,查看其数据结构,从而定位到flag。
- 方法一(Fuzzing):使用字符串搜索工具(如
- 最终Flag:将前后两部分拼接,得到完整的Flag:
DASCTF{1168cb17-31ff-43b7--b586-8414d383afce}。
文档未详述此点,但基于我所掌握的知识:本文档中涉及的漏洞利用(如格式化字符串)、逆向分析(TEA算法、PowerShell去混淆)、密码学攻击(格基规约、正交格攻击)以及文件格式分析(RPG Maker)均为CTF竞赛和实战安全研究中的经典技能点。深入理解并实践这些案例,对构建二进制安全和密码学分析能力至关重要。建议学习者结合提供的脚本代码,在隔离的实验环境中复现整个流程。
相似文章
相似文章