首页
社区
课程
招聘
[原创]2021强网杯Reverse-LongTimeAgo
2021-6-18 14:33 15090

[原创]2021强网杯Reverse-LongTimeAgo

2021-6-18 14:33
15090

LongTimeAgo

一:patch花指令

拖入IDA之后发现有花指令,逐个patch太慢,以便之后我们多次调试,写一个IDAPython的脚本来批量patch,不然IDA每次重新调试我们都要重新patch一次

1
2
3
4
5
6
7
8
9
10
11
12
addr = 0x4A2A0C
for i in range(2):
    ida_bytes.patch_byte((addr+i), 0x90)
add_arr = [0x00000000004A2A4B, 0x00000000004A2ABC, 0x00000000004A2AC1, 0x00000000004A2B4A,
0x0000000000402F89]
for i in range(len(add_arr)):
    for j in range(5):
        ida_bytes.patch_byte((add_arr[i]+j), 0x90)
add_arr1 = [0x00000000004A2ABC]
for i in range(len(add_arr)):
    for j in range(4):
        ida_bytes.patch_byte((add_arr1[i]+j), 0x90)

patch之后反编译,才能正确看到main函数

二:逐渐调试并分析逻辑

main函数如下:

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
126
127
128
129
130
131
132
133
134
135
136
137
138
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *v3; // rdx
  int v4; // ecx
  unsigned int v5; // eax
  char *input_1; // r15
  char *v8; // rdi
  int *cmp_addr; // r12
  char *cmp_dest; // r14
  int *input_dest; // rbx
  int *v12; // r13
  int hex_data; // eax
  __int64 tmp; // rax
  int data_len; // edx
  int v16; // eax
  __int64 cmp_data_len; // rax
  int cmp_data_len_1; // edx
  int v19; // ecx
  int v20; // eax
  __int64 v21; // rax
  char v22; // dl
  char input[80]; // [rsp+30h] [rbp-3F8h] BYREF
  int input_dest_1[18]; // [rsp+80h] [rbp-3A8h] BYREF
  int v25[18]; // [rsp+C8h] [rbp-360h] BYREF
  int v26[18]; // [rsp+110h] [rbp-318h] BYREF
  int v27[18]; // [rsp+158h] [rbp-2D0h] BYREF
  int key[9]; // [rsp+1A0h] [rbp-288h] BYREF
  int v29; // [rsp+1C4h] [rbp-264h] BYREF
  __int64 v30; // [rsp+1E8h] [rbp-240h] BYREF
  int v31; // [rsp+20Ch] [rbp-21Ch] BYREF
  char v32[360]; // [rsp+2C0h] [rbp-168h] BYREF
 
  sub_40CC40(argc, argv, envp);
  memset(input, 0, sizeof(input));
  std::operator<<<std::char_traits<char>>((std::ostream *)off_4A68E0, "Input Your Key:");
  std::operator>><char,std::char_traits<char>>((std::istream *)&addr, input);
  v3 = input;
  do
  {
    v4 = *(_DWORD *)v3;
    v3 += 4;
    v5 = ~v4 & (v4 - 0x1010101) & 0x80808080;
  }
  while ( !v5 );
  if ( (~v4 & (v4 - 0x1010101) & 0x8080) == 0 )
    v5 >>= 16;
  if ( (~v4 & (v4 - 0x1010101) & 0x8080) == 0 )
    v3 += 2;
  if ( &v3[-__CFADD__((_BYTE)v5, (_BYTE)v5) - 3] - input == 64 )// strlen() == 64
  {
    input_1 = input;
    v8 = v32;
    cmp_addr = &cmp_data;
    cmp_dest = v32;
    std::operator<<<std::char_traits<char>>((std::ostream *)off_4A68E0, "Are You Sure You Want To Keep Waiting...\n");
    input_dest = input_dest_1;
    v12 = input_dest_1;
    do
    {
      hex_data = take_eight_to_hex(input_1, 8); // 8个字节当作16进制数据
      *((_BYTE *)input_dest + 8) = 0;
      input_dest[1] = hex_data;
      tmp = 4i64;                               // 判断总共有多少个有效16进制数据
      while ( 1 )
      {
        data_len = tmp;
        if ( *((_BYTE *)input_dest + tmp + 3) )
          break;
        if ( !--tmp )
        {
          data_len = 0;
          break;
        }
      }
      *input_dest = data_len;
      v16 = *cmp_addr;
      cmp_dest[8] = 0;
      *((_DWORD *)cmp_dest + 1) = v16;
      cmp_data_len = 4i64;
      while ( 1 )
      {
        cmp_data_len_1 = cmp_data_len;
        if ( cmp_dest[cmp_data_len + 3] )
          break;
        if ( !--cmp_data_len )
        {
          cmp_data_len_1 = 0;
          break;
        }
      }
      input_1 += 8;                             // 输入字符串的地址偏移8字节
      *(_DWORD *)cmp_dest = cmp_data_len_1;
      input_dest += 9;
      cmp_dest += 36;
      ++cmp_addr;
    }
    while ( input_1 != &input[64] );            // 循环8次,将对应数据按格式存储
    create((__int64)key, 13i64);
    create((__int64)&v29, 14i64);
    create((__int64)&v30, 15i64);
    create((__int64)&v31, 16i64);               // 根据第二个参数传入的值,生成一个数并判断其hex共多少字节
                                                // 传入13,14,15,16生成对应的四个key
    xtea(input_dest_1, key);
    xtea(v25, key);
    tea(v26, key);
    tea(v27, key);
    v19 = 0;
    while ( 1 )
    {
      v20 = *v12;
      if ( *v12 != *(_DWORD *)v8 )
        break;
      if ( v20 - 1 >= 0 )
      {
        if ( v32[36 * v19 - 573 + v20] != v32[36 * v19 + 3 + v20] )
          break;
        v21 = v20 - 2;
        while ( (int)v21 >= 0 )
        {
          v22 = *((_BYTE *)v12 + v21-- + 4);
          if ( v22 != v8[v21 + 5] )
            goto LABEL_8;
        }
      }
      ++v19;
      v12 += 9;
      v8 += 36;
      if ( v19 == 8 )
      {
        printf_0("QWB{%s}\n", input);
        return 0;
      }
    }
  }
LABEL_8:
  printf_0("sorry\n");
  return 0;
}

逐段进行分析:

第一段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sub_40CC40(argc, argv, envp);
memset(input, 0, sizeof(input));
std::operator<<<std::char_traits<char>>((std::ostream *)off_4A68E0, "Input Your Key:");
std::operator>><char,std::char_traits<char>>((std::istream *)&addr, input);
v3 = input;
do
{
  v4 = *(_DWORD *)v3;
  v3 += 4;
  v5 = ~v4 & (v4 - 0x1010101) & 0x80808080;
}
while ( !v5 );
if ( (~v4 & (v4 - 0x1010101) & 0x8080) == 0 )
  v5 >>= 16;
if ( (~v4 & (v4 - 0x1010101) & 0x8080) == 0 )
  v3 += 2;
if ( &v3[-__CFADD__((_BYTE)v5, (_BYTE)v5) - 3] - input == 64 )// strlen() == 64

输入之后并判断长度是否为64

第二段

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
input_1 = input;
v8 = v32;
cmp_addr = &cmp_data;
cmp_dest = v32;
std::operator<<<std::char_traits<char>>((std::ostream *)off_4A68E0, "Are You Sure You Want To Keep Waiting...\n");
input_dest = input_dest_1;
v12 = input_dest_1;
do
{
  hex_data = take_eight_to_hex(input_1, 8); // 8个字节当作16进制数据
  *((_BYTE *)input_dest + 8) = 0;
  input_dest[1] = hex_data;
  tmp = 4i64;                               // 判断总共有多少个有效16进制数据
  while ( 1 )
  {
    data_len = tmp;
    if ( *((_BYTE *)input_dest + tmp + 3) )
      break;
    if ( !--tmp )
    {
      data_len = 0;
      break;
    }
  }
  *input_dest = data_len;
  v16 = *cmp_addr;
  cmp_dest[8] = 0;
  *((_DWORD *)cmp_dest + 1) = v16;
  cmp_data_len = 4i64;
  while ( 1 )
  {
    cmp_data_len_1 = cmp_data_len;
    if ( cmp_dest[cmp_data_len + 3] )
      break;
    if ( !--cmp_data_len )
    {
      cmp_data_len_1 = 0;
      break;
    }
  }
  input_1 += 8;                             // 输入字符串的地址偏移8字节
  *(_DWORD *)cmp_dest = cmp_data_len_1;
  input_dest += 36;
  cmp_dest += 36;
  ++cmp_addr;
}
while ( input_1 != &input[64] );            // 循环8次,将对应数据按格式存储

take_eight_to_hex函数的意思就是:比如我输入的是1111111122222222.....等64个字节,那么逐渐循环take_eight_to_hex取出来的就是0x11111111,0x22222222,.......(自己调试一下就可以发现)

 

然后这种小循环,是判断有多少个有效16进制字节的,比如0x123456,返回的就是3,0x11111111,返回的就是4

1
2
3
4
5
6
7
8
9
10
11
12
13
tmp = 4i64;                               // 判断总共有多少个有效16进制数据
      while ( 1 )
      {
        data_len = tmp;
        if ( *((_BYTE *)input_dest + tmp + 3) )
          break;
        if ( !--tmp )
        {
          data_len = 0;
          break;
        }
      }
      *input_dest = data_len;

下方对那个已知的数组(就是比较数据)
图片描述

 

进行相同的储存方式

1
2
data_len
data

存一个地址就偏移36字节,貌似是一个类似对象,结构体的东西

 

调试一下,每次循环都查看cmp_dest 和input_dest 就可以知道

第三段

1
2
3
4
5
create((__int64)key, 13i64);
create((__int64)&v29, 14i64);
create((__int64)&v30, 15i64);
create((__int64)&v31, 16i64);               // 根据第二个参数传入的值,生成一个数并判断其hex共多少字节
                                            // 传入13,14,15,16生成对应的四个key

实际上就是生成key并判断生成的数据的长度,和前面是相同的储存方式

1
2
part_key_len
key

其实对于生成key的函数,就是create里面的一个函数:

 

图片描述

 

每次调试,修改传入的a2参数,然后查看返回的v3的值,猜测规律

 

我的猜测过程:
图片描述

 

得到这个函数功能:

1
(((1 << (i-1)) - 1) << 4)+13

第四段

1
2
3
4
xtea(input_dest_1, key);
xtea(v25, key);
tea(v26, key);
tea(v27, key);

加密的函数,4个部分,前两个进行xtea加密,后两个进行tea加密

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
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
sum = 0;
  do
  {
    left((__int64)v71, &v1, 4);
    right(v72, &v1, 5i64);
    xor(v73, v71, v72);
    add(v74, v73, &v1);                         // (((v1 << 4) ^ (v1 >> 5)) + v1)
    v57 = 0;
    v14 = 4i64;
    v56 = sum;
    while ( 1 )
    {
      v15 = v14;
      if ( *((_BYTE *)&sum_1 + v14 + 3) )
        break;
      if ( !--v14 )
      {
        v15 = 0;
        break;
      }
    }
    sum_1 = v15;
    v16 = sum & 3;
    sum -= 0x70C88617;
    add(v75, &sum_1, &key_1[9 * v16]);          // sum + key[sum & 3]
    xor(v76, v74, v75);                         // (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3])
    add(&v0, &v0, v76);                         // v0 +=
    left((__int64)v77, &v0, 4);
    right(v78, &v0, 5i64);
    xor(v79, v77, v78);
    add(v80, v79, &v0);                         // (((v0 << 4) ^ (v0 >> 5)) + v0)
    v57 = 0;
    v17 = 4i64;
    v56 = sum;
    while ( 1 )
    {
      v18 = v17;
      if ( *((_BYTE *)&sum_1 + v17 + 3) )
        break;
      if ( !--v17 )
      {
        v18 = 0;
        break;
      }
    }
    sum_1 = v18;
    add(xor_data1_1, &sum_1, &key_1[9 * ((sum >> 11) & 3)]);// (sum + key[(sum>>11) & 3])
    xor(xor_data2_1, v80, xor_data1_1);         // (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3])
    add(&v1, &v1, xor_data2_1);                 // v1 +=
  }
  while ( sum != 0xE6EF3D20 );
  xor_data1 = fun(3, 5);
  v82 = 0;
  xor_data1_1[1] = xor_data1;
  v20 = 4i64;
  while ( 1 )
  {
    v21 = v20;
    if ( *((_BYTE *)xor_data1_1 + v20 + 3) )
      break;
    if ( !--v20 )
    {
      v21 = 0;
      break;
    }
  }
  xor_data1_1[0] = v21;
  xor(&v0, &v0, xor_data1_1);                   // 注意最后还加了一步异或
  v22 = v0;                                     // v0 = v0 ^ fun(5)
  if ( v0 > 32 )
  {
    *a1 = 32;
    v22 = 32i64;
LABEL_108:
    *(_QWORD *)((char *)v50 + v22 - 8) = *(_QWORD *)((char *)&v52[-2] + v22);
    v45 = v22 - 1;
    if ( v45 >= 8 )
    {
      v46 = v45 & 0xFFFFFFFFFFFFFFF8ui64;
      v47 = 0i64;
      do
      {
        *(_QWORD *)&v50[v47 / 4] = *(_QWORD *)&v52[v47 / 4];
        v47 += 8i64;
      }
      while ( v47 < v46 );
    }
    goto LABEL_66;
  }
  *a1 = v0;
  if ( v22 >= 8 )
    goto LABEL_108;
  if ( (v22 & 4) != 0 )
  {
    a1[1] = v52[0];
    *(int *)((char *)v50 + v22 - 4) = *(_DWORD *)((char *)&v52[-1] + v22);
  }
  else if ( v22 )
  {
    *((_BYTE *)a1 + 4) = v52[0];
    if ( (v22 & 2) != 0 )
      *(_WORD *)((char *)v50 + v22 - 2) = *(_WORD *)((char *)&v0 + v22 + 2);
  }
LABEL_66:
  xor_data2 = fun(3, 6);
  v84 = 0;
  xor_data2_1[1] = xor_data2;
  v24 = 4i64;
  while ( 1 )
  {
    v25 = v24;
    if ( *((_BYTE *)xor_data2_1 + v24 + 3) )
      break;
    if ( !--v24 )
    {
      v25 = 0;
      break;
    }
  }
  xor_data2_1[0] = v25;
  xor(&v1, &v1, xor_data2_1);                   // v1 = v1 ^ xor_data2

写出xtea_encrypt函数:

1
2
3
4
5
6
7
8
9
10
11
12
void xtea_encrypt(uint32_t v[2], uint32_t const key[4])
{
    uint32_t v0=v[0], v1=v[1], delta=0x70C88617, sum=0;
    while(sum != 0xE6EF3D20)                                 //轮数发生了改变
    {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
    }
    v0 = v0 ^ fun(5);
    v1 = v1 ^ fun(6);     //在后面添加了异或
}

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
v13 = 32;
  do
  {
    add(sum, sum, delta);                       // sum += delta
    left((__int64)v65, &v1, 4);
    add(v65, v65, &key0);                       // ((v1<<4) + k0)
    add(v66, &v1, sum);                         // (v1 + sum)
    right(v67, &v1, 5i64);
    add(v67, v67, &key1);                       // ((v1>>5) + k1)
    xor(v65, v65, v66);
    xor(v65, v65, v67);                         // ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1)
    add(&v0, &v0, v65);                         // v0 +=
    left((__int64)v68, &v0, 4);
    add(v68, v68, &v61);
    add(xor_data3_1, &v0, sum);
    right(xor_data4_1, &v0, 5i64);
    add(xor_data4_1, xor_data4_1, &v63);
    xor(v68, v68, xor_data3_1);
    xor(v68, v68, xor_data4_1);                 // ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3)
    add(&v1, &v1, v68);                         // v1 +=
    --v13;
  }
  while ( v13 );
  xor_data3 = fun(3, 7);
  v70 = 0;
  xor_data3_1[1] = xor_data3;
  v15 = 4i64;
  while ( 1 )
  {
    v16 = v15;
    if ( *((_BYTE *)xor_data3_1 + v15 + 3) )
      break;
    if ( !--v15 )
    {
      v16 = 0;
      break;
    }
  }
  xor_data3_1[0] = v16;
  xor(&v0, &v0, xor_data3_1);                   // v0 = v0 ^ xor_data3
  v17 = v0;
  if ( v0 > 32 )
  {
    *a1 = 32;
    v17 = 32i64;
LABEL_94:
    *(_QWORD *)((char *)v45 + v17 - 8) = *(_QWORD *)((char *)&v47[-2] + v17);
    v40 = v17 - 1;
    if ( v40 >= 8 )
    {
      v41 = v40 & 0xFFFFFFFFFFFFFFF8ui64;
      v42 = 0i64;
      do
      {
        *(_QWORD *)&v45[v42 / 4] = *(_QWORD *)&v47[v42 / 4];
        v42 += 8i64;
      }
      while ( v42 < v41 );
    }
    goto LABEL_55;
  }
  *a1 = v0;
  if ( v17 >= 8 )
    goto LABEL_94;
  if ( (v17 & 4) != 0 )
  {
    a1[1] = v47[0];
    *(int *)((char *)v45 + v17 - 4) = *(_DWORD *)((char *)&v47[-1] + v17);
  }
  else if ( v17 )
  {
    *((_BYTE *)a1 + 4) = v47[0];
    if ( (v17 & 2) != 0 )
      *(_WORD *)((char *)v45 + v17 - 2) = *(_WORD *)((char *)&v0 + v17 + 2);
  }
LABEL_55:
  xor_data4 = fun(3, 8);
  v72 = 0;
  xor_data4_1[1] = xor_data4;
  v19 = 4i64;
  while ( 1 )
  {
    v20 = v19;
    if ( *((_BYTE *)xor_data4_1 + v19 + 3) )
      break;
    if ( !--v19 )
    {
      v20 = 0;
      break;
    }
  }
  xor_data4_1[0] = v20;
  xor(&v1, &v1, xor_data4_1);                   // v1 = v1 ^ xor_data4

写出tea_encrypt函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void tea_encrypt(uint32_t* v, uint32_t* k)
{
    uint32_t v0=v[0], v1=v[1], sum=0, i;
    uint32_t delta=0x3d3529bc;           //异或得到的delta
    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 ^ fun(7);
    v[1]=v1 ^ fun(8);
}

这里吐槽一句,不知道题目的author是使用了什么库?左移右移加法异或这些都是小函数,得自己看

第五段

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
while ( 1 )
    {
      v20 = *v12;
      if ( *v12 != *(_DWORD *)v8 )
        break;
      if ( v20 - 1 >= 0 )
      {
        if ( v32[36 * v19 - 573 + v20] != v32[36 * v19 + 3 + v20] )
          break;
        v21 = v20 - 2;
        while ( (int)v21 >= 0 )
        {
          v22 = *((_BYTE *)v12 + v21-- + 4);
          if ( v22 != v8[v21 + 5] )
            goto LABEL_8;
        }
      }
      ++v19;
      v12 += 9;
      v8 += 36;
      if ( v19 == 8 )
      {
        printf_0("QWB{%s}\n", input);
        return 0;
      }
    }
  }
LABEL_8:
  printf_0("sorry\n");
  return 0;
}

这里就是和比较数据进行比较

三:decrypt

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
#include <stdio.h>
#include <stdint.h>
#include <windows.h>
 
int fun(int i)         //我们推导出来的那个函数
{
    return (((1 << (i-1)) - 1) << 4)+13;
}
 
void xtea_encrypt(uint32_t v[2], uint32_t const key[4])
{
    uint32_t v0=v[0], v1=v[1], delta=0x70C88617, sum=0;
    while(sum != 0xE6EF3D20)                                 //轮数发生了改变
    {
        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 ^ fun(5);
    v[1] = v1 ^ fun(6);     //在后面添加了异或
}
 
void xtea_decrypt(uint32_t v[2], uint32_t const key[4]) {
    uint32_t v0=v[0] ^ fun(5);
    uint32_t v1=v[1] ^ fun(6);
    uint32_t delta=0x70C88617, sum=0xE6EF3D20;
    while(sum != 0)
    {
        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;
}
 
void tea_encrypt(uint32_t* v, uint32_t* k)
{
    uint32_t v0=v[0], v1=v[1], sum=0, i;
    uint32_t delta=0x3d3529bc;           //异或得到的delta
    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 ^ fun(7);
    v[1]=v1 ^ fun(8);
}
 
void tea_decrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0] ^ fun(7);
    uint32_t v1=v[1] ^ fun(8);
    uint32_t sum=0xa6a53780, i;
    uint32_t delta=0x3d3529bc;
    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()
{
    int i = 0;
    uint32_t v[8] = {0x1F306772, 0xB75B0C29, 0x4A7CDBE3, 0x2877BDDF,0x1354C485, 0x357C3C3A, 0x738AF06C, 0x89B7F537};
    uint32_t k[4]={0, 0, 0, 0};
    k[0] = fun(13);
    k[1] = fun(14);
    k[2] = fun(15);
    k[3] = fun(16);       //根据传入的参数是13,14,15,16,调用函数得到key
    //下面进行批量解密
    uint32_t temp[2];
    printf("QWB{");
    for(i=0;i<4;i+=2)
    {
        temp[0] = v[i];
        temp[1] = v[i+1];
        xtea_decrypt(temp, k);
        printf("%08X%08X",temp[0], temp[1]);      //注意必须大写
    }
    for(i=4;i<8;i+=2)
    {
        temp[0] = v[i];
        temp[1] = v[i+1];
        tea_decrypt(temp, k);
        printf("%08X%08X",temp[0], temp[1]);      //注意必须大写
    }
    printf("}");
    system("pause");
    return 0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-6-23 16:22 被SYJ-Re编辑 ,原因:
上传的附件:
收藏
点赞5
打赏
分享
最新回复 (5)
雪    币: 12
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
大史 4.0 2021-6-23 11:05
2
0
19、20行是不是应该是v[0] = v0 ^ fun(5);    v[1] = v1 ^ fun(6);     //在后面添加了异或
雪    币: 3656
活跃值: (9205)
能力值: ( LV9,RANK:319 )
在线值:
发帖
回帖
粉丝
SYJ-Re 3 2021-6-23 16:22
3
0
感谢提醒,由于加密步骤解密并没有用到,下次注意
雪    币: 11
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
robotrsp 2021-7-2 17:17
4
0
感谢分享
雪    币: 39
活跃值: (139)
能力值: ( LV3,RANK:38 )
在线值:
发帖
回帖
粉丝
cuannuo 2021-7-3 15:09
5
0
解题的话第30行感觉应该是加,题目里面的sum运算和标准的是相反的
雪    币: 3656
活跃值: (9205)
能力值: ( LV9,RANK:319 )
在线值:
发帖
回帖
粉丝
SYJ-Re 3 2021-7-16 23:15
6
0
不知为何这道与津门杯的GoodRE很相似 
游客
登录 | 注册 方可回帖
返回