TEA 系列加密

TEA(Tiny Encryption Algorithm)是一种实现简单、速度较快的分组加密算法。它每次处理 64 bit(8 byte)数据,使用 128 bit(16 byte)密钥,常见迭代轮数为 32 轮。

在 CTF Reverse 中,TEA 系列常见于算法识别题。识别重点通常包括:

  • 以两个 uint32_t 作为一组数据块。
  • 使用四个 uint32_t 作为 key。
  • 循环中反复出现 sum += deltasum -= delta
  • 常量 0x9e3779b9 或其补码形式 0x61c88647

TEA 后续还有 XTEA、XXTEA 等变种,核心思路相近,但轮函数和数据组织方式会有差异。

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include<stdio.h>

#include<stdint.h>



void encrypt(uint32_t* v,uint32_t* k)

{

    uint32_t sum=0;

    uint32_t v0=v[0],v1=v[1];

    uint32_t delta=0x9e3779b9;

    uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];



    for(int i=0;i<32;i++)

    {

        sum+=delta;

        v0+=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);

        v1+=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);

    }

    v[0]=v0;

    v[1]=v1;

}



void decrypt(uint32_t* v,uint32_t* k)

{

    uint32_t v0=v[0],v1=v[1];

    uint32_t delta=0x9e3779b9;

    uint32_t sum=delta*32;

    uint32_t k0=k[0],k1=k[1],k2=k[2],k3=k[3];

    for(int i=0;i<32;i++)

    {

        v1-=((v0<<4)+k2)^(v0+sum)^((v0>>5)+k3);

        v0-=((v1<<4)+k0)^(v1+sum)^((v1>>5)+k1);

    }



    v[0]=v0;

    v[1]=v1;

}



int main()

{



    // 两个32位无符号整数,即待加密的64bit明文数据

    char plain[]="12345678";

    uint32_t v[2]={0x12345678,0x78563412};

    // 四个32位无符号整数,即128bit的key

    uint32_t k[4]={0x1,0x2,0x3,0x4};

    printf("Data is : %x %x\n",v[0],v[1]);

    encrypt(v,k);

    printf("Encrypted data is : %x %x\n",v[0],v[1]);

    decrypt(v,k);

    printf("decrypted data is : %x %x\n",v[0],v[1]);



    return 0;



}

由于TEA用python是实现比较麻烦(需要截断位数),因此在逆向的时候我们经常将ida里的逻辑复制粘贴到C编译器中稍加修改就可以了

识别特征:

-标准DELTA常数(魔数)
-密钥为16字节(4个DWORD)加密轮数为16/32/64轮加密结构中存在左4右5移位及异或运算加密结构中存在轮加/减相同常数的语句

对抗方式:

-修改魔数
-修改轮数
-修改轮加/减魔数的位置
就做题经验来看,tea解密时数据大多是unsigned int 类型的

XTEA:

XTEA
XTEA是TEA的升级版,变量类型处理和TEA一样,主要是加密逻辑有所变化,对每轮加密的key的选择也有所变化。
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include<stdio.h>

#include<stdint.h>

void encrypt(uint32_t* v,uint32_t* key)

{

    uint32_t v0=v[0],v1=v[1];

    uint32_t sum=0,delta=0x9E3779B9;

    for(int i=0;i<32;i++)

    {

        v0+=(((v1<<4)^(v1>>5))+v1)^(sum+key[sum&3]);

        sum+=delta;

        v1+=(((v0<<4)^(v0>>5))+v0)^(sum+key[(sum>>11)&3]);

    }

    v[0]=v0;

    v[1]=v1;

}



void decrypt(uint32_t* v,uint32_t* key)

{

    uint32_t v0=v[0],v1=v[1];

    uint32_t delta=0X9E3779B9;

    uint32_t sum=delta *32;

    for(int i=0;i<32;i++)

    {

        v1-=(((v0<<4)^(v0>>5))+v0)^(sum+key[(sum>>11)&3]);

        sum-=delta;

        v0-=(((v1<<4)^(v1>>5))+v1)^(sum+key[sum&3]);

    }

}

识别特征:

同TEA
加密结构中存在右移11位并&3的运算

对抗方式:

同TEA

XXTEA:

XXTEA是XTEA的升级版,其实现过程比前两种算法要略显复杂些,加密的明文数据可以不再是64bit(两个32位无符号整数),并且其加密轮数是由n,即待加密数据个数决定的.
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include<stdio.h>

#include<stdint.h>

#define DELTA 0x9e3379B9//最常见的魔改就是delta的值

#define MX (((z>>5^y<<2)+(y>>3^z<<4))^((sum^y)+(key[(p&3)^e]^z)))

void xxtea(uint32_t* v,int n,uint32_t* key)

{

    uint32_t y,z,sum;

    unsigned p,rounds,e;

    if(n>1)

    {

        rounds=6+52/n;//这里的轮数可以魔改,同时这个轮数也是一个xxtea的特征

        sum=0;

        z=v[n-1];

        do

        {

            sum+=DELTA;

            e=(sum>>2)&3;//这里也是一个特征

            for(p=0;p<n-1;p++)

            {

                y=v[p+1];

                z=v[p]+=MX;

            }

            y=v[0];

            z=v[n-1]+=MX;

        }

        while(--rounds);

    }

    else if(n<-1)

    {

        n=-n;

        rounds=6+52/n;

        sum=rounds*DELTA;

        y=v[0];

        do

        {

            e=(sum>>2)&3;

            for(p=n-1;p>0;p--)

            {

                z=v[p-1];

                y=v[p]-=MX;

            }

            z=v[n-1];

            y=v[0]-=MX;

            sum-=DELTA;

        }

        while(--rounds);

    }



}



int main()

{

    uint32_t v[2]={0x12345678,0x78563412};//这里可以改加密数据的长度

    uint32_t k[4]={0x1,0x2,0x3,0x4};

    int n=2;这里的n和加密数据的长度统一



    printf("Data is : %x %x\n",v[0],v[1]);

    xxtea(v,n,k);

    printf("Encrypted data is : %x %x\n",v[0],v[1]);

    xxtea(v,-n,k);

    printf("Decrypted data is : %x %x\n",v[0],v[1]);



    return 0;