week3-re-tea
算法特征
tea 算法
主要特征表现在 sum 和 delta 变量,以及三行核心加密中出现的右移 4 左移 5,两行各有 3 个小括号相互异或。
加密过程
密钥长度为 128 位
下面被拆分成 4 个子密钥 [K0,K1,K2,K3]
将 64 位明文分成两部分(假设为 L
,R
,各 32 位)
进行 64 轮加密,更新 L
,R
1 2 3 4 5
| for (int i = 0; i < 64; i++) { L += ((R << 4) + K0) ^ (R + sum) ^ ((R >> 5) + K1); R += ((L << 4) + K2) ^ (L + sum) ^ ((L >> 5) + K3); sum += delta; }
|
(R << 4) + K0
:左移 4 位后叠加 K0
。
(R >> 5) + K1
:右移 5 位后叠加 K1
。
sum 初始值为 0,每轮加密累加 delta
XTEA
增多了密钥表,移位和异或等操作
核心加密
1 2 3
| L += ((R << 4 ^ R >> 5) + R) ^ (sum + K[sum & 3]); sum += delta; R += ((L << 4 ^ L >> 5) + L) ^ (sum + K[(sum >> 11) & 3]);
|
XXTEA
再难一点
1
| v[j] += ((v[j-1] << 4 ^ v[j-1] >> 5) + v[j-1]) ^ (sum + K[(j & 3) ^ e]);
|
例题
[GDOUCTF 2023]Tea
先查壳

我们用 ida 打开后 利用 shift+f12 查找关键字,如下

我们看到了 you are right,跟进(尝试),并查看 交叉引用(ctrl+x)

并按 F5,进入

我们点进去查看


这两个都是输入函数,将 v7
,v8
分别输入,我们一个一个点进去看看

- 原来的 v7 值为 1234,5678,9012,3456
- 改变后的 v7 值为 2233,4455,6677,8899
在上面的 sub_140011339 中,a1 就是最初的 v7
在 sub_140011352 中

在这里,a1 应该就对应的是 flag,也就是 v8,转换一下就是

进入下面的函数

里面是关键加密部分


这里就是 Tea 加密过程,其中的 a2 是原本的 v7,也就是 key 值

我们进行改名,这道题差不多的逻辑就是这样
然后利用 c 语言对 Tea 加密过程进行逆写,形成一个解密脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include <stdio.h> #include <stdint.h> #define delta 0xF462900
int main() { uint32_t key[4] = {2233,4455,6677,8899}; uint32_t Data[10] = { 0x1A800BDA ,0xF7A6219B ,0x491811D8,0xF2013328,0x156C365B, 0x3C6EAAD8,0x84D4BF28,0xF11A7EE7,0x3313B252,0xDD9FE279 }; unsigned int j; int i; unsigned int sum; for (i = 8; i >= 0; i--) { j = 33; sum = delta * (i + j); while(j--) { sum -= delta; Data[i + 1] -= (sum + key[(sum >> 11) & 3]) ^ ((Data[i] + ((Data[i] >> 5) ^ (Data[i] << 4)))); Data[i] -= sum ^ (Data[i + 1] + ((Data[i + 1] >> 5) ^ (Data[i + 1] << 4))) ^ (sum + key[sum & 3]); }
}
for (int i = 0; i < 10; i++) { printf("%x", Data[i]); } return 0; }
|
485a4354467b687a4374665f39345f726536363666696e676372793536343171717d0
利用赛博厨子进行十六进制解码

HZCTF{hzCtf_94_re666fingcry5641qq}
[MoeCTF 2022]ezTea
打开题目中的 c 语言代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <stdio.h> #include <stdint.h>
void encrypt (uint32_t* v, uint32_t* k) { uint32_t v0 = v[0], v1 = v[1], sum = 0; uint32_t delta = 0xd33b470; for (int i = 0; i < 32; i++) { sum += delta; v0 += ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]); v1 += ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]); } v[0] = v0; v[1] = v1; }
int main() { uint32_t k[4] = {1, 2, 3, 4}; int8_t input[33] = {0}; scanf("%32s", input); for (int i = 0; i < 32; i+=8) { uint32_t v[2] = {*(uint32_t *)&input[i], *(uint32_t *)&input[i+4]}; encrypt(v, k); for (int j = 0; j < 2; j++) { for (int k = 0; k < 4; k++) { printf("%#x, ", v[j] & 0xff); v[j] >>= 8; } } } return 0; }
|
- 这段代码是一个 TEA 变种加密实现,对 32 字节输入分组加密。
- 核心:32 轮 Feistel 运算,密钥
{1,2,3,4}
,delta=0xd33b470
。
根据提示,当输入正确的 flag 时,会输出 0x17, 0x65, 0x54, 0x89, 0xed, 0x65, 0x46, 0x32, 0x3d, 0x58, 0xa9, 0xfd, 0xe2, 0x5e, 0x61, 0x97, 0xe4, 0x60, 0xf1, 0x91, 0x73, 0xe9, 0xe9, 0xa2, 0x59, 0xcb, 0x9a, 0x99, 0xec, 0xb1, 0xe1, 0x7d
输入的 flag 被分为 4 组,每组 8 字节
sum
初始值为 delta * 32
(因为加密时 sum
累加了 32 次 delta
)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <stdio.h> #include <stdint.h>
void decrypt(uint32_t* v, uint32_t* k) { uint32_t v0 = v[0], v1 = v[1]; uint32_t delta = 0xd33b470; uint32_t sum = delta * 32; // 加密时的最终sum值 for (int i = 0; i < 32; i++) { v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]); v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]); sum -= delta; } v[0] = v0; v[1] = v1; }
int main() { uint32_t k[4] = {1, 2, 3, 4}; // 给定的密文(按小端序组合成uint32_t) uint8_t cipher[32] = { 0x17, 0x65, 0x54, 0x89, 0xed, 0x65, 0x46, 0x32, 0x3d, 0x58, 0xa9, 0xfd, 0xe2, 0x5e, 0x61, 0x97, 0xe4, 0x60, 0xf1, 0x91, 0x73, 0xe9, 0xe9, 0xa2, 0x59, 0xcb, 0x9a, 0x99, 0xec, 0xb1, 0xe1, 0x7d };
// 每组8字节解密 for (int i = 0; i < 32; i += 8) { // 将小端序的密文转换为uint32_t uint32_t v[2] = { *(uint32_t*)&cipher[i], *(uint32_t*)&cipher[i+4] }; decrypt(v, k); // 输出解密后的明文(按小端序) for (int j = 0; j < 2; j++) { for (int k = 0; k < 4; k++) { printf("%c", (v[j] >> (k * 8)) & 0xff); } } } return 0; }
|
运行得到 flag moectf{Th3_TEA_!S_s0_t4s7y~~!!!}
[HNCTF 2022 WEEK2]TTTTTTTTTea
先查壳

我们先查一下关键字

这个可能是我们需要的,跟进,查看交叉引用

F5


跟进&key


得到 key 的
看到 tea_encrypt(&v4[2 * j + 8], &key);
,跟进一下

看到主加密函数,这是一个 xtea,接下来逆向,写解密脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| **#include<stdio.h>int** **main**(){ **unsigned** **int** enc[6] = {0xC11EE75A, 0xA4AD0973, 0xF61C9018, 0x32E37BCD, 0x2DCC1F26, 0x344380CC}; **unsigned** **int** key[4] = {0x10203, 0x4050607, 0x8090A0B, 0x0C0D0E0F}; **int** i, j; **long** sum = 0, delta = 0x61C88647; _// 解码_**for**(i=0;i < 6;i+=2){ sum = 0 - (32 * delta); **for**(j = 0; j < 32; j++) { enc[i+1] -= (((enc[i] >> 5) ^ (16 * enc[i])) + enc[i]) ^ (key[((sum >> 11) & 3)] + sum); sum += delta; enc[i] -= ((((enc[i+1] >> 5) ^ (16 * enc[i+1])) + enc[i+1]) ^ key[sum & 3] + sum); } } _// 打印_**for** (i = 0; i < 6; i++) { **for** (j = 0; j<=3; j++) { printf("%c", (enc[i] >> (j * 8)) & 0xFF); } }
**return** 0; }
|
得到 flag NSSCTF{Tea_TEA_TeA_TEa+}