-
-
[原创] 京东-看雪-2018 春季赛 第七题 密室逃脱
-
发表于: 2018-6-29 11:17 3092
-
拿到的是一个 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
运行结果
Only 'a'-'z','A'-'Z','0'-'9' accepted. Only 16 chars accepted. Serial:zzzzzzzzzzzzzzzz serial error
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; }
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;
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 );
abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课