RE入门第三天---TEA算法

news/2024/9/20 9:23:58/文章来源:https://www.cnblogs.com/yanxiao777/p/18381269

OK,老规矩,先复习一下昨天的内容

.....

几分钟就复习了,直接开干今天的内容

先找大佬的wp

来源:

TEA系列加密解密 | Gruge's Blog (g2uge.github.io)

逆向算法之TEA算法 - Sk2rw - 博客园 (cnblogs.com)

一.TEA加密解密简介

在密码学中,微型加密算法(Tiny Encryption Algorithm,TEA)是一种易于描述和执行的块密码,通常只需要很少的代码就可实现。

代码的特点:

  • 加密使用的数据为2个32位无符号整数,密钥为4个32位无符号整数即密钥长度为128位(当加密解密的对象是一串数组的时候,需要将这个32位无符号整数的数组每两个32位无符号整数划分为一组,对每一组数据单独加密解密得到结果)
  • 该算法使用了一个常数 δ 作为倍数,它来源于黄金比率,以保证每一轮加密都不相同。但 δ 的精确值似乎并不重要,这里 TEA 把它定义为 δ=「(√5 - 1)231」(也就是程序中的 0×9E3779B9)作为魔数(了解即可)

加密过程

拥有一个叫做Feistel 结构的密码学结构。这种密码学结构通俗的来讲就是会将加密的plaintext分成L、R两部分,并且满足 L_{i+1} = R_i, R_{i+1} = F(K_i,R_i) \oplus L_i 这种交换式的加密方式的一种结构。

img

TEA加密算法的实现

参数要求:输入一定要是一个64bit的数字,或者可以写作一个拥有两个元素的32bit的数组。并且需要一个两倍长度的key(int[4]),即一个128位的数字(拥有四个元素的32bit的数组)

加密特征:存在一个delta值,这个值会不停的增加到sum之中,形成一种循环的效果;会有一个位移->与密钥相加->异或的过程;

计算delta的sum状态值也会参与

void encrypt (uint32_t v[2], const uint32_t k[4]) {uint32_t v0=v[0], v1=v[1], sum=0, i;           /* set up */uint32_t delta=0x9E3779B9;                     /* a key schedule constant */uint32_t 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;
}
代码解释(v1<<4)--->将v1的进制左移两位

用11001100举例解释

好的,我们将使用二进制数 11001100 作为例子来解释左移操作。这个二进制数是一个8位的数,其十进制值为204(如果你计算的话:1*2^7 + 1*2^6 + 0*2^5 + 0*2^4 + 1*2^3 + 1*2^2 + 0*2^1 + 0*2^0 = 128 + 64 + 0 + 0 + 8 + 4 + 0 + 0 = 204)。

原始二进制数

原始二进制数 x

11001100

左移2位操作

现在,我们要将这个数向左移动2位。左移操作意味着我们将所有位都向左移动指定的位数(在这个例子中是2位),并且在右侧新增相应数量的0来填补空位。最左边的位(在这个例子中是 11)将会超出边界并被丢弃。

左移2位后的结果:

(被丢弃的位)  |--|--  v  v

11|00110000| (同样,这里的空格是为了对齐,实际中并不存在)

去掉被丢弃的位和额外的空格后,我们得到:

100110000

但是,这里有一个问题:我们原始的二进制数是一个8位的数。当我们左移2位后,它实际上变成了一个9位的数。然而,在大多数计算机系统中,如果我们有一个8位的变量,并且我们尝试将一个9位的数存储到它里面,那么最高位(在这个例子中是最左边的 1)将会被丢弃,以符合8位的限制。

因此,如果我们是在一个8位的上下文中进行这个操作(比如,在一个8位的寄存器或变量中),那么结果应该是这样的:

00110000

这个二进制数转换为十进制是 48(0*2^7 + 0*2^6 + 1*2^5 + 1*2^4 + 0*2^3 + 0*2^2 + 0*2^1 + 0*2^0 = 0 + 0 + 32 + 16 + 0 + 0 + 0 + 0 = 48)。

结论

所以,当我们将二进制数 11001100 向左移动2位时,并且假设我们是在一个8位的上下文中进行这个操作,我们得到的结果是 00110000(十进制中的48)。这个操作相当于将原始的十进制数204除以4(因为我们是左移2位,相当于乘以2的-2次方,即除以4),并取结果的低8位(在这个例子中,结果本身就没有超过8位,所以直接就是48)。

TEA解密算法的实现

参数要求:输入一定要是一个64bit的数字,或者可以写作一个拥有两个元素的32bit的数组。并且需要一个两倍长度的key(int[4]),即一个128位的数字(拥有四个元素的32bit的数组)

//解密函数  
void decrypt (uint32_t* v, uint32_t* k) {  uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  /* set up */  uint32_t delta=0x9e3779b9;                     /* a key schedule constant */  uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];   /* cache key */  sum = delta << 5;   //32轮运算,所以是2的5次方;16轮运算,所以是2的4次方;8轮运算,所以是2的3次方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;  
} 

可能你和我一样,有点不太懂,但是这不是你放弃的理由,慢慢了解

我的理解就是加密就是一个算法,解密也就是逆过来,

k0与k2互换,v0与v1换,左移变成右移

TEA补充脚本
def encrypt(v, k):v0 = v[0]v1 = v[1]x = 0delta = 0x9E3779B9k0 = k[0]k1 = k[1]k2 = k[2]k3 = k[3]for i in range(32):x += deltax = x & 0xFFFFFFFFv0 += ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1)v0 = v0 & 0xFFFFFFFFv1 += ((v0 << 4) + k2) ^ (v0 + x) ^ ((v0 >> 5) + k3)v1 = v1 & 0xFFFFFFFFv[0] = v0v[1] = v1return v
def decrypt(v, k):v0 = v[0]v1 = v[1]x = 0xC6EF3720delta = 0x9E3779B9k0 = k[0]k1 = k[1]k2 = k[2]k3 = k[3]for i in range(32):v1 -= ((v0 << 4) + k2) ^ (v0 + x) ^ ((v0 >> 5) + k3)v1 = v1 & 0xFFFFFFFFv0 -= ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1)v0 = v0 & 0xFFFFFFFFx -= deltax = x & 0xFFFFFFFFv[0] = v0v[1] = v1return v
if __name__ == '__main__':plain = [1, 2]key = [2, 2, 3, 4]encrypted = encrypt(plain, key)print(encrypted)decrypted = decrypt(encrypted, key)print(decrypted)
"""
[1347371722, 925494771]
[1, 2]"""

实例

解密数组:{0x3e8947cb,0xcc944639,0x31358388,0x3b0b6893,0xda627361,0x3b2e6427}

key数组:{0x4445,0x4144,0x4245,0x4546}

因为在解密的过程之中会产生移位的运算,这个过程会产生溢出,所以每组解密的对象声明成 v1[3]={0x3e8947cb,0xcc944639,0x0} 这样的形式

#include <stdio.h>
#include <stdint.h>
void decrypt (uint32_t* v, uint32_t* k) {uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  /* set up */uint32_t delta=0x9e3779b9;                     /* a key schedule constant */uint32_t 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()
{uint32_t v1[3]={0x3e8947cb,0xcc944639,0x0},k[4]={0x4445,0x4144,0x4245,0x4546};uint32_t v2[3]={0x31358388,0x3b0b6893,0x0};uint32_t v3[3]={0xda627361,0x3b2e6427};decrypt(v1, k);decrypt(v2, k);decrypt(v3, k);printf("解密后的数据:%s %s %s\n",(char*)v1,(char*)v2,(char*)v3);   // 注意如何将一串数组以字符串的形式输出return 0;
}
//输出的结果:fvBXQdEa rcbvhBPx cOA8Ag6J

遇到新知识,学一下

代码解释_元组

元组(Tuple)是Python中的一种内置数据结构,用于存储一系列不可变(immutable)的元素。与列表(List)不同,元组一旦被创建,其内部的元素就不能被修改(即不能添加、删除或更改元素)。元组通常用于存储那些不应该被改变的数据集合,比如数据库查询的结果、函数的多个返回值等。

元组使用圆括号()来定义,元素之间用逗号,分隔。如果元组中只有一个元素,那么需要在该元素后面加上逗号,,以区分该元素和圆括号本身(后者在Python中通常用于分组或调用函数)。

示例

  • 定义一个简单的元组:
my_tuple = (1, 2, 3, 4, 5)
  • 定义一个只包含一个元素的元组(注意逗号):
single_element_tuple = (1,)
  • 访问元组中的元素:

元组中的元素可以通过索引来访问,索引从0开始。

print(my_tuple[0])  # 输出: 1  
print(my_tuple[-1]) # 输出: 5,使用负索引访问最后一个元素
  • 元组是不可变的:

尝试修改元组中的元素会引发TypeError

# 尝试修改元组中的元素  
my_tuple[0] = 10  # TypeError: 'tuple' object does not support item assignment
  • 元组的应用场景:
  • 作为字典的键(因为字典的键需要是不可变的)。
  • 存储函数的多个返回值(Python允许函数返回多个值,实际上是以元组的形式返回的)。
  • 在需要不可变序列的场合,比如作为集合(Set)的元素或另一个元组的元素。

元组由于其不可变性,在某些情况下比列表更加高效,因为Python解释器可以对它们进行更多的优化。然而,这也意味着在某些需要频繁修改数据的场合,使用列表可能更为合适。

我的理解就是用括号括起来的数组

二.XTEA加密解密

XTEA是TEA的升级版,增加了更多的密钥表,移位和异或操作

img

XTEA加密算法的实现

相较于TEA的变化:

  • 由之前的((v1<<4) + k0) ^ ((v1>>5) + k1) 变化成了 ((v1 << 4) ^ (v1 >> 5)) + v1),此时v1内部数据的加密变化不再受到密钥的影响。
  • 原先的v1 + sum变成了(sum + key[sum & 3])以及sum + key[(sum>>11) & 3],密钥变成了轮转使用,而不是固定只针对某种数据进行加密(解密)。并且此时密钥的选取受到sum的影响
  • sum += delta的时机由每次加密开头就发生变化到v0,v1两个block加密的中间

输入的参数:输入一定要是一个64bit的数字,或者可以写作一个拥有两个元素的32bit的数组。并且需要一个两倍长度的key(int[4]),即一个128位的数字(拥有四个元素的32bit的数组),注意这里循环的次数不是固定的了,是需要传入的参数num_rounds

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;  
} 

XTEA解密算法的实现

输入的参数:输入一定要是一个64bit的数字,或者可以写作一个拥有两个元素的32bit的数组。并且需要一个两倍长度的key(int[4]),即一个128位的数字(拥有四个元素的32bit的数组),注意这里循环的次数不是固定的了,是需要传入的参数num_rounds

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;  
}
XTEA补充脚本
def encrypt(rounds, v, k):v0 = v[0]v1 = v[1]x = 0delta = 0x9E3779B9for i in range(rounds):v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (x + k[x & 3])v0 = v0 & 0xFFFFFFFFx += deltax = x & 0xFFFFFFFFv1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (x + k[(x >> 11) & 3])v1 = v1 & 0xFFFFFFFFv[0] = v0v[1] = v1return v
def decrypt(rounds, v, k):v0 = v[0]v1 = v[1]delta = 0x9E3779B9x = delta * roundsfor i in range(rounds):v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (x + k[(x >> 11) & 3])v1 = v1 & 0xFFFFFFFFx -= deltax = x & 0xFFFFFFFFv0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (x + k[x & 3])v0 = v0 & 0xFFFFFFFFv[0] = v0v[1] = v1return v
if __name__ == '__main__':plain = [1, 2]key = [2, 2, 3, 4]rounds = 32encrypted = encrypt(rounds, plain, key)print(encrypted)decrypted = decrypt(rounds, encrypted, key)print(decrypted)
"""
[1345390024, 2801624574]
[1, 2]
"""

示例代码

#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[3]={0x73647979,0x726b6f5f,0x0};uint32_t v1[2]={0x646f675f,0x0};uint32_t const k[4]={0X95C4C,0X871D,0X1A7B7,0X12C7C7};unsigned int r=32;//num_rounds建议取值为32// v为要加密的数据是两个32位无符号整数// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位printf("加密前原始数据:%s%s\n",(char*)v,(char*)v1);encipher(r, v, k);encipher(r, v1, k);printf("加密后的数据:%u %u %u\n",v[0],v[1],v1[0]);decipher(r, v, k);decipher(r, v1, k);printf("解密后的数据:%s%s\n",(char*)v,(char*)v1);return 0;
}
/*
结果:
加密前原始数据:yyds_okr_god
加密后的数据:3461349474 1314311102 3609197830
解密后的数据:yyds_okr_god
*/

三.XXTEA加密解密

介绍

XTEA再度进化, 变成了支持块加密XXTEA

加密过程

img

XXTEA加密解密算法的实现

特点:在可变长度块上运行,这些块是32位大小的任意倍数(最小64位),使用128位密钥, 是目前TEA系列中最安全的算法,但性能较上两种有所降低。

参数:输入的是至少拥有两个元素的32bit的数组,密钥的长度仍然是128位,即拥有4个元素32位长度的数组

#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);  }  
}  
XXTEA补充脚本:
def shift(z, y, x, k, p, e):return ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((x ^ y) + (k[(p & 3) ^ e] ^ z)))
def encrypt(v, k):delta = 0x9E3779B9n = len(v)rounds = 6 + 52 // nx = 0z = v[n - 1]for i in range(rounds):x = (x + delta) & 0xFFFFFFFFe = (x >> 2) & 3for p in range(n - 1):y = v[p + 1]v[p] = (v[p] + shift(z, y, x, k, p, e)) & 0xFFFFFFFFz = v[p]p += 1y = v[0]v[n - 1] = (v[n - 1] + shift(z, y, x, k, p, e)) & 0xFFFFFFFFz = v[n - 1]return v
def decrypt(v, k):delta = 0x9E3779B9n = len(v)rounds = 6 + 52 // nx = (rounds * delta) & 0xFFFFFFFFy = v[0]for i in range(rounds):e = (x >> 2) & 3for p in range(n - 1, 0, -1):z = v[p - 1]v[p] = (v[p] - shift(z, y, x, k, p, e)) & 0xFFFFFFFFy = v[p]p -= 1z = v[n - 1]v[0] = (v[0] - shift(z, y, x, k, p, e)) & 0xFFFFFFFFy = v[0]x = (x - delta) & 0xFFFFFFFFreturn v
if __name__ == '__main__':plain = [1, 2]key = [2, 2, 3, 4]encrypted = encrypt(plain, key)print(encrypted)decrypted = decrypt(encrypted, key)print(decrypted)
"""
[3238569099, 2059193138]
[1, 2]
"""

示例代码

#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[4]= {0x73647979,0x726b6f5f,0x646f675f,0x0};uint32_t const k[4]= {0X95C4C,0X871D,0X1A7B7,0X12C7C7};int n= 2; //n的绝对值表示v的长度,取正表示加密,取负表示解密// v为要加密的数据是两个32位无符号整数// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位printf("加密前原始数据:%s\n",(char*)v);btea(v, n, k);printf("加密后的数据:%u %u %u\n",v[0],v[1],v[3]);btea(v, -n, k);printf("解密后的数据:%s\n",(char*)v);return 0;
}
输出结果:
加密前原始数据:yyds_okr_god
加密后的数据:609835868 2980644312 0
解密后的数据:yyds_okr_god

四.逆向中TEA系列加密的识别

解决逆向题大部分出现TEA的场合都是【识别算法->编写对应解密程序】

分析二进制文件中的算法的时候有几个识别的特征

  • 可能存在针对64bit以及128bit数字的操作(输入的msg和key) ,一般会用无符号的32位的数组表示
  • 存在先进行位移,然后异或的类似操作((z>>5^y<<2) 这类混合变换)(z>>5^y<<2)就是xxtea加密了,**
  • 存在(v0 << 4)** 和 (v0 >> 5)移位就是tea和xtea加密了
  • 前面一个复杂的混合变换的结果可能会叠加到另一个值上,两者相互叠加(Feistel 结构)
  • 获取密钥的时候,会使用某一个常量值作为下标(key[(sum>>11) & 3])存在轮换的方式获得密钥 就是xtea或者xxtea了
  • 会在算法开始定义一个delta,并且这个值不断的参与算法,但是从来不会受到输入的影响(delta数值如果没有魔改就是0x9e3779b9)
  • 如果出现了0x9e3779b9这个数字一般就能确定是TEA加密系列

五.解题实例

NSSCTF/算法识别/工坊第四题TEA

一个txt文件

hint1 = {11,22,33,44}
hint2 = {0x7c12e17f,0x43c2b691,0xa8d8d6ce,0x6280ecc8,0xe6e18c6e,0x20d6dfa3,0xf2dd40c,0xb819b77e,0xb9258436,0x5d3e88b6}
.text:0000000000401550                               ; unsigned int *__fastcall encrypt(unsigned int *, unsigned int *)
.text:0000000000401550                               public _Z7encryptPjS_
.text:0000000000401550                               _Z7encryptPjS_ proc near                ; CODE XREF: main+FC↓p
.text:0000000000401550                                                                       ; DATA XREF: .pdata:000000000040A06C↓o
.text:0000000000401550
.text:0000000000401550                               var_14= dword ptr -14h
.text:0000000000401550                               var_10= dword ptr -10h
.text:0000000000401550                               var_C= dword ptr -0Ch
.text:0000000000401550                               var_8= dword ptr -8
.text:0000000000401550                               var_4= dword ptr -4
.text:0000000000401550                               arg_0= qword ptr  10h
.text:0000000000401550                               arg_8= qword ptr  18h
.text:0000000000401550
.text:0000000000401550 55                            push    rbp
.text:0000000000401551 48 89 E5                      mov     rbp, rsp
.text:0000000000401554 48 83 EC 20                   sub     rsp, 20h
.text:0000000000401558 48 89 4D 10                   mov     [rbp+arg_0], rcx
.text:000000000040155C 48 89 55 18                   mov     [rbp+arg_8], rdx
.text:0000000000401560 C7 45 EC B9 79 37 9E          mov     [rbp+var_14], 9E3779B9h
.text:0000000000401567 48 8B 45 10                   mov     rax, [rbp+arg_0]
.text:000000000040156B 8B 00                         mov     eax, [rax]
.text:000000000040156D 89 45 FC                      mov     [rbp+var_4], eax
.text:0000000000401570 48 8B 45 10                   mov     rax, [rbp+arg_0]
.text:0000000000401574 8B 40 04                      mov     eax, [rax+4]
.text:0000000000401577 89 45 F8                      mov     [rbp+var_8], eax
.text:000000000040157A C7 45 F4 00 00 00 00          mov     [rbp+var_C], 0
.text:0000000000401581 C7 45 F0 00 00 00 00          mov     [rbp+var_10], 0
.text:0000000000401581
.text:0000000000401588
.text:0000000000401588                               loc_401588:                             ; CODE XREF: encrypt(uint *,uint *)+B2↓j
.text:0000000000401588 83 7D F0 1F                   cmp     [rbp+var_10], 1Fh
.text:000000000040158C 7F 76                         jg      short loc_401604
.text:000000000040158C
.text:000000000040158E 8B 45 EC                      mov     eax, [rbp+var_14]
.text:0000000000401591 01 45 F4                      add     [rbp+var_C], eax
.text:0000000000401594 8B 45 F8                      mov     eax, [rbp+var_8]
.text:0000000000401597 C1 E0 04                      shl     eax, 4
.text:000000000040159A 89 C2                         mov     edx, eax
.text:000000000040159C 48 8B 45 18                   mov     rax, [rbp+arg_8]
.text:00000000004015A0 8B 00                         mov     eax, [rax]
.text:00000000004015A2 01 C2                         add     edx, eax
.text:00000000004015A4 8B 4D F8                      mov     ecx, [rbp+var_8]
.text:00000000004015A7 8B 45 F4                      mov     eax, [rbp+var_C]
.text:00000000004015AA 01 C8                         add     eax, ecx
.text:00000000004015AC 31 C2                         xor     edx, eax
.text:00000000004015AE 8B 45 F8                      mov     eax, [rbp+var_8]
.text:00000000004015B1 C1 E8 05                      shr     eax, 5
.text:00000000004015B4 89 C1                         mov     ecx, eax
.text:00000000004015B6 48 8B 45 18                   mov     rax, [rbp+arg_8]
.text:00000000004015BA 48 83 C0 04                   add     rax, 4
.text:00000000004015BE 8B 00                         mov     eax, [rax]
.text:00000000004015C0 01 C8                         add     eax, ecx
.text:00000000004015C2 31 D0                         xor     eax, edx
.text:00000000004015C4 01 45 FC                      add     [rbp+var_4], eax
.text:00000000004015C7 8B 45 FC                      mov     eax, [rbp+var_4]
.text:00000000004015CA C1 E0 04                      shl     eax, 4
.text:00000000004015CD 89 C2                         mov     edx, eax
.text:00000000004015CF 48 8B 45 18                   mov     rax, [rbp+arg_8]
.text:00000000004015D3 48 83 C0 08                   add     rax, 8
.text:00000000004015D7 8B 00                         mov     eax, [rax]
.text:00000000004015D9 01 C2                         add     edx, eax
.text:00000000004015DB 8B 4D FC                      mov     ecx, [rbp+var_4]
.text:00000000004015DE 8B 45 F4                      mov     eax, [rbp+var_C]
.text:00000000004015E1 01 C8                         add     eax, ecx
.text:00000000004015E3 31 C2                         xor     edx, eax
.text:00000000004015E5 8B 45 FC                      mov     eax, [rbp+var_4]
.text:00000000004015E8 C1 E8 05                      shr     eax, 5
.text:00000000004015EB 89 C1                         mov     ecx, eax
.text:00000000004015ED 48 8B 45 18                   mov     rax, [rbp+arg_8]
.text:00000000004015F1 48 83 C0 0C                   add     rax, 0Ch
.text:00000000004015F5 8B 00                         mov     eax, [rax]
.text:00000000004015F7 01 C8                         add     eax, ecx
.text:00000000004015F9 31 D0                         xor     eax, edx
.text:00000000004015FB 01 45 F8                      add     [rbp+var_8], eax
.text:00000000004015FE 83 45 F0 01                   add     [rbp+var_10], 1
.text:0000000000401602 EB 84                         jmp     short loc_401588
.text:0000000000401602
.text:0000000000401604                               ; ---------------------------------------------------------------------------
.text:0000000000401604
.text:0000000000401604                               loc_401604:                             ; CODE XREF: encrypt(uint *,uint *)+3C↑j
.text:0000000000401604 48 8B 45 10                   mov     rax, [rbp+arg_0]
.text:0000000000401608 8B 55 FC                      mov     edx, [rbp+var_4]
.text:000000000040160B 89 10                         mov     [rax], edx
.text:000000000040160D 48 8B 45 10                   mov     rax, [rbp+arg_0]
.text:0000000000401611 48 83 C0 04                   add     rax, 4
.text:0000000000401615 8B 55 F8                      mov     edx, [rbp+var_8]
.text:0000000000401618 89 10                         mov     [rax], edx
.text:000000000040161A 90                            nop
.text:000000000040161B 48 83 C4 20                   add     rsp, 20h
.text:000000000040161F 5D                            pop     rbp
.text:0000000000401620 C3                            retn
.text:0000000000401620
.text:0000000000401620                               _Z7encryptPjS_ endp

识别为tea(通过hint1,有四个数字,

hint2有4x10=40位,大概的fllag的长度

逆向加密函数中有左移右移,四个异或,脚本直接解

出现9E3779B9h,大概是delta

#include<stdio.h>
#include <stdint.h>
#include<string.h>void encrypt(uint32_t *v, uint32_t *k) {uint32_t v0 = v[0], v1 = v[1], sum = 0, i;uint32_t delta = 0x9e3779b9;for (i = 0; i < 32; i++) {sum += delta;v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);}v[0] = v0; v[1] = v1;
}void decrypt(uint32_t *v, uint32_t *k) {uint32_t v0 = v[0], v1 = v[1], i;uint32_t delta = 0x9e3779b9;uint32_t sum = delta * 32;for (i = 0; i < 32; i++) {v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);sum -= delta;}v[0] = v0; v[1] = v1;
}int main() {// 提供的提示数组uint32_t key[4] = {11, 22, 33, 44};uint32_t v[10] = {0x7c12e17f, 0x43c2b691, 0xa8d8d6ce, 0x6280ecc8, 0xe6e18c6e, 0x20d6dfa3, 0xf2dd40c, 0xb819b77e, 0xb9258436, 0x5d3e88b6};uint32_t temp[2]; //定义存放解密后的值for(int i=0;i<10;i+=2)
{temp[0] = v[i];temp[1] = v[i+1];decrypt(temp, key);for(int j = 0; j < 2; j++){printf("%c", temp[j]&0xff);printf("%c", (temp[j]>>8)&0xff);printf("%c", (temp[j]>>16)&0xff);printf("%c", (temp[j]>>24)&0xff);}
}return 0;
}//NSSCTF{5b84a51236d7043fe2480d69d24b37a3} 

NSSCTF/算法识别/工坊第五题XXTEA

img

给了一个py文件和一个so文件,

from ctypes import c_uint32DELTA = 0x9E3779B9
def decrypt(v, n, k):rounds = 6 + int(52 / n)sum = c_uint32(rounds * DELTA)y = v[0].valuewhile rounds > 0:e = (sum.value >> 2) & 3p = n - 1while p > 0:z = v[p - 1].valuev[p].value -= (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))y = v[p].valuep -= 1z = v[n - 1].valuev[0].value -= (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum.value ^ y) + (k[(p & 3) ^ e] ^ z)))y = v[0].valuesum.value -= DELTArounds -= 1if __name__ == "__main__":k = [0x73645212, 0x31378432, 0x12325153, 0x34356531]m = [c_uint32(0xe034b77),c_uint32(0xfec9c3af),c_uint32(0x763b3820),c_uint32(0x8bdcc362),c_uint32(0xf443f322),c_uint32(0x6a0759bb),c_uint32(0x8d67f594),c_uint32(0x320282e4),c_uint32(0xef25b93c),c_uint32(0x4cad32cd)]decrypt(m, len(m), k)for i in m:for j in range(4):print(chr(i.value&0xff),end='')i.value >>= 8#NSSCTF{c166910265954e79448a6a1d80ea4bfb}

tea就先这样,再死啃就失去兴趣,现在多学一点基础知识,多了解一点,入门之后再慢慢来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/787606.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3 控制el-dialog 双向绑定显示隐藏

父组件<Contact v-model:isView="isView" /> 子组件<template><div><el-dialogwidth="400"title="微信二维码":model-value="props.isView"@closed="handleClose"><div class="dialog-div…

Typora使用PicGo自动上传图片

Gitee配置PicGo图床 简介 由于我们使用Markdown写博客时需要上传一些图片,以便于理解。但是md文件不像Word文件一样能承载图片传输,所以我们使用md文件进行多设备协作,或者传输发给其他人的时候,图片的传输成了很大的问题。一般情况下我们可以搭建一个文件服务器,但是这样…

【网络安全C10-2024.8.24】-docker、数据库、Web应用程序安全

1、在docker中分别以后台方式和交互方式启动centos,对比启动后的容器状态,实现退出容器也能保持其运行状态。docker run -d --name centos7-001 centos docker run -it --name centos7-002 centos /bin/bash docker run -d -t --name centos7-003 centos2、在docker并部署DVW…

网络安全C10-2024.8.24-docker、数据库、Web应用程序安全

docker run -d --name centos7-001 centos docker run -it --name centos7-002 centos /bin/bash docker run -d -t --name centos7-003 centos docker pull sagikazarmark/dvwa docker run -d -p 8082:80 -p 33060:3306 --name dvwa sagikazarmark/dvwa

CodeForces VP Record

CodeForces Round 767 (contest 1628) A Meximum Array 考虑二分。二分的时候计算区间 $ \text{mex} $,参考 P4137 Rmq Problem / mex,主席树即可。时间复杂度 $ \Theta(n \log^2 n) $,无需卡常。 B Peculiar Movie Preferences 首先,对于一个合法的回文串,容易证明首尾两…

数据库监控运维方案,保障高性能及高可用

通过构建对关键指标的监控,实现对数据库性能和资源的实时追踪,识别并解决影响的数据库问题,保障数据库的高性能及高可用性,更全面地支持业务及应用的稳定、持续运行。 随着企业对数据高可用的需求日益增长,对于数据库的实时监控和故障自动恢复方案愈发重要。作为关…

VL22 根据状态转移图实现时序电路

和上一题的第一段完全相同,第二段只是根据状态转移有部分改变,本体使用三段式状态机来写,第三段写法和上一题不一样。`timescale 1ns/1nsmodule seq_circuit(input C ,input clk ,input rst_n,output wire Y );…

Datawhale X 李宏毅苹果书 AI夏令营 深度学习01

神经网络的优化,通常我们使用梯度下降的方法对获取最优的参数,已达到优化神经网络的目的。另外,我们也可以对学习率进行调整,通过使用自适应学习率和学习率调度,最后,批量归一化改变误差表面,达到优化的目的。 同样,也会存在优化失败的时候,在收敛在局部极限值或者鞍点…

京东搜索重排:基于互信息的用户偏好导向模型

SIGIR 24: A Preference-oriented Diversity Model Based on Mutual-information in Re-ranking for E-commerce Search 链接:https://dl.acm.org/doi/abs/10.1145/3626772.3661359 摘要:重排是一种通过考虑商品之间的相互关系来重新排列商品顺序以更有效地满足用户需求的过…

探索AC自动机:多关键词搜索的原理与应用案例

引言 目前,大多数自由文本搜索技术采用类似于Lucene的策略,通过解析搜索文本为各个组成部分来定位关键词。这种方法在处理少量关键词时表现良好。但当搜索的关键词数量达到10万个或更多时,这种方法的效率会显著下降,尤其是在需要与词典进行详尽对比的场景中。本文将介绍的A…