首页
社区
课程
招聘
1
[原创]看雪.京东 2018CTF-第七题分析
发表于: 2018-6-29 18:25 2825

[原创]看雪.京东 2018CTF-第七题分析

2018-6-29 18:25
2825
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
int check()
{
  signed int v0; // ebx
  signed int index; // esi
  signed int i; // eax
  int v3; // eax
  char *v4; // ecx
  signed int v5; // edi
  char *pkey3CharBuf; // eax
  int v7; // esi
  int v8; // ecx
  int v9; // ecx
  int v10; // ecx
  signed int v11; // eax
  char *v13; // [esp+Ch] [ebp-258h]
  int cnt; // [esp+10h] [ebp-254h]
  int v15; // [esp+14h] [ebp-250h]
  char key3CharBuf[3]; // [esp+18h] [ebp-24Ch]
  int v17; // [esp+1Ch] [ebp-248h]
  char inputIndexKey[20][16]; // [esp+20h] [ebp-244h]
  char table[256]; // [esp+160h] [ebp-104h]
 
  v0 = 0;
  *(_DWORD *)table = 65793;
  *(_DWORD *)&table[4] = 0;
  *(_DWORD *)&table[8] = 0;
  *(_DWORD *)&table[12] = 0;
  *(_DWORD *)&table[16] = 16777217;
  *(_DWORD *)&table[20] = 1;
  *(_DWORD *)&table[24] = 0;
  *(_DWORD *)&table[28] = 0;
  *(_DWORD *)&table[32] = 1;
  *(_DWORD *)&table[36] = 65792;
  *(_DWORD *)&table[40] = 0;
  *(_DWORD *)&table[44] = 0;
  *(_DWORD *)&table[48] = 256;
  *(_DWORD *)&table[52] = 16777472;
  *(_DWORD *)&table[56] = 0;
  *(_DWORD *)&table[60] = 0;
  *(_DWORD *)&table[64] = 256;
  *(_DWORD *)&table[68] = 65537;
  *(_DWORD *)&table[72] = 0;
  *(_DWORD *)&table[76] = 0;
  *(_DWORD *)&table[80] = 16842752;
  *(_DWORD *)&table[84] = 0;
  *(_DWORD *)&table[88] = 1;
  *(_DWORD *)&table[92] = 0;
  *(_DWORD *)&table[96] = 0x10000;
  *(_DWORD *)&table[100] = 1;
  *(_DWORD *)&table[104] = 256;
  *(_DWORD *)&table[108] = 0;
  *(_DWORD *)&table[112] = 0x1000000;
  *(_DWORD *)&table[116] = 0x1000000;
  *(_DWORD *)&table[120] = 0x10000;
  *(_DWORD *)&table[124] = 0;
  *(_DWORD *)&table[128] = 0;
  *(_DWORD *)&table[132] = 256;
  *(_DWORD *)&table[136] = 1;
  *(_DWORD *)&table[140] = 1;
  *(_DWORD *)&table[144] = 0;
  *(_DWORD *)&table[148] = 0x10000;
  *(_DWORD *)&table[152] = 0x1000000;
  *(_DWORD *)&table[156] = 256;
  *(_DWORD *)&table[160] = 0;
  *(_DWORD *)&table[164] = 0x1000000;
  *(_DWORD *)&table[168] = 0;
  *(_DWORD *)&table[172] = 257;
  *(_DWORD *)&table[176] = 0;
  *(_DWORD *)&table[180] = 0;
  *(_DWORD *)&table[184] = 16777472;
  *(_DWORD *)&table[188] = 0x10000;
  *(_DWORD *)&table[192] = 0;
  *(_DWORD *)&table[196] = 0;
  *(_DWORD *)&table[200] = 65537;
  *(_DWORD *)&table[204] = 0x10000;
  *(_DWORD *)&table[208] = 0;
  *(_DWORD *)&table[212] = 0;
  *(_DWORD *)&table[216] = 65792;
  *(_DWORD *)&table[220] = 0x1000000;
  *(_DWORD *)&table[224] = 0;
  *(_DWORD *)&table[228] = 0;
  *(_DWORD *)&table[232] = 0x1000000;
  *(_DWORD *)&table[236] = 16777217;
  *(_DWORD *)&table[240] = 0;
  *(_DWORD *)&table[244] = 0;
  *(_DWORD *)&table[248] = 0;
  *(_DWORD *)&table[252] = 16843008;
  index = 0;
  do
  {
    for ( i = 0; ; ++i )
    {
      if ( i >= 64 )
      {
        printf("input error\n");
        system("PAUSE");
        exit(-1);
      }
      if ( byte_40DA68[i] == (unsigned __int8)g_inputKey[index] )
        break;
    }
    inputIndexKey[0][index++] = i;
  }
  while ( index < 16 );
  printf("\n");
  v3 = 0x10;
  v17 = 0x10;
  v15 = 2 - (_DWORD)inputIndexKey[1];
  do
  {
    v4 = (char *)inputIndexKey + v3;
    v13 = (char *)inputIndexKey + v3;
    v5 = 0;
    do
    {
      pkey3CharBuf = key3CharBuf;
      v7 = (int)&v4[v15];
      cnt = 4;
      do
      {
        v8 = (v7 - 2) % 16;
        if ( table[v5 + v8] )
          *pkey3CharBuf++ = *((_BYTE *)&cnt + v8 + v17);
        v9 = (v7 - 1) % 16;
        if ( table[v5 + v9] )
          *pkey3CharBuf++ = *((_BYTE *)&cnt + v9 + v17);
        if ( table[v5 + v7 % 16] )
          *pkey3CharBuf++ = *((_BYTE *)&cnt + v7 % 16 + v17);
        v10 = (v7 + 1) % 16;
        if ( table[v5 + v10] )
          *pkey3CharBuf++ = *((_BYTE *)&cnt + v10 + v17);
        v7 += 4;
        --cnt;
      }
      while ( cnt );
      *v13 = byte_40FEF0[64 * ((unsigned __int8)key3CharBuf[1] + ((unsigned __int8)key3CharBuf[0] << 6))
                       + (unsigned __int8)key3CharBuf[2]];
      v5 += 16;
      v4 = v13++ + 1;
    }
    while ( v5 < 0x100 );
    v15 -= 16;
    v3 = v17 + 16;
    v17 = v3;
  }
  while ( v3 < 320 );
  v11 = 0;
  do
  {
    if ( (unsigned __int8)inputIndexKey[0x13][v11] != byte_40FEE0[v11] )
      return printf("serial error\n");
    ++v11;
  }
  while ( v11 < 16 );
  do
    printf("%c", (unsigned __int8)byte_40DA68[(unsigned int)(unsigned __int8)inputIndexKey[9][v0++] >> 1]);
  while ( v0 < 16 );
  return printf("\n");
}
       
1、初始化了一个16*16的数组 table:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
          2、从"abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"查找输入kjey,并替换成对应字符所在的位置索引。
          2、从"abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"查找输入kjey,并替换成对应字符所在的位置索引。
        可以把输入16个字符变换后的数据比作16把钥匙,并将其存储在第0层房间inputIndexKey[0]中。而最内层循环的作用是根据变量索引index,获取与下层index相关的本层的三把钥匙,而本层具体三把钥匙与下层相关是由前面定义的talbe(16*16)来决定的。观察talbe,可以看到当前层的16把钥匙中的有且仅有3把钥匙与下层的某个钥匙相关。通过最内层循环索引 talbe后得到3把钥匙,放到key3CharBuf[中],而下层的钥匙数值value为:
 value = key3CharBuf[0]*64*64 + key3CharBuf [1]*64 + key3CharBuf[0]。然后索引g_constKey[64][64][64]常量表, 因此取索引对应的数值作为下层相应的钥匙。 g_constKey存储的数据范围为:(0~63)。
 6、中间层循环
        使index数值从0 开始依次循环16次,从而获得下层的所有16把钥匙,才可以到最外层循环,进入到下一层。需要注意的是:
        当进行索引第i把钥匙,首先要确定索引 table的位置,即为table[i][i]开始,比如:
 value = key3CharBuf[0]*64*64 + key3CharBuf [1]*64 + key3CharBuf[0]。然后索引g_constKey[64][64][64]常量表, 因此取索引对应的数值作为下层相应的钥匙。 g_constKey存储的数据范围为:(0~63)。
 value = key3CharBuf[0]*64*64 + key3CharBuf [1]*64 + key3CharBuf[0]。然后索引g_constKey[64][64][64]常量表, 因此取索引对应的数值作为下层相应的钥匙。 g_constKey存储的数据范围为:(0~63)。
 6、中间层循环
        使index数值从0 开始依次循环16次,从而获得下层的所有16把钥匙,才可以到最外层循环,进入到下一层。需要注意的是:
        当进行索引第i把钥匙,首先要确定索引 table的位置,即为table[i][i]开始,比如:
        索引第0把钥匙,则取 table[0][0] ~ table[0][15]
        索引第1把钥匙,则取 table[1][1] ~table[1][15]、 table[1][0]
        索引第0把钥匙,则取 table[0][0] ~ table[0][15]
        索引第1把钥匙,则取 table[1][1] ~table[1][15]、 table[1][0]
       通过分析中间层循环不难得出下一层钥匙与本次钥匙的关系,假如当前层是a,其16把钥匙为 a0-a15, 下一层为b,其16把钥匙为b0-b15:    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
b0        =      g_constKey[ a0*64*64               +             a1*64               +                a2]
b1        =      g_constKey[ a3*64*64               +             a4*64               +                a0] 
b2        =      g_constKey[ a5*64*64               +             a6*64               +                a0]  
b3        =      g_constKey[ a5*64*64               +             a7*64               +                a1]
b4        =      g_constKey[ a4*64*64               +             a6*64               +                a1] 
b5        =      g_constKey[ a8*64*64               +             a2*64               +                a3]       
b6        =      g_constKey[ a9*64*64               +             a8*64               +                a4] 
b7        =      g_constKey[ a7*64*64               +             a10*64              +                a3] 
b8        =      g_constKey[ a8*64*64               +             a12*64              +                a5] 
b9        =      g_constKey[ a11*64*64              +             a13*64              +                a6]
b10       =      g_constKey[ a12*64*64              +             a13*64              +                a7]
b11       =      g_constKey[ a11*64*64              +             a14*64              +                a9]
b12       =      g_constKey[ a14*64*64              +             a8*64               +                a10]
b13       =      g_constKey[ a15*64*64              +             a9*64               +                a10]
b14       =      g_constKey[ a15*64*64              +             a11*64              +                a12]
b15       =      g_constKey[ a15*64*64              +             a13*64              +                a14]  
7、最外层循环
         获得下层所有钥匙后,就可以开启下层的门锁,从而进入下一层,依次循环一共循环20次。
8、第20次循环的钥匙即: inputIndexKey [19]与全局变量byte_40DA68[16]必须相等,如果不同则返回失败,如果相同,则输入第9层相关信息,成功。
二、算法分析
        现在我们需要做的是,根据最后一层的钥匙,来逆推前一层的钥匙,一直到第0层,从而拿到key。可以利用本层与下层的钥匙关系,进行暴力穷举,是可以获得最原始的初始钥匙,获得key大概需要4个小时。下面是个优化的算法,大概需要3-5分钟获得原始钥匙。
         已知本层所有钥匙,来获得上一层的所有钥匙:
         存在16把钥匙,就是存在16个方程,通过遍历 g_constKey 表,可知每个方程共有4096个解。假定本层第0把钥匙对应的上层3把钥匙a0, a1,a2确定,则可知本层第1、2、3、4、5、6把钥匙都分别有64个解。然后再以第1把钥匙为基础,遍历其64中可能,通过各钥匙之间的关系,可知其中每一种可能都可以锁定剩余11把钥匙的可能性。以次为基础,开始依次遍历校验,先获取16把钥匙每把的可能4096个解,然后循环4096*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
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#include "stdafx.h"
#include <windows.h>     
extern char g_constKey[0x40000];
extern unsigned char g_indexKey[0x100];
typedef struct {
    unsigned char x;
    unsigned char y;
    unsigned char z;
}result;
typedef struct nextRest{
    unsigned char m;
    unsigned char n;
}nextRest;
typedef struct nextRestInfo{
    int count;
    nextRest result[640];
}nextRestInfo;
typedef struct {
    //0--a0,a1,a2
    //1--a3,a4,a0
    result r[16][40960];
}allResult;
unsigned char arm[16] = { 0x14, 0x22, 0x1E, 0x10, 0x38, 0x30, 0x18, 0x10, 0x04, 0x1A, 0x24, 0x08, 0x02, 0x26, 0x38, 0x2A };
char srt[] = "abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
unsigned char newArm[16];
nextRestInfo nr56;
nextRestInfo nr34;
nextRestInfo nr57;
nextRestInfo nr46;
nextRestInfo nr83;
nextRestInfo nr94;
allResult allr;
bool getmnResult(nextRestInfo* nr, unsigned char a, int index, int xyz)
{
    int count = 0;
    for (int i = 0; i < 4096; i++)
    {
        if (1 == xyz)
        {
            if (allr.r[index][i].x == a)
            {
                nr->result[count].m = allr.r[index][i].y;
                nr->result[count].n = allr.r[index][i].z;
                if (count < 64)
                    count++;
                else
                {
                    printf("ERROR:   count > 64");
                    return false;
                }
            }
        }
        if (2 == xyz)
        {
            if (allr.r[index][i].y == a)
            {
                nr->result[count].m = allr.r[index][i].x;
                nr->result[count].n = allr.r[index][i].z;
                if (count < 64)
                    count++;
                else
                {
                    printf("ERROR:   count > 64");
                    return false;
                }
            }
        }
        if (3 == xyz)
        {
            if (allr.r[index][i].z == a)
            {
                nr->result[count].m = allr.r[index][i].x;
                nr->result[count].n = allr.r[index][i].y;
                if (count < 64)
                {
                    count++;
                }
                else
                {
                    printf("ERROR:   count > 64");
                    return false;
                }
            }  
        }
    }
    return true;
}
 
unsigned char geta7Bya5(unsigned char a5)
{
    for (int i = 0; i < 64; i++)
    {
        if (nr57.result[i].m == a5)
            return nr57.result[i].n;
    }
    return 0xff;
}
unsigned char geta4Bya6(unsigned char a6)
{
    for (int i = 0; i < 64; i++)
    {
        if (nr46.result[i].n == a6)
            return nr46.result[i].m;
    }
    return 0xff;
}
unsigned char geta3Bya4(unsigned char a4)
{
    for (int i = 0; i < 64; i++)
    {
        if (nr34.result[i].n== a4)
            return nr34.result[i].m;
    }
    return 0xff;
}
unsigned char geta8Bya3(unsigned char a3)
{
    for (int i = 0; i < 64; i++)
    {
        if (nr83.result[i].n == a3)
            return nr34.result[i].m;
    }
    return 0xff;
}
unsigned char geta9Bya4(unsigned char a4)
{
    for (int i = 0; i < 64; i++)
    {
        if (nr94.result[i].n == a4)
            return nr94.result[i].m;
    }
    return 0xff;
}
unsigned char geta10Bya7a3()
{
    for (int i = 0; i < 4096; i++)
    {
        if (allr.r[7][i].x == newArm[7] && allr.r[7][i].z == newArm[3])
            return allr.r[7][i].y;
    }
    return 0xff;
}
unsigned char geta12Bya8a5()
{
    for (int i = 0; i < 4096; i++)
    {
        if (allr.r[8][i].x == newArm[8] && allr.r[8][i].z == newArm[5])
            return allr.r[8][i].y;
    }
    return 0xff;
}
unsigned char geta13Bya11a6()
{
    for (int i = 0; i < 4096; i++)
    {
        if (allr.r[9][i].x == newArm[11] && allr.r[9][i].z == newArm[6])
            return allr.r[9][i].y;
    }
    return 0xff;
}
unsigned char geta14Bya8a10()
{
    for (int i = 0; i < 4096; i++)
    {
        if (allr.r[12][i].y == newArm[8] && allr.r[12][i].z == newArm[10])
            return allr.r[12][i].x;
    }
    return 0xff;
}
unsigned char geta11Bya14a9()
{
    for (int i = 0; i < 4096; i++)
    {
        if (allr.r[11][i].y == newArm[14] && allr.r[11][i].z == newArm[9])
            return allr.r[11][i].x;
    }
    return 0xff;
}
unsigned char geta15Bya9a10()
{
    for (int i = 0; i < 4096; i++)
    {
        if (allr.r[13][i].y == newArm[9] && allr.r[13][i].z == newArm[10])
            return allr.r[13][i].x;
    }
    return 0xff;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int count = 0;
    unsigned char block = 0;
    unsigned char  hh = 0;
    unsigned char ll = 0;
    int binggo = 0;
     
    printf("开始遍历: \r\n");
    for (int loop = 0; loop < 19; loop++)
    {
        //获取16组解
        for (int k = 0; k <16 ; k++)
        {
            int count = 0;
            for (int i = 0; i < 0x40000; i++)
            {
                if (g_constKey[i] == arm[k])
                {
                    block = i / (64 * 64);
                    hh = (i % (64 * 64)) / 64;
                    ll = i - block*(4 * 16 * 64) - 64 * hh;
                    allr.r[k][count].x = block;
                    allr.r[k][count].y = hh;
                    allr.r[k][count].z = ll;
                    count++;
                }
            }
        }
        for (int indexa1a2a3 = 0; indexa1a2a3 < 4096; indexa1a2a3++)
        {
            newArm[0] = allr.r[0][indexa1a2a3].x;
            newArm[1] = allr.r[0][indexa1a2a3].y;
            newArm[2] = allr.r[0][indexa1a2a3].z;
            //根据a0获得a3,a4可能解集合
            //m=x,n=y
            getmnResult(&nr34, newArm[0],1,3);
            getmnResult(&nr56, newArm[0],2,3);
            getmnResult(&nr57, newArm[1],3,3);
            getmnResult(&nr46, newArm[1],4,3);
            getmnResult(&nr83, newArm[2],5,2);
            getmnResult(&nr94, newArm[2],6,2);
            for (int mnIndex = 0; mnIndex < 64; mnIndex++)
            {
                newArm[5] = nr56.result[mnIndex].m;
                newArm[6] = nr56.result[mnIndex].n;
                newArm[7] = geta7Bya5(newArm[5]);
                newArm[4] = geta4Bya6(newArm[6]);
                newArm[3] = geta3Bya4(newArm[4]);
                newArm[8] = geta8Bya3(newArm[3]);
                newArm[9] = geta9Bya4(newArm[4]);
                newArm[10] = geta10Bya7a3();
                newArm[12] = geta12Bya8a5();
                newArm[14] = geta14Bya8a10();
                newArm[11] = geta11Bya14a9();
                newArm[13] = geta13Bya11a6();
                newArm[15] = geta15Bya9a10();        
                if (g_constKey[64 * 64 * newArm[0] + 64 * newArm[1] + newArm[2]] != arm[0])continue;
                if (g_constKey[64 * 64 * newArm[3] + 64 * newArm[4] + newArm[0]] != arm[1])continue;
                if (g_constKey[64 * 64 * newArm[5] + 64 * newArm[6] + newArm[0]] != arm[2])continue;
                if (g_constKey[64 * 64 * newArm[5] + 64 * newArm[7] + newArm[1]] != arm[3])continue;
                if (g_constKey[64 * 64 * newArm[4] + 64 * newArm[6] + newArm[1]] != arm[4])continue;
                if (g_constKey[64 * 64 * newArm[8] + 64 * newArm[2] + newArm[3]] != arm[5])continue;
                if (g_constKey[64 * 64 * newArm[9] + 64 * newArm[2] + newArm[4]] != arm[6])continue;
                if (g_constKey[64 * 64 * newArm[7] + 64 * newArm[10] + newArm[3]] != arm[7])continue;
                if (g_constKey[64 * 64 * newArm[8] + 64 * newArm[12] + newArm[5]] != arm[8])continue;
                if (g_constKey[64 * 64 * newArm[11] + 64 * newArm[13] + newArm[6]] != arm[9])continue;
                if (g_constKey[64 * 64 * newArm[12] + 64 * newArm[13] + newArm[7]] != arm[10])continue;
                if (g_constKey[64 * 64 * newArm[11] + 64 * newArm[14] + newArm[9]] != arm[11])continue;
                if (g_constKey[64 * 64 * newArm[14] + 64 * newArm[8] + newArm[10]] != arm[12])continue;
                if (g_constKey[64 * 64 * newArm[15] + 64 * newArm[9] + newArm[10]] != arm[13]) continue;
                if (g_constKey[64 * 64 * newArm[15] + 64 * newArm[11] + newArm[12]] != arm[14]) continue;
                if (g_constKey[64 * 64 * newArm[15] + 64 * newArm[13] + newArm[14]] != arm[15]) continue;
 
                //获得结果
                binggo++;
                printf("倒数第%2d轮: ", 19-loop);
                for (int c = 0; c < 16; c++)
                    printf("0x%02x ", newArm[c]);
                printf("\r\n");
                memcpy(arm, newArm, 16);
                break;
            }
        }
    }
    printf("\n遍历完成:sn = ");
    for (int i = 0; i < 16; i++)
    {
        arm[i] = srt[arm[i]];
        printf("%c", arm[i]);
    }
    return 0;
}
 运行结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
开始遍历:
倒数第19轮: 0x0f 0x0b 0x07 0x0b 0x35 0x03 0x19 0x1f 0x0b 0x31 0x3b 0x33 0x03 0x07 0x15 0x37
倒数第18轮: 0x3a 0x26 0x00 0x3a 0x34 0x06 0x2c 0x3c 0x0e 0x1e 0x0a 0x26 0x24 0x18 0x3c 0x18
倒数第17轮: 0x0f 0x07 0x0d 0x15 0x23 0x3f 0x3f 0x19 0x11 0x0d 0x03 0x25 0x37 0x3b 0x19 0x31
倒数第16轮: 0x0c 0x36 0x16 0x06 0x06 0x26 0x04 0x2e 0x0c 0x0c 0x3a 0x10 0x10 0x16 0x36 0x22
倒数第15轮: 0x0f 0x1f 0x33 0x0d 0x2b 0x2b 0x19 0x19 0x3f 0x33 0x35 0x2d 0x27 0x1b 0x11 0x07
倒数第14轮: 0x3a 0x12 0x3c 0x0e 0x2c 0x3c 0x2e 0x08 0x1e 0x22 0x3c 0x12 0x26 0x18 0x0e 0x0e
倒数第13轮: 0x19 0x2f 0x03 0x29 0x15 0x03 0x11 0x29 0x15 0x3f 0x33 0x09 0x1f 0x1d 0x23 0x33
倒数第12轮: 0x38 0x1e 0x38 0x2a 0x0e 0x16 0x1e 0x2a 0x16 0x2c 0x1a 0x1e 0x3e 0x10 0x08 0x28
倒数第11轮: 0x27 0x3d 0x25 0x3f 0x2d 0x29 0x19 0x21 0x27 0x39 0x33 0x05 0x17 0x13 0x0d 0x15
倒数第10轮: 0x30 0x1c 0x28 0x22 0x24 0x08 0x22 0x10 0x00 0x16 0x10 0x24 0x0c 0x1c 0x1c 0x06
倒数第 9轮: 0x25 0x05 0x1f 0x2d 0x27 0x33 0x19 0x0b 0x01 0x0d 0x21 0x31 0x15 0x31 0x3b 0x17
倒数第 8轮: 0x16 0x2e 0x36 0x10 0x08 0x28 0x02 0x20 0x06 0x00 0x28 0x0e 0x14 0x0a 0x04 0x22
倒数第 7轮: 0x35 0x2d 0x31 0x17 0x3b 0x1d 0x29 0x03 0x21 0x0b 0x0b 0x3f 0x05 0x31 0x11 0x1d
倒数第 6轮: 0x3e 0x0a 0x2a 0x02 0x2a 0x08 0x24 0x1e 0x1e 0x3a 0x38 0x1e 0x2c 0x2a 0x1c 0x3c
倒数第 5轮: 0x13 0x01 0x27 0x39 0x2f 0x25 0x1b 0x09 0x2d 0x13 0x11 0x1d 0x31 0x0b 0x37 0x17
倒数第 4轮: 0x2e 0x22 0x24 0x0e 0x2a 0x36 0x00 0x0e 0x34 0x2a 0x32 0x00 0x14 0x20 0x14 0x08
倒数第 3轮: 0x21 0x1f 0x17 0x03 0x27 0x2b 0x29 0x01 0x15 0x1f 0x1b 0x05 0x25 0x39 0x35 0x23
倒数第 2轮: 0x20 0x30 0x32 0x16 0x32 0x12 0x06 0x32 0x3c 0x1a 0x16 0x18 0x30 0x22 0x24 0x1e
倒数第 1轮: 0x11 0x2b 0x21 0x05 0x3f 0x01 0x25 0x0b 0x39 0x13 0x33 0x09 0x3f 0x39 0x35 0x25
 
遍历完成:sn = rPFf9bJl3tXj93ZJ
sn 为 “rPFf9bJl3tXj93ZJ”
      
       通过分析中间层循环不难得出下一层钥匙与本次钥匙的关系,假如当前层是a,其16把钥匙为 a0-a15, 下一层为b,其16把钥匙为b0-b15:    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
b0        =      g_constKey[ a0*64*64               +             a1*64               +                a2]
b1        =      g_constKey[ a3*64*64               +             a4*64               +                a0] 
b2        =      g_constKey[ a5*64*64               +             a6*64               +                a0]  
b3        =      g_constKey[ a5*64*64               +             a7*64               +                a1]
b4        =      g_constKey[ a4*64*64               +             a6*64               +                a1] 
b5        =      g_constKey[ a8*64*64               +             a2*64               +                a3]       
b6        =      g_constKey[ a9*64*64               +             a8*64               +                a4] 
b7        =      g_constKey[ a7*64*64               +             a10*64              +                a3] 
b8        =      g_constKey[ a8*64*64               +             a12*64              +                a5] 
b9        =      g_constKey[ a11*64*64              +             a13*64              +                a6]
b10       =      g_constKey[ a12*64*64              +             a13*64              +                a7]
b11       =      g_constKey[ a11*64*64              +             a14*64              +                a9]
b12       =      g_constKey[ a14*64*64              +             a8*64               +                a10]
b13       =      g_constKey[ a15*64*64              +             a9*64               +                a10]
b14       =      g_constKey[ a15*64*64              +             a11*64              +                a12]
b15       =      g_constKey[ a15*64*64              +             a13*64              +                a14]  
7、最外层循环
         获得下层所有钥匙后,就可以开启下层的门锁,从而进入下一层,依次循环一共循环20次。
8、第20次循环的钥匙即: inputIndexKey [19]与全局变量byte_40DA68[16]必须相等,如果不同则返回失败,如果相同,则输入第9层相关信息,成功。
二、算法分析
        现在我们需要做的是,根据最后一层的钥匙,来逆推前一层的钥匙,一直到第0层,从而拿到key。可以利用本层与下层的钥匙关系,进行暴力穷举,是可以获得最原始的初始钥匙,获得key大概需要4个小时。下面是个优化的算法,大概需要3-5分钟获得原始钥匙。
         已知本层所有钥匙,来获得上一层的所有钥匙:
         存在16把钥匙,就是存在16个方程,通过遍历 g_constKey 表,可知每个方程共有4096个解。假定本层第0把钥匙对应的上层3把钥匙a0, a1,a2确定,则可知本层第1、2、3、4、5、6把钥匙都分别有64个解。然后再以第1把钥匙为基础,遍历其64中可能,通过各钥匙之间的关系,可知其中每一种可能都可以锁定剩余11把钥匙的可能性。以次为基础,开始依次遍历校验,先获取16把钥匙每把的可能4096个解,然后循环4096*64次即可碰撞出上一层所有钥匙。


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

最后于 2018-6-30 14:04 被oooAooo编辑 ,原因:
收藏
免费 1
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2023-2-4 02:44
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册