CTF逆向实战:如何快速识别并破解TEA加密算法(附Python解密脚本)
·
CTF逆向实战:如何快速识别并破解TEA加密算法(附Python解密脚本)
在CTF竞赛的逆向工程赛题中,加密算法分析一直是核心考点之一。TEA(Tiny Encryption Algorithm)作为轻量级分组加密算法,因其简洁高效的特性成为出题人偏爱的素材。本文将分享三个实战技巧,帮助选手在IDA静态分析中快速定位TEA算法特征,并给出可应对魔改变种的Python自动化解密方案。
1. TEA算法特征速查手册
1.1 标准结构识别三要素
在IDA反汇编视图中,标准TEA算法通常呈现以下特征组合:
- 32轮循环结构:典型的
for(int i=0; i<32; i++)循环体 - 黄金分割常数:原始DELTA值
0x9E3779B9(或补码形式0x61C88647) - 密钥调度模式:
key[sum & 3]和key[(sum >> 11) & 3]的交替访问
// 典型TEA加密片段特征
l += (((r << 4) ^ (r >> 5)) + r) ^ (sum + key[sum & 3]);
sum += DELTA;
r += (((l << 4) ^ (l >> 5)) + l) ^ (sum + key[(sum >> 11) & 3]);
1.2 魔改变种检测技巧
当遇到非标准TEA时,可通过以下方法定位关键参数:
| 检测维度 | 标准TEA | 魔改TEA | 识别方法 |
|---|---|---|---|
| DELTA值 | 0x9E3779B9 | 任意32位整数 | 跟踪循环体内的累加/递减操作 |
| 轮次 | 32 | 16/64等 | 查找循环计数器初始化值 |
| 密钥索引 | sum & 3 | (sum>>8) & 7等 | 分析密钥数组的访问偏移计算 |
提示:在IDA中按
Alt+T搜索十六进制常数时,可尝试0x9E3779B9的补码形式0x61C88647
2. 逆向工程实战四步法
2.1 动态定位加密函数
使用x64dbg调试时,可通过以下特征快速定位加密函数:
- 函数参数包含两个32位整型指针(明文/密文)
- 局部变量存在明显的128位密钥缓冲区
- 函数内出现连续的位移-异或操作序列
# 动态调试定位示例(PyKD脚本)
import pykd
def find_tea():
for func in pykd.getFunctions():
disasm = pykd.disasm(func)
if sum(1 for line in disasm if 'shl' in line and 'xor' in line) > 5:
print(f"Potential TEA at {hex(func)}")
2.2 密钥提取方法论
密钥通常以以下形式存在:
- 硬编码在.data段:直接Hex-Rays反编译查看初始化值
- 运行时动态生成:在加密函数前设置内存访问断点
- 文件/网络加载:Hook文件读取API(如
fread)或网络接收函数
2.3 对抗混淆方案
当遇到混淆后的TEA实现时,可采用:
- 常量传播分析:追踪DELTA值的流向
- 污点分析:标记密钥内存区域,观察其使用路径
- 符号执行:使用Angr求解密钥约束条件
3. Python自动化解密工具链
3.1 标准TEA解密脚本
def tea_decrypt(v, key, delta=0x9E3779B9, rounds=32):
v0, v1 = map(lambda x: x & 0xFFFFFFFF, v)
sum = (delta * rounds) & 0xFFFFFFFF
for _ in range(rounds):
v1 -= ((v0 << 4) + key[2]) ^ (v0 + sum) ^ ((v0 >> 5) + key[3])
v1 &= 0xFFFFFFFF
v0 -= ((v1 << 4) + key[0]) ^ (v1 + sum) ^ ((v1 >> 5) + key[1])
v0 &= 0xFFFFFFFF
sum = (sum - delta) & 0xFFFFFFFF
return [v0, v1]
3.2 魔改参数自动检测
def detect_tea_params(binary):
from capstone import Cs, CS_ARCH_X86, CS_MODE_32
md = Cs(CS_ARCH_X86, CS_MODE_32)
delta_candidates = set()
for insn in md.disasm(binary, 0x1000):
# 检测DELTA加载指令
if insn.mnemonic == 'mov' and insn.op_str.startswith('0x'):
delta_candidates.add(int(insn.op_str, 16))
# 检测轮次设置
elif insn.mnemonic == 'mov' and insn.op_str.endswith(', 32'):
print(f"Found round count at {hex(insn.address)}")
return sorted(d for d in delta_candidates if 0 < d < 0xFFFFFFFF)
3.3 IDAPython辅助分析脚本
def ida_tea_analyzer():
import idautils, idc
for segea in idautils.Segments():
for funcea in idautils.Functions(segea, idc.get_segm_end(segea)):
flags = idc.get_func_attr(funcea, idc.FUNCATTR_FLAGS)
if flags & idc.FUNC_LIB: continue
# 检测特征指令模式
cnt = 0
for head in idautils.Heads(funcea, idc.find_func_end(funcea)):
if idc.print_insn_mnem(head) == 'add' and '0x9E3779B9' in idc.GetDisasm(head):
print(f"Found TEA at {hex(funcea)}")
break
4. 实战案例:三道CTF赛题解析
4.1 基础题型:2023年XX杯Reverse100
- 题目特征:ELF文件,UPX加壳,加密函数在
.text:080485A0 - 破解过程:
upx -d脱壳后IDA加载- 搜索
0x9E3779B9定位到加密函数 - 发现
.rodata段中的密钥数组[0xDEADBEEF, 0xCAFEBABE, ...] - 使用标准解密脚本直接获得flag
4.2 进阶题型:2022年XXCTF Crypto200
- 魔改点:
- DELTA改为
0xABCD1234 - 轮次减少到16轮
- 密钥索引变为
(sum >> 8) & 3
- DELTA改为
- 解决方案:
custom_tea_decrypt(cipher, key, delta=0xABCD1234, rounds=16,
key_idx=lambda s: (s >> 8) & 3)
4.3 综合题型:2023年DefCon Quals
- 保护措施:
- 动态生成密钥(通过
time(0)播种) - 每加密8字节插入随机填充
- 使用TEA-CBC模式
- 动态生成密钥(通过
- 破解策略:
- Hook
time函数固定返回已知时间戳 - 通过已知明文攻击恢复密钥
- 实现CBC模式解密链
- Hook
在最近的一场线下赛中,遇到将TEA与XXTEA混合使用的变种,通过分析密钥扩展流程发现实际仍保持TEA的核心运算结构。这种情况下,保持对位移-异或模式的敏感度比盲目依赖工具更重要。
更多推荐



所有评论(0)