week3-re-tea

算法特征

tea 算法

主要特征表现在 sum 和 delta 变量,以及三行核心加密中出现的右移 4 左移 5,两行各有 3 个小括号相互异或。

加密过程

密钥长度为 128 位

下面被拆分成 4 个子密钥 [K0,K1,K2,K3]

将 64 位明文分成两部分(假设为 LR,各 32 位)

进行 64 轮加密,更新 LR

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; // delta = 0x9E3779B9(黄金比例相关)
}
  • (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,进入

我们点进去查看

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

  • 原来的 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++) { // 杩欎竴娈典富瑕佹槸鎶?v 鎸夊崟瀛楄妭杈撳嚭锛屽彟澶栧彲浠ヤ簡瑙d竴涓?鈥滃ぇ灏忕搴忊€?鍦ㄨ繖棰樻槸濡備綍浣撶幇鐨?
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+}