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 #include <stdint.h> void encrypt (uint32_t * v, uint32_t * k) { uint32_t v0=v[0 ], v1=v[1 ], sum=0 , 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++) { 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; }
在 Tea 算法中其最主要的识别特征就是 拥有一个 magic number :0x9e3779b9 。当然,这 Tea 算法也有魔改的,感兴趣的可以看 2018 0ctf Quals milk-tea。
概念 解析 TEA 加密算法(C语言、python):
TEA系列概述:
TEA算法是由剑桥大学计算机实验室的 David Wheeler 和 Roger Needham于1994年发明,TEA 是Tiny Encryption Algorithm的缩写,以加密解密速度快,实现简单著称。
TEA 算法每一次可以操作 64bit(8byte),采用 128bit(16byte) 作为 key,算法采用迭代的形式,推荐的迭代轮数是 64轮,最少 32 轮。
为解决 TEA 算法密钥表攻击的问题,TEA 算法先后经历了几次改进,从 XTEA 到 BLOCK TEA,直至最新的XXTEA。
XTEA 也称做 TEAN:
它使用与 TEA 相同的简单运算,但四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。
Block TEA 算法可以对 32 位的任意整数倍长度的变量块进行加解密的操作:
该算法将 XTEA 轮循函数依次应用于块中的每个字,并且将它附加于被应用字的邻字。
XXTEA使用跟Block TEA相似的结构:
但在处理块中每个字时利用了相邻字,且用拥有两个输入量的 MX 函数代替了 XTEA 轮循函数。
上面提到的相邻字其实就是数组中相邻的项。
TEA 系列算法中均使用了一个 DELTA 常数,但 DELTA 的值对算法并无什么影响,只是为了避免不良的取值,推荐DELTA 的值取为黄金分割数 (5√-2)/2 与 232 的乘积,取整后的十六进制值为 0x9e3779B9,用于保证每一轮加密都不相同。
TEA 加密: TEA算法介绍:
TEA 采用与 DES 算法类似的 Feistel 结构,迭代的每次循环使用加法和移位操作,对明文和密钥进行扩散和混乱,实现明文的非线性变换。TEA 密钥长度和迭代次数都是 DES 的两倍,抗“试错法”攻击的强度不低于 DES 算法。算法以32bits 的字为运算单位,而不是耗费计算能力的逐位运算。算法没有采用 DES 那样的转换矩阵,它安全、高效、占用存储空间少,非常适合在嵌入式系统中应用, 据说 QQ 就是使用 16 轮迭代的 TEA 算法。
加密过程:(解密过程逆过来即可)
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 #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; uint32_t delta=0x9e3779b9 ; uint32_t k0=k[0 ],k1=k[1 ],k2=k[2 ],k3=k[3 ]; for (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 ],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 }; 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 ; }
python脚本 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 from ctypes import * def encrypt(v, k): v0 = c_uint32(v[0]) v1 = c_uint32(v[1]) sum1 = c_uint32(0) delta = 0x9e3779b9 for i in range(32): sum1.value += delta v0.value += ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1]) v1.value += ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3]) return v0.value, v1.value def decrypt(v, k): v0 = c_uint32(v[0]) v1 = c_uint32(v[1]) delta = 0x9e3779b9 sum1 = c_uint32(delta * 32) for i in range(32): v1.value -= ((v0.value << 4) + k[2]) ^ (v0.value + sum1.value) ^ ((v0.value >> 5) + k[3]) v0.value -= ((v1.value << 4) + k[0]) ^ (v1.value + sum1.value) ^ ((v1.value >> 5) + k[1]) sum1.value -= delta return v0.value, v1.value if __name__ == '__main__': a = [1, 2] k = [2, 2, 3, 4] print("加密前数据:", a) res = encrypt(a, k) print("加密后的数据:", res) res = decrypt(res, k) print("解密后数据:", res)
原文链接:https://blog.csdn.net/xiao__1bai/article/details/123307059
XTEA加密 首先我们还是先了解一下XTEA算法 跟TEA算法很类似,差别就是将r的变化结果和l变化结果进行了交替赋值,同时位移次数进行了一些变化,也掺杂了一些与操作
这里是典型的XTEA加密和异或加密,但是根据给定的key和 算法 ,计算出来的是一个假flag: fakeflag_plz_Try_more_hard_to_find_the_true_flag
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 #include <stdio.h> #include <stdint.h> 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 ; 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 ; }
TEA例题 1、 先查壳,放入64
直接运行exe是个fakeflag哈哈哈哈哈
去string里面找关键语句,然后x快捷键去查看调用的函数
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 for ( j = 0; j < 10; ++j ) // 输入函数,scanf sub_1400111FE("%x", &v8[j]); // v7重新赋值 sub_140011339(v7); // v8备份到v9 sub_140011145(v8, v9); // v7为key,v8为输入的值,进行tea加密 sub_1400112B7(v8, v7); // 验证加密的结果是否符合预期 v6 = sub_140011352(v8); if ( v6 ) { // sub_140011195 为打印函数 printf("you are right\n"); for ( k = 0; k < 10; ++k ) { for ( m = 3; m >= 0; --m ) printf("%c", (v9[k] >> (8 * m))); } } else { printf("fault!\nYou can go online and learn the tea algorithm!"); }
跟进 sub_140011339(v7),发现v7被重新赋值
原来的———————————————————>改后的
1 2 3 4 v7[0] = 1234; v7[1] = 5678; v7[2] = 9012; v7[3] = 3456;
1 2 3 4 5 6 7 8 v6 = 2233; v7 = 4455; v8 = 6677; v9 = 8899; *a1 = 2233; a1[1] = v7; a1[2] = v8; a1[3] = v9;
// v8备份到v9;
跟进sub_140011145(v8, v9);发现就是一个备份功能的函数
// v7为key,v8为输入的值,进行tea加密
sub_1400112B7(v8, v7);
进入 sub_140011B60 函数,得到加密后的数据,开始写脚本
cexp 经典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 int main () { int key[] = {2233 , 4455 , 6677 , 8899 }; unsigned int value[10 ]; value[0 ] = 0x1A800BDA ; value[1 ] = 0xF7A6219B ; value[2 ] = 0x491811D8 ; value[3 ] = 0xF2013328 ; value[4 ] = 0x156C365B ; value[5 ] = 0x3C6EAAD8 ; value[6 ] = 0x84D4BF28 ; value[7 ] = 0xF11A7EE7 ; value[8 ] = 0x3313B252 ; value[9 ] = 0xDD9FE279 ; int delta = 0xF462900 ; int i = 0 ; int wheel; int sum = 0 ; for (i = 8 ; i >= 0 ; i--) { wheel = 33 ; sum = delta * (i + wheel); while (wheel--) { sum -= delta; value[i + 1 ] -= (sum + key[(sum >> 11 ) & 3 ]) ^ (value[i] + ((value[i] >> 5 ) ^ (16 * value[i]))); value[i] -= sum ^ (value[i + 1 ] + ((value[i + 1 ] >> 5 ) ^ (16 * value[i + 1 ]))) ^ (sum + key[sum & 3 ]); } } for (i = 0 ; i <= 9 ; i++) { printf ("%c" , (value[i] >> 24 ) & 0xFF ); printf ("%c" , (value[i] >> 16 ) & 0xFF ); printf ("%c" , (value[i] >> 8 ) & 0xFF ); printf ("%c" , value[i] & 0xFF ); } return 0 ; }
pyexp(会有乱码) python代码可以会输出乱码,主要是溢出的问题,去掉乱码投机正确,还是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 def main(): key = [2233, 4455, 6677, 8899] # 密钥数组 value = [0x1A800BDA, 0xF7A6219B, 0x491811D8, 0xF2013328, 0x156C365B, 0x3C6EAAD8, 0x84D4BF28, 0xF11A7EE7, 0x3313B252, 0xDD9FE279] # 初始化加密数据 delta = 0x0F462900 # 一个常量,用于加密算法 sum = 0 # 逆算法解密 for i in range(8, -1, -1): wheel = 33 # 33轮加密 sum = delta * (i + wheel) while wheel > 0: sum -= delta sum &= 0xFFFFFFFF # 保持为32位 value[i + 1] -= ((sum + key[(sum >> 11) & 3]) ^ (value[i] + ((value[i] >> 5) ^ (16 * value[i])))) value[i + 1] &= 0xFFFFFFFF # 保持为32位 value[i] -= (sum ^ (value[i + 1] + ((value[i + 1] >> 5) ^ (16 * value[i + 1]))) ^ (sum + key[sum & 3])) value[i] &= 0xFFFFFFFF # 保持为32位 wheel -= 1 # 将解密后的数据转换为字符并输出 for val in value: print(chr((val >> 24) & 0xFF), end='') # 高8位 print(chr((val >> 16) & 0xFF), end='') # 次高8位 print(chr((val >> 8) & 0xFF), end='') # 次低8位 print(chr(val & 0xFF), end='') # 低8位 if __name__ == "__main__": main()
2、
代码分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 scanf("%s", v5); v9 = v5; // 将输入的值赋入 v4的后八位 for ( i = 0; i <= 5; ++i ) v4[i + 8] = *v9++; // 两两进行XTea加密 for ( j = 0; j <= 2; ++j ) tea_encrypt(&v4[2 * j + 8], &key); // 加密后的字符串要等于这些 v4[0] = -1054939302; v4[1] = -1532163725; v4[2] = -165900264; v4[3] = 853769165; v4[4] = 768352038; v4[5] = 876839116; for ( k = 0; k <= 5; ++k ) { if ( v4[k] != v4[k + 8] ) { printf("ERROR!"); exit(9); } }
按d,将key合成为4位、8字节的形式,再提取 tea加密函数 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 #include<stdio.h> int main() { unsigned int enc[6] = {0xC11EE75A, 0xA4AD0973, 0xF61C9018, 0x32E37BCD, 0x2DCC1F26, 0x344380CC}; unsigned int key[4] = {0x10203, 0x4050607, 0x8090A0B, 0x0C0D0E0F}; int i, j; long sum = 0, delta = 0x61C88647; // 解码 for(i=0;i < 6;i+=2){ sum = 0 - (32 * delta); for(j = 0; j < 32; j++) { enc[i+1] -= (((enc[i] >> 5) ^ (16 * enc[i])) + enc[i]) ^ (key[((sum >> 11) & 3)] + sum); sum += delta; enc[i] -= ((((enc[i+1] >> 5) ^ (16 * enc[i+1])) + enc[i+1]) ^ key[sum & 3] + sum); } } // 打印 for (i = 0; i < 6; i++) { for (j = 0; j<=3; j++) { printf("%c", (enc[i] >> (j * 8)) & 0xFF); } } return 0; }
ezzzz 先每8位转化成一个数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def string_to_hex_with_prefix(input_string): # 创建一个空的结果数组 hex_result = [] # 每 8 个字符一组 for i in range(0, len(input_string), 8): chunk = input_string[i:i + 8] # 将每组字符转为十六进制并加上 '0x' 前缀 hex_value = int(chunk.encode('utf-8').hex()) # 添加到数组中 hex_result.append(hex_value) return hex_result # 示例 input_string = "f1f186b25a96c782e6c63a0b70b61b5ced6bf84889700d6b09381b5ccb2f24fab1c79e796d822d9cdcc55f760f780e750d65c4afb89084a9e978c3827a8dd81091f28df3a84dbacab4d75f75f19af8e5b90f80fcfc10a5c3d20679fb2bc734c8ccb31c921ac52ad3e7f922b72e24d923fb4ce9f53548a9e571ebc25adf38862e10059186327509463dd4d54c905abc36c26d5312d2cd42c0772d99e50cd4c4665c3178d63a7ffe71ada251c070568d5a5798c2921ec0f7fc3ae9d8418460762930ca6a2dccef51d2a1a8085491b0f82d686ca34774c52d0f0f26449fc28d362c86f3311b8adc4fb1a4497e34e0f0915d" # 输入字符串 hex_output = string_to_hex_with_prefix(input_string) # 输出结果 print("Hexadecimal array:", hex_output)
喝茶 上面为密文,记得转成十六进制
提取key和密文
每两个一组进行tea解密,一共6个三组解密完成
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 #include <stdio.h> #include <stdint.h> void decrypt (uint32_t *v,uint32_t *k) { uint32_t v0=v[0 ],v1=v[1 ],sum=0x1919810 *32 ,i; uint32_t delta=0x1919810 ; 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 input[] = {0x12287745 , 0x3692f306 , 0x0ee7c0e2 , 0xb97f85b7 , 0xaa966689 , 0x46b81a67 }; uint32_t k[4 ]={0x73656372 ,0x65746b65 ,0x79313233 ,0x34353637 }; for (int i=0 ;i<6 ;i+=2 ) { uint32_t v[2 ]={input[i],input[i+1 ]}; decrypt(v,k); for (int j = 0 ; j < 2 ; j++) { for (int k = 0 ; k < 4 ; k++) { printf ("%c" , v[j] & 0xff ); v[j] >>= 8 ; } } } return 0 ; }
XTEA例题 1、 这里是典型的XTEA加密和异或加密,但是根据给定的key和 算法 ,计算出来的是一个假flag: fakeflag_plz_Try_more_hard_to_find_the_true_flag
更新: 2025-04-19 16:44:05 原文: https://www.yuque.com/chaye-apqbl/vsc85q/rqg1uagfufcb8ylp