news 2026/9/15 7:28:09

nssctf_TTTTTTTTTea

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
nssctf_TTTTTTTTTea


下载、查壳、64位、IDA打开

tea算法的特征非常明显
TEA(Tiny Encryption Algorithm,微型加密算法)是由剑桥大学的 David Wheeler 和 Roger Needham 于 1994 年提出的一种轻量级分组对称加密算法。它的设计目标是代码极简、易于实现、占用资源极少,非常适合嵌入式设备、逆向 CTF 题目等场景。


核心参数

表格

标准 TEA 默认值本题对应实现
分组长度64 bit(8 字节,拆为 2 个 32 位整数v0, v1一致,每组 2 个 int(8 字节)
密钥长度128 bit(16 字节,拆为 4 个 32 位整数k[0]~k[3]一致,16 字节密钥
经典轮数32 轮一致,循环0x1F即 32 轮
魔数 delta0x9E3779B9(源于黄金分割比例,保证混淆性)等价补码写法:0x61C88647

标准 TEA 加密原理

TEA 基于迭代混淆 - 扩散的思想,对两个 32 位明文块v0、v1进行多轮运算,每轮通过位移、异或、加法和密钥混合,逐步打乱明文特征。

加密流程(32 轮)
  1. 初始化累加值sum = 0,delta 为固定魔数
  2. 每轮执行:
sum = sum + delta; v0 = v0 + ( ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]) ); v1 = v1 + ( ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]) );
  1. 32 轮结束后,v0、v1就是最终的密文分组

核心设计:

  • (v << 4) ^ (v >> 5)位移混淆,通过左移 4 位和右移 5 位的异或,打散比特位分布
  • 加法和异或交替使用,实现非线性混淆,增加破解难度
  • sum累加值每轮递增,保证每轮的密钥混合因子都不同,避免相同轮函数重复

本题中的 TEA 代码对应

你 IDA 反汇编里的tea_encrypt函数,本质就是标准 TEA 的轻微改写,对应关系如下:

  1. 变量映射
    • v6= 左 32 位明文 / 密文v0
    • v5= 右 32 位明文 / 密文v1
    • v4= 轮累加值sum
    • a2= 128 位密钥数组首地址k
  2. delta 的写法差异
    代码里写的是v4 -= 1640531527(即sum -= 0x61C88647
    它和标准 TEA 的sum += 0x9E3779B9运算结果完全等价,因为 32 位无符号整数运算下:
-0x61C88647 mod 2^32 = 0x9E3779B9

只是编译器把正数加法优化成了负数减法的补码形式。
3.密钥索引的差异
标准 TEA 固定用k[0]/k[1]计算 v0、k[2]/k[3]计算 v1;
本题用sum & 3(sum >> 11) & 3动态取密钥下标,属于 CTF 中很常见的 TEA 变种写法,本质还是 4 个密钥字循环参与运算。


TEA 解密逻辑

解密是加密的严格逆过程

  1. 初始sum设为加密结束时的最终值(32 轮后 sum = 32 × delta)
  2. 每轮倒序执行加密操作:先还原 v1,再回退 sum,最后还原 v0
  3. 循环 32 轮后得到原始明文

这也是为什么之前的解密脚本里,sum 初始值是负数、运算顺序和加密反过来的原因。

代码解析:
这是一个flag 验证程序的主函数,核心逻辑是:读取用户输入 → 按 TEA 算法加密 → 和内置密文对比,判断输入是否正确。我们按执行顺序拆解:


1. 变量声明
int v4[16]; // 整数数组,共16个int,用于存放「内置密文」和「加密后的输入」 char v5[44]; // 字符缓冲区,存放用户输入的flag字符串 int k, j, i; // 循环计数器 int *v9; // int型指针,用于把字符串按4字节整数读取
  • v4是核心数组:前半部分存正确答案(密文),后半部分存用户输入加密后的结果,最后逐位对比。
  • v5是输入缓冲区,最大 44 字节,但实际只会用到前 24 字节(6 个 int)。

2. 输入读取
puts("please input your flag"); scanf("%s", v5); v9 = (int *)v5;
  • 提示用户输入 flag,读取字符串存入v5
  • v9 = (int *)v5:把字符数组的地址强制转为 int 指针
    作用是:把输入的字符串,按4 字节一个 32 位整数的方式来读取(x86 平台默认小端序)。

3. 输入拆分:字符串 → 整数数组
for ( i = 0; i <= 5; ++i ) v4[i + 8] = *v9++;
  • 循环 6 次,把输入的 flag 按 4 字节切分成6 个 int 整数,依次存入v4[8] ~ v4[13]
  • 6 个 int = 24 字节,说明 flag 的有效长度最多 24 字节。

4. 核心:分组 TEA 加密
for ( j = 0; j <= 2; ++j ) tea_encrypt(&v4[2 * j + 8], &key);
  • 循环 3 次,每次取**2 个 int(8 字节)**作为一组,调用tea_encrypt进行加密。
    • j=0:加密v4[8], v4[9](第 1 组)
    • j=1:加密v4[10], v4[11](第 2 组)
    • j=2:加密v4[12], v4[13](第 3 组)
  • tea_encrypt原地加密:直接修改传入地址里的数值,加密完成后v4[8]~v4[13]就从明文变成了密文。
  • 这符合 TEA 算法的特征:64 位(8 字节)分组加密,每次处理 2 个 32 位整数。

5. 内置正确密文
v4[0] = -1054939302; v4[1] = -1532163725; v4[2] = -165900264; v4[3] = 853769165; v4[4] = 768352038; v4[5] = 876839116;
  • v4[0] ~ v4[5]是程序写死的正确密文(标准答案)。
  • 这里是有符号 int 显示,实际参与运算时是 32 位无符号整数。

6. 校验对比
for ( k = 0; k <= 5; ++k ) { if ( v4[k] != v4[k + 8] ) { printf("ERROR!"); exit(9); } } printf("you are right!");
  • 循环 6 次,逐位对比:
    • 左边v4[k]:内置的正确密文
    • 右边v4[k+8]:用户输入加密后的结果
  • 只要有一位不相等,就打印ERROR!并退出;
  • 全部相等则打印you are right!,说明输入的 flag 正确。

整体逻辑总结

用户输入flag字符串 ↓ 按4字节拆成6个int整数(存入v4[8]~v4[13]) ↓ 分成3组,每组2个int,分别调用TEA加密 ↓ 加密结果 和 程序内置的6个正确密文 逐位对比 ↓ 全部相等 → 正确;否则 → 错误

然后解析加密算法:

这是一个32 轮迭代的 64 位分组对称加密算法(变种 TEA),输入是 8 字节明文(拆为 2 个 32 位整数)和 16 字节密钥(拆为 4 个 32 位整数),经过 32 轮混淆运算后输出 8 字节密文,属于原地加密(直接修改输入的内存数据)。


二、变量映射与初始化

1. 输入参数
  • unsigned int *a1:明文指针,指向连续 2 个unsigned int(共 8 字节),分别是明文的左 32 位、右 32 位
  • __int64 a2:密钥指针,指向连续 4 个unsigned int(共 16 字节),即 128 位密钥
2. 内部变量对应

表格

变量对应 TEA 核心概念作用
v6左半部分v0存储加密过程中的左 32 位数据
v5右半部分v1存储加密过程中的右 32 位数据
v4轮累加值sum每轮递变的常量,保证每轮运算因子不同
i轮计数器控制 32 轮循环
3. 初始化步骤
v6 = *a1; // 读取明文左32位 v5 = a1[1]; // 读取明文右32位 v4 = 0; // 轮累加值 sum 初始化为 0

循环for ( i = 0i64; i <= 0x1F; ++i )0x1F= 31,循环执行32 轮(0~31 共 32 次),和标准 TEA 的轮数一致。


三、单轮加密核心运算(逐行拆解)

每一轮循环严格分为三步:更新左半 v6 → 更新 sum 值 v4 → 更新右半 v5

第 1 步:更新左半部分 v6
v6 += (((v5 >> 5) ^ (16 * v5)) + v5) ^ (*(_DWORD *)(4i64 * (v4 & 3) + a2) + v4);

从内到外逐层拆解运算逻辑:

  1. 比特位移混淆(v5 >> 5) ^ (16 * v5)
    • v5 >> 5:v5 逻辑右移 5 位,高位补 0
    • 16 * v5:等价于v5 << 4,v5 左移 4 位,低位补 0
    • 两者异或:把 v5 的高低比特位交叉打散,是 TEA 算法的核心混淆单元,目的是破坏明文的统计规律
  2. 非线性叠加((位移异或结果) + v5)
    • 把混淆后的结果再加上 v5 本身,通过加法引入非线性,进一步扩散比特位
  3. 密钥 + 轮值混合(*(_DWORD *)(4i64 * (v4 & 3) + a2) + v4)
    • v4 & 3:取 sum 的低 2 位,得到 0/1/2/3 的下标,动态选择 4 个密钥字中的一个
    • 4i64 * 下标:每个密钥字占 4 字节,计算对应的字节偏移量
    • 加上密钥基地址a2,取出对应的 32 位密钥字
    • 再加上当前轮的 sum 值v4:让密钥和轮值绑定,相同密钥字在不同轮的作用不同
  4. 最终合并(非线性叠加结果) ^ (密钥轮值混合结果),结果累加到 v6 上
    • 用异或把数据和密钥混合,再通过加法更新左半部分,完成一轮左半部分的扩散
第 2 步:更新轮累加值 sum(v4)
v4 -= 1640531527;
  • 常量1640531527的十六进制为0x61C88647
  • 在 32 位无符号整数运算中,减去0x61C88647等价于加上0x9E3779B9(标准 TEA 的经典 delta 常量,源于黄金分割数)
  • 作用:每轮让 sum 变化一个固定值,保证每一轮的密钥混合因子都不相同,避免轮函数重复
第 3 步:更新右半部分 v5
v5 += (((v6 >> 5) ^ (16 * v6)) + v6) ^ (*(_DWORD *)(4i64 * ((v4 >> 11) & 3) + a2) + v4);

和 v6 的更新结构对称,但有两个关键区别:

  1. 输入是更新后的 v6:用刚更新完的左半部分 v6 来计算右半部分,形成迭代依赖,这是分组密码实现扩散的核心
  2. 密钥索引方式不同(v4 >> 11) & 3
    • 把 sum 右移 11 位后再取低 2 位,和 v6 更新时的v4 & 3索引不同
    • 目的是让左右两半使用不同的密钥字调度,增加算法的非线性和破解难度

四、结果写回

32 轮循环结束后:

*a1 = v6; // 加密后的左32位写回原地址 a1[1] = v5; // 加密后的右32位写回原地址 return v5; // 返回右半部分(主函数未使用该返回值)

这是原地加密:输入的明文内存直接被覆盖为密文,不需要额外的输出缓冲区。


五、算法核心特性总结

  1. 64 位分组:一次处理 8 字节数据,符合 TEA 家族的基本设计
  2. 32 轮迭代:通过多轮重复的简单运算,累积实现足够的混淆和扩散
  3. 位移混淆单元左移4 ^ 右移5是 TEA 的标志性设计,用极简单的运算实现比特打散
  4. 动态密钥调度:通过 sum 的不同位选择密钥字,相比标准 TEA 的固定密钥搭配,变种性更强
  5. 轮值 sum:每轮变化的累加值,让相同密钥在不同轮产生不同的加密效果

这个算法本质是标准 TEA 的轻量变种,保留了 TEA 代码极简、易于实现的特点,修改了密钥调度和运算顺序,是 CTF 逆向题的高频出题模板。

提取key:

最后写解密脚本:

importstructdeftea_decrypt(v0,v1,key):""" 变种TEA解密函数,严格逆向反汇编中的加密逻辑 v0: 密文左32位(对应加密中的v6) v1: 密文右32位(对应加密中的v5) key: 128位密钥,4个32位无符号整数 """delta=0x61C88647# 加密中的递减常量 1640531527# 加密32轮结束后,sum的最终值:初始0,每轮减delta,共减32次sum_val=(0-32*delta)&0xFFFFFFFFfor_inrange(32):# --------------------------# 第1步:逆加密的最后一步(v5更新)# 加密:v5 += ( ((v6>>5) ^ (v6<<4)) + v6 ) ^ ( key[(sum>>11)&3] + sum )# 解密:v5 减去该增量# --------------------------# 位移混淆部分(左移4位必须截断32位,模拟C语言溢出)mix=((v0>>5)^((v0<<4)&0xFFFFFFFF))&0xFFFFFFFF# 密钥 + 轮累加值k_sum=(key[(sum_val>>11)&3]+sum_val)&0xFFFFFFFF# 总增量inc=(mix+v0)&0xFFFFFFFF^k_sum# 逆加法v1=(v1-inc)&0xFFFFFFFF# --------------------------# 第2步:逆sum的更新# 加密:sum -= delta → 解密:sum += delta# --------------------------sum_val=(sum_val+delta)&0xFFFFFFFF# --------------------------# 第3步:逆加密的第一步(v6更新)# 加密:v6 += ( ((v5>>5) ^ (v5<<4)) + v5 ) ^ ( key[sum&3] + sum )# 解密:v6 减去该增量# --------------------------mix=((v1>>5)^((v1<<4)&0xFFFFFFFF))&0xFFFFFFFFk_sum=(key[sum_val&3]+sum_val)&0xFFFFFFFFinc=(mix+v1)&0xFFFFFFFF^k_sum# 逆加法v0=(v0-inc)&0xFFFFFFFFreturnv0,v1# --------------------------# 1. 提取密钥:数据段字节 → 小端解析为4个32位无符号整数# --------------------------key_bytes=bytes([0x03,0x02,0x01,0x00,0x07,0x06,0x05,0x04,0x0B,0x0A,0x09,0x08,0x0F,0x0E,0x0D,0x0C])key=list(struct.unpack('<4I',key_bytes))# < 表示小端序# --------------------------# 2. 提取密文:有符号int → 32位无符号整数# --------------------------cipher=[-1054939302,-1532163725,-165900264,853769165,768352038,876839116]cipher_uint=[x&0xFFFFFFFFforxincipher]# --------------------------# 3. 分3组解密(每组8字节/2个int)# --------------------------groups=[(cipher_uint[0],cipher_uint[1]),(cipher_uint[2],cipher_uint[3]),(cipher_uint[4],cipher_uint[5])]# --------------------------# 4. 逐组解密,拼接为flag字符串# --------------------------flag_bytes=b''forv0,v1ingroups:plain0,plain1=tea_decrypt(v0,v1,key)# 小端打包回字节序列flag_bytes+=struct.pack('<2I',plain0,plain1)# 输出结果print("解密得到的flag:",flag_bytes.decode('ascii'))

运行得到:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 7:27:49

情感计算技术如何革新企业估值方法

1. 企业估值新维度&#xff1a;情感计算技术的引入背景传统企业估值方法主要依赖财务数据、市场表现等量化指标&#xff0c;但近年来随着人工智能技术的发展&#xff0c;情感计算&#xff08;Affective Computing&#xff09;正逐渐成为评估企业价值的新维度。我在为多家科技企…

作者头像 李华
网站建设 2026/9/15 7:24:49

外贸网络营销策划方案制定:3个免费工具搞定高转化官网

外贸网络营销策划方案制定:3个免费工具搞定高转化官网 找建站公司怕被坑高价?别再交智商税了。 很多外贸老板做【外贸网络营销策划方案制定】,第一步就错了:把官网当成“电子名片”扔给开发公司,结果花了八万块,做出来的页面在谷歌上搜不到,询盘转化率为零。 真正的策划,不是看谁做得花哨,而是看谁能用…

作者头像 李华
网站建设 2026/9/15 7:24:37

基于SpringBoot+Vue的老年疗养院管理系统设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 7:24:21

【SONIC源码阅读系列2】运动数据到观测

现在开始整个系列的 Phase 0 Phase 1。这一部分会刻意放慢一点&#xff0c;因为后面 Universal Token、PPO 和 deployment 都建立在这里的数据定义之上。 这次直接以当前 main 分支代码为准&#xff0c;而不是只根据 SONIC report 复述。当前 repo 已经发展到包含 Default SON…

作者头像 李华
网站建设 2026/9/15 7:21:53

MicroPython与RP2040硬件深度协同原理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 7:17:07

AI通识基础Coze平台工作流搭建案例

扣子编程网站&#xff1a;www.coze.cn/store进入官网后点击资源库&#xff0c;再点击右上角资源&#xff0c;选中工作流进行创建。一、生成祝福图片案例需求&#xff1a;输入祝福主题 → 让大模型生成祝福语 → 根据祝福语生成图片描述 → 生成图片 → 输 出图片完整工作流1.开…

作者头像 李华