TEA算法及例题总结
算法详解
TEA在加密的过程中要加密的明文 使用2个32位无符号整数(2×4字节),秘钥 为4个32位无符号整数(4×4字节),更长的明文可通过分为多个4字节为单位的小组分别进行加密(循环)
加密流程示意图:

实战识别
在逆向分析实战中判断TEA算法的可从其3行核心加密中出现的右移4左移5,两行各有3个小括号互相异或的加密流程 和单次加密循环32次 以及运算中出现的sum和delta变量看出
代码实现
下面是TEA算法加密 过程的C语言函数实现
1 |
|
下面是TEA算法解密 过程的C语言代码实现
1 |
|
魔改
魔改TEA的一些方法:
腾讯TEATEA的变种,标准TEA中使用的32轮加密,而腾讯只用了16轮。
CBC模式的TEA
将明文分组与前一个密文分组进行异或运算,然后再进行加密,对于第一组的话就设置一个初始值来和第一组明文异或。每一轮是取v0和v1,data1, data2和v0,v1异或,异或之后的data1和data2传入指针进行tea加密,之后再将加密之后的赋值回的v0和v1。
逆向方法:
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
37int __fastcall main(int argc, const char **argv, const char **envp)
{
int v3; // eax
char *v4; // rcx
__m128i si128; // [rsp+20h] [rbp-19h] BYREF
int Buf2[8]; // [rsp+30h] [rbp-9h] BYREF
__int16 v8; // [rsp+50h] [rbp+17h]
__int128 Buf1; // [rsp+58h] [rbp+1Fh] BYREF
__int128 v10[2]; // [rsp+68h] [rbp+2Fh] BYREF
__int16 v11; // [rsp+88h] [rbp+4Fh]
Buf2[0] = 0x2E63829D;
Buf1 = 0i64;
memset(v10, 0, sizeof(v10));
v11 = 0;
Buf2[1] = 0xC14E400F;
si128 = _mm_load_si128((const __m128i *)&xmmword_1400022B0);
Buf2[2] = 0x9B39BFB9;
Buf2[3] = 0x5A1F8B14;
Buf2[4] = 0x61886DDE;
Buf2[5] = 0x6565C6CF;
Buf2[6] = 0x9F064F64;
Buf2[7] = 0x236A43F6;
v8 = '}k';// 按R变字符串
printf("nice tea!\n> ");
scanf("%50s");
sub_1400010B4((unsigned int *)&Buf1, si128.m128i_i32);
sub_1400010B4((unsigned int *)&Buf1 + 2, si128.m128i_i32);
sub_1400010B4((unsigned int *)v10, si128.m128i_i32);
sub_1400010B4((unsigned int *)v10 + 2, si128.m128i_i32);
v3 = memcmp(&Buf1, Buf2, 0x22ui64);
v4 = "wrong...";
if ( !v3 )
v4 = "Congratulations!";
printf(v4);
return 0;
}可知
Buf2为密文,si128是密文,核心加密算法在sub_1400010B4,其分组进行了四次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__int64 __fastcall sub_1400010B4(unsigned int *a1, int *a2)
{
int v2; // ebx
int v3; // r11d
int v4; // edi
int v5; // esi
int v6; // ebp
unsigned int v7; // r9d
__int64 v8; // rdx
unsigned int v9; // r10d
__int64 result; // rax
v2 = *a2;
v3 = 0;
v4 = a2[1];
v5 = a2[2];
v6 = a2[3];
v7 = *a1;
v8 = 32i64;
v9 = a1[1];
do
{
v3 -= 1412567261;
v7 += (v3 + v9) ^ (v2 + 16 * v9) ^ (v4 + (v9 >> 5));
result = v3 + v7;
v9 += result ^ (v5 + 16 * v7) ^ (v6 + (v7 >> 5));
--v8;
}
while ( v8 );
*a1 = v7;
a1[1] = v9;
return result;
}由
>>5和*16(即<<4)易知其为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
31
32
33
34
35
36
37
38
39
40
41
42
int main()
{
unsigned int key1 = 0x12345678;
unsigned int key2 = 0x23456789;
unsigned int key3 = 0x34567890;
unsigned int key4 = 0x45678901;
unsigned int sum = 0x79bde460;
int i = 32;
unsigned int enc1 = 0x9F064F64;
unsigned int enc2 = 0x236A43F6;//一定要注意把数据设置为无符号类型!!!
int enc[2] = { 0 };
do
{
enc2 -= (sum + enc1) ^ (key3 + 16 * enc1) ^ (key4 + (enc1 >> 5));
enc1 -= (sum + enc2) ^ (key1 + 16 * enc2) ^ (key2 + (enc2 >> 5));
sum -= -1412567261;
--i;
} while (i);
*enc = enc1;
enc[1] = enc2;
for (int j = 0; j < 2; j++) // 输出解密后的数据
{
for (int m = 0; m < 4; m++)
{
printf("%c", enc[j] ); // 按字节输出,恢复原始字符
enc[j] >>= 8;
}
}
printf("%c%c", 0x6b, 0x7d);
return 0;
//第一轮:hgame{Te
//第二轮:a_15_4_v
//第三轮:3ry_h3a1
//第四轮:thy_drln
//补充后缀:k}
//hgame{Tea_15_4_v3ry_h3a1thy_drlnk}
}
注意在原程序的密文定义中v8紧跟在enc数组的栈内地址后面,其没有进行tea加密,而是以明文形式存储着密文的最后两位内容
[HDCTF 2023]enc

进入main_0函数,经分析可知"input key"阶段进行的是TEA加密,并给出了key秘钥的内容(此处笔误写成了RC4)

查看栈段的调用发现v7和v8是连着的

传入RC4加密函数是v7的地址,根据后面if中的条件中对v7和v8的判断得出密文,可用TEA解密代码得出
1 |
|
得出解密结果为00030004(要以整数输出),即key为3
点开最后处理v6的sub_411302函数

发现是一堆未识别出的数据

打断点进入调试模式
步进运行程序将loc_0041D000地址的数据分析为指令,再在loc_0041D000处按P将其分析为函数,分析伪代码可知该函数为RC4加密
1 |
|
—|—
用RC4代码解密即可
