首页
社区
课程
招聘
2
[原创] 京东-看雪-2018 春季赛 第七题 密室逃脱
发表于: 2018-6-29 11:17 3212

[原创] 京东-看雪-2018 春季赛 第七题 密室逃脱

aqs 活跃值
5
2018-6-29 11:17
3212

拿到的是一个 win32 程序,跑一下看看

serial 是16byte 长度的字符串,根据题目描述,每个byte对应一个初始密钥
看一下程序逻辑

逻辑不复杂,前面output 一些信息,输入 序列号,然后进入main_logic 函数,main_logic 函数只有一层实现,下面分段看一下

首先会写入一个 16x16 的表
在内存中是这个样子的

这个表在后面会用到,主要是用来确定操作的index 的
先看一下后面的逻辑

首先根据输入的每个byte在一个 table 中找到对应的 index

后面对 变换之后的 index table 进行加密

代码被自己改的有点难看,大概逻辑是:

这么说有点模糊,调试一下,在 0x0401287 这里下个断点,ecx -0x10 就是 table 的位置

这里传入的是 abcdefghijklmnop , 可以看到 index 变换之后变成了 index 0-0xf
接下来在0x0401393, 也就是获取到下一个table 的一个byte回填的时候

找到 三个参数

可以发现是 0 1 2,结合前面的 16x16 的表来看 index 是符合的
但是顺序没搞清楚是怎么变换的,只有 16 个byte,调试看看就行,得到的每次 变换的 三个参数是 对应的 index 是

变换 之后将最后得到的密钥和 一个固定的串进行比较

如果一致就过,还会根据 变换得到的 19 个加密串中间的一个来生成一段字符串
到了这里,整理一下

一开始想到的是 有没有可能反向解密回去回去,但是发现用于变换的table 是 64x64x64 大小的,要变换回去感觉很难, 情况会有很多种
想了很久,后面发现,如果多加密几轮的话就有可能重新得到原来的输入
这就简单了,将 最后密钥多加密几轮,找到重新得到最后密钥的地方,就可以知道他是怎么来的了, 写了一个脚本测试了一下

多循环几次,grep 一下,可以看到重复了,找到重复位置的前19 个密钥,变换一下就可以得到 serial

运行结果

1
2
3
4
5
Only 'a'-'z','A'-'Z','0'-'9' accepted.
Only 16 chars accepted.
Serial:zzzzzzzzzzzzzzzz
 
serial error
1
2
3
4
5
6
7
8
9
10
int __cdecl main(int argc, const char **argv, const char **envp)
{
  printf("Only 'a'-'z','A'-'Z','0'-'9' accepted.\n");
  printf("Only 16 chars accepted.\n");
  printf("Serial:");
  scanf_s("%s", input_450B80, 17);
  main_logic_401050();
  system("PAUSE");
  return 0;
}
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
helpset[0] = 0x10101;
helpset[1] = 0;
helpset[2] = 0;
helpset[3] = 0;
helpset[4] = 0x1000001;
helpset[5] = 1;
helpset[6] = 0;
helpset[7] = 0;
helpset[8] = 1;
helpset[9] = 0x10100;
helpset[10] = 0;
helpset[11] = 0;
helpset[12] = 0x100;
helpset[13] = 0x1000100;
helpset[14] = 0;
helpset[15] = 0;
helpset[16] = 0x100;
helpset[17] = 0x10001;
helpset[18] = 0;
helpset[19] = 0;
helpset[20] = 0x1010000;
helpset[21] = 0;
helpset[22] = 1;
helpset[23] = 0;
helpset[24] = 0x10000;
helpset[25] = 1;
helpset[26] = 256;
helpset[27] = 0;
helpset[28] = 0x1000000;
helpset[29] = 0x1000000;
helpset[30] = 0x10000;
helpset[31] = 0;
helpset[32] = 0;
helpset[33] = 256;
helpset[34] = 1;
helpset[35] = 1;
helpset[36] = 0;
helpset[37] = 0x10000;
helpset[38] = 0x1000000;
helpset[39] = 256;
helpset[40] = 0;
helpset[41] = 0x1000000;
helpset[42] = 0;
helpset[43] = 257;
helpset[44] = 0;
helpset[45] = 0;
helpset[46] = 16777472;
helpset[47] = 0x10000;
helpset[48] = 0;
helpset[49] = 0;
helpset[50] = 65537;
helpset[51] = 0x10000;
helpset[52] = 0;
helpset[53] = 0;
helpset[54] = 65792;
helpset[55] = 0x1000000;
helpset[56] = 0;
helpset[57] = 0;
helpset[58] = 0x1000000;
helpset[59] = 16777217;
helpset[60] = 0;
helpset[61] = 0;
helpset[62] = 0;
helpset[63] = 16843008;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
do
 {                                             // 找到每个key 对应的 index
   for ( offset = 0; ; ++offset )
   {
     if ( offset >= 64 )
     {                                        
       printf("input error\n");
       system("PAUSE");
       exit(-1);
     }
     if ( serial_set_40DA68[offset] == (unsigned __int8)input_450B80[index] )
       break;
   }                                           // 找到每个byte 对应的 offset
   input_index[index++] = offset;            
 }
 while ( index < 16 );
1
abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

[注意]看雪招聘,专注安全领域的专业人才平台!

最后于 2018-6-29 15:37 被aqs编辑 ,原因:
上传的附件:
收藏
免费 2
支持
分享
赞赏记录
参与人
雪币
留言
时间
PLEBFE
为你点赞~
2022-7-27 02:00
心游尘世外
为你点赞~
2022-7-27 00:04
最新回复 (0)
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

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