TEA,XTEA 与 XXTEA 及其例题

不介绍背景了,直接上算法

TEA

TEA 算法是一种对称加密算法,全称为 Tiny Encryption Algorithm。它使用一个 128 位的密钥和 64 位的明文块,通过多轮迭代加密来实现加密过程。TEA 算法的加密和解密过程是相同的,只是密钥的使用顺序不同。其拥有一个叫做 Feistel 结构的密码学结构。这种密码学结构通俗的来讲就是会将加密的 plaintext 分成 L、R 两部分,并且满足 L*{i+1} = R_i, R*{i+1} = F(K_i,R_i) \oplus L_i 这种交换式的加密方式的一种结构。tea 算法最关键的是要找到 DELTA 值和 128 位的 key。其中 DELTA 常常是存在 0x9e3779b9,但是也存在 DELTA 的值被改变的代码。除了初等 tea 算法,tea 算法还有很多魔改版本。

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
#include <stdio.h>
#include <stdint.h>

//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; //v0,v1分别为字符串的低字节高字节
uint32_t delta=0x9e3779b9;
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i < 32; i++) { //加密32轮
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], sum=0xC6EF3720, i;
uint32_t delta=0x9e3779b9;
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i<32; i++) { //解密时将加密算法的顺序倒过来,还有+=变为-=
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
}
v[0]=v0; v[1]=v1;//解密后再重新赋值
}

int main()
{
uint32_t v[2]={1,2},k[4]={2,2,3,4};
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
encrypt(v, k);
printf("加密后的数据:%u %u\n",v[0],v[1]);
decrypt(v, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}

xTEA

XTEA 是 TEA 的升级版:

XTEA 算法的加密和解密过程都是由多轮迭代完成的。每轮迭代都包括四个步骤:轮密钥加、代换、置换和轮密钥加。其中,代换和置换步骤是 XTEA 算法的核心部分。XTEA 算法是 TEA 算法的魔改算法。XTEA 算法四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。

xtea

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
#include <stdio.h>
#include <stdint.h>

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
for (i=0; i < num_rounds; 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 decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
for (i=0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0]=v0; v[1]=v1;
}

int main()
{
uint32_t v[2]={1,2};
uint32_t const k[4]={2,2,3,4};
unsigned int r=32;//num_rounds建议取值为32
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
encipher(r, v, k);
printf("加密后的数据:%u %u\n",v[0],v[1]);
decipher(r, v, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}

xxTEA

XXtea 算法的基本原理是将明文分成若干个固定长度的块,然后对每个块进行加密。加密过程中,使用一个密钥对每个块进行加密,然后将加密后的块拼接在一起形成密文。
解密过程与加密过程相反。使用相同的密钥对密文进行解密,然后将解密后的块拼接在一起形成明文。

xxtea

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

#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52/n;
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) /* Decoding Part */
{
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]= {1,2};
uint32_t const k[4]= {2,2,3,4};
int n= 2; //n的绝对值表示v的长度,取正表示加密,取负表示解密
// v为要加密的数据是两个32位无符号整数
// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
printf("加密前原始数据:%u %u\n",v[0],v[1]);
btea(v, n, k);
printf("加密后的数据:%u %u\n",v[0],v[1]);
btea(v, -n, k);
printf("解密后的数据:%u %u\n",v[0],v[1]);
return 0;
}

例题

【xxtea】happytime.elf(同时也练一下监听调试)

监听前置工作:

将 ida 中的 linux_server64 拖入到 linux 中

拖入后 chmod + x linux_server64 chmod +x 你的待调试文件名给予权限

1
2
ifconfig 			查询ip
./linux_server64 进行监听

查克无壳 ida

happytime01

跟进 cry

happytime-cry

发现是 xxtea,找了一个 xxtea 的算法模板进行相关修改

那么第一个图的 v5 就是 key,v6 就是密文

这里直接用轮数会出问题所以用了下动调直接将加密后轮数得出

偷懒动调

exp

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
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x61C88647
#define MX ( ( (z>>5^y<<2) + (y>>3^z<<4) ) ^ ( (sum^y) + (key[(p&3)^e] ^ z) ) )

void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 415 / n + 114;
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) /* Decoding Part */
{
n = -n;
rounds = 415 / n + 114;
sum = 0x52b8cc1f;//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[11]= {0x480AC20C,0xCE9037F2,0x8C212018,0xE92A18D,0xA4035274,0x2473AAB1,0xA9EFDB58,0xA52CC5C8,0xE432CB51,0xD04E9223,0x6FD07093};
uint32_t const k[4]= {0x79696755,0x67346F6C,0x69231231,0x5F674231};
int n= 11;
// btea(v, n, k);
//printf("0x%0x",k[3]);
btea(v, -n, k);
printf("%s",v);

return 0;
}

【xxtea】[NewStarCTF 公开赛赛道]EzTea

可以看看这位师傅的 blog:https://www.cnblogs.com/Only-xiaoxiao/p/16759891.html

查克无壳 ida

newstarCtf01

这是将输入的字符串进行加密后与预定密文比对,

跟进查看 sub_140011c0

newstarCtf02

发现还是 xxtea

回到前面跟进查看 unk_140004038 获得 key

查看 dword_140004038 获得密文

exp

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
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x11451400
#define MX (((z ^ (key[(e ^ p) & 3])) + (y ^ sum)) ^ (((32 * z) ^ (y >> 3)) + ((4 * y) ^ (z >> 4))))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52 / n ;
sum = 0;
z = v[n-1];
do
{
sum += DELTA;A
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) /* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n ;
sum = rounds*DELTA;/*0xbdf7dc00*/;
//这次可以用round*常数,也可以动调
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[9]= {0x38FA8A82, 0x0D7501380, 0x0E40969D, 0x4E169120, 0x713A29AB, 0x6CE5393D, 0x0B69D752E, 0x841A88E6, 0x6F31B459};
uint32_t const k[4]= {0x19,0x19,0x08,0x10};
int n= 9;
// btea(v, n, k); //鍔犲瘑
//printf("0x%0x",k[3]);
btea(v, -n, k);
printf("%s",v);

return 0;
}

大佬们文章与视频,去看看有助于理解

csdn:(这两我建议配着看)

1.https://blog.csdn.net/m0_73393932/article/details/130094306?ops_request_misc=&request_id=&biz_id=102&utm_term=tea%E7%AE%97%E6%B3%95&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-130094306.142

2.https://blog.csdn.net/xiao__1bai/article/details/123307059

b 站:(第一个视频没有更新到 xxtea 的动画演示理解,第二个 up 麦比较炸)
【【动画密码学】TEA(Tiny Encryption Algorithm)|分组加密】 https://www.bilibili.com/video/BV1Nu411E7wX/?share_source=copy_web&vd_source=86d6e63e560e68bb720088caa831e036

【VTuber 深入浅出应用密码学 7-2-1 XTEA 算法 C++代码 对称密码 块密码 分组密码 信息安全】 https://www.bilibili.com/video/BV1zF411U7ap/?share_source=copy_web&vd_source=86d6e63e560e68bb720088caa831e036