TEA 系列加密
TEA(Tiny Encryption Algorithm)是一种实现简单、速度较快的分组加密算法。它每次处理 64 bit(8 byte)数据,使用 128 bit(16 byte)密钥,常见迭代轮数为 32 轮。
在 CTF Reverse 中,TEA 系列常见于算法识别题。识别重点通常包括:
- 以两个
uint32_t 作为一组数据块。
- 使用四个
uint32_t 作为 key。
- 循环中反复出现
sum += delta 或 sum -= 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()
{
char plain[]="12345678";
uint32_t v[2]={0x12345678,0x78563412};
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
#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;
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;
|