这个迷宫题目还是挺有意思的,后来发现可以多解碰撞crc,就觉得更有意思了
这个程序有tls和几处anti,还是要稍微小心一点
401660 CheckRemoteDebuggerPresent
4015E0 NtQueryInformationProcess
401710 GetThreadContext 检查drx之和
401690 setjmp3/SetUnhandledExceptionFilter
输入处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | .text:004B5370 sub eax, 004BA040h //"6GxRI4XlsLDQoVfb7pgE8hcYHaUtWZwKBPyNvuCSF3d0e2JA9q5jrTMOzknim1"
.text:004B5375 test al, al
.text:004B5377 mov [ebp+ebx+var_264], al //base64 decode
...
.text:004B539E sub eax, 12h //前18个字符
.text:004B53A1 cmp eax, 5Dh //后93个字符
.text:004B53A4 ja loc_4B55EC //输入总长度不超过112
...
.text:004B53AA lea ecx, [ebp+var_1E4]
.text:004B53B0 mov [ebp+var_298], 1
.text:004B53BA call sub_4017A0 //初始化迷宫数据
.text:004B53BF lea eax, [ebp+var_25B]
.text:004B53C5 lea ecx, [ebp+var_1E4]
.text:004B53CB mov [esp+2C8h+var_2C4], eax
.text:004B53CF lea eax, [ebp+var_264]
.text:004B53D5 mov [esp+2C8h+var_2C8], eax
.text:004B53D8 call sub_401BD0 //初始化几个大数,主要的是把输入的前18个字符拆分成两个大数x,y,还有一个固定的常数z
|
加密的迷宫初始数据,四个关卡,每关地图大小是6x5:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | .text:004B5370 sub eax, 004BA040h //"6GxRI4XlsLDQoVfb7pgE8hcYHaUtWZwKBPyNvuCSF3d0e2JA9q5jrTMOzknim1"
.text:004B5375 test al, al
.text:004B5377 mov [ebp+ebx+var_264], al //base64 decode
...
.text:004B539E sub eax, 12h //前18个字符
.text:004B53A1 cmp eax, 5Dh //后93个字符
.text:004B53A4 ja loc_4B55EC //输入总长度不超过112
...
.text:004B53AA lea ecx, [ebp+var_1E4]
.text:004B53B0 mov [ebp+var_298], 1
.text:004B53BA call sub_4017A0 //初始化迷宫数据
.text:004B53BF lea eax, [ebp+var_25B]
.text:004B53C5 lea ecx, [ebp+var_1E4]
.text:004B53CB mov [esp+2C8h+var_2C4], eax
.text:004B53CF lea eax, [ebp+var_264]
.text:004B53D5 mov [esp+2C8h+var_2C8], eax
.text:004B53D8 call sub_401BD0 //初始化几个大数,主要的是把输入的前18个字符拆分成两个大数x,y,还有一个固定的常数z
|
加密的迷宫初始数据,四个关卡,每关地图大小是6x5:
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 | 02 13 00 00 07
07 04 05 0B 0A
09 08 0E 0E 0C
0C 12 13 11 01
36 16 15 15 1B
2B 19 18 1E 1C
1E 1D 32 23 20
20 27 26 24 24
2B 3B 29 29 2F
2F 2D 2C 33 32
31 30 37 36 34
34 2A 3B 39 3A
3C 2F 1C 3C 43
43 40 40 47 77
44 44 4B 4A 49
49 4F 4E 4D 4C
53 43 50 50 56
47 54 55 5B 58
5A 58 5F 5E 6C
4D 63 73 61 60
66 66 64 65 6A
6A 69 68 7E 6E
6D 6C 72 72 71
41 76 76 75 76
|
几个关键函数:
sub_401DE0 会被多处调用的函数,调试分析得知是个寻路判断函数,返回值表示两个点之间是可到达,同时也可看到迷宫数据解密算法,算法比较简单xor个密钥再xor个索引序号
先用初始迷宫密钥3解密出明文迷宫数据,方便后面描述:
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 | 02 13 00 00 07
07 04 05 0B 0A
09 08 0E 0E 0C
0C 12 13 11 01
36 16 15 15 1B
2B 19 18 1E 1C
1E 1D 32 23 20
20 27 26 24 24
2B 3B 29 29 2F
2F 2D 2C 33 32
31 30 37 36 34
34 2A 3B 39 3A
3C 2F 1C 3C 43
43 40 40 47 77
44 44 4B 4A 49
49 4F 4E 4D 4C
53 43 50 50 56
47 54 55 5B 58
5A 58 5F 5E 6C
4D 63 73 61 60
66 66 64 65 6A
6A 69 68 7E 6E
6D 6C 72 72 71
41 76 76 75 76
|
几个关键函数:
sub_401DE0 会被多处调用的函数,调试分析得知是个寻路判断函数,返回值表示两个点之间是可到达,同时也可看到迷宫数据解密算法,算法比较简单xor个密钥再xor个索引序号
先用初始迷宫密钥3解密出明文迷宫数据,方便后面描述:
几个关键函数:
sub_401DE0 会被多处调用的函数,调试分析得知是个寻路判断函数,返回值表示两个点之间是可到达,同时也可看到迷宫数据解密算法,算法比较简单xor个密钥再xor个索引序号
先用初始迷宫密钥3解密出明文迷宫数据,方便后面描述:
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 | 01 11 01 00 00
01 01 01 00 00
00 00 01 00 01
00 01 01 00 11
21 00 00 01 00
31 00 00 01 02
03 01 11 01 01
00 00 00 01 00
00 11 00 01 00
01 00 00 00 00
00 00 00 00 01
00 11 01 00 02
03 11 21 00 00
01 01 00 00 31
01 00 00 00 00
01 00 00 00 00
00 11 01 00 01
11 01 01 00 02
03 00 00 00 31
11 00 11 00 00
01 00 01 01 01
00 00 00 11 00
00 00 01 00 00
31 01 00 00 02
|
从上面寻路判断函数中可以分析出:地图中的数值低4位是1表示该点可走,如果是0且下一层是1x表示空洞下面被垫高了也可同样可走
sub_402460 走到指定位置,如遇到道具会自动拾取,0x31道具可以改变密钥
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 | 01 11 01 00 00
01 01 01 00 00
00 00 01 00 01
00 01 01 00 11
21 00 00 01 00
31 00 00 01 02
03 01 11 01 01
00 00 00 01 00
00 11 00 01 00
01 00 00 00 00
00 00 00 00 01
00 11 01 00 02
03 11 21 00 00
01 01 00 00 31
01 00 00 00 00
01 00 00 00 00
00 11 01 00 01
11 01 01 00 02
03 00 00 00 31
11 00 11 00 00
01 00 01 01 01
00 00 00 11 00
00 00 01 00 00
31 01 00 00 02
|
从上面寻路判断函数中可以分析出:地图中的数值低4位是1表示该点可走,如果是0且下一层是1x表示空洞下面被垫高了也可同样可走
sub_402460 走到指定位置,如遇到道具会自动拾取,0x31道具可以改变密钥
从上面寻路判断函数中可以分析出:地图中的数值低4位是1表示该点可走,如果是0且下一层是1x表示空洞下面被垫高了也可同样可走
sub_402460 走到指定位置,如遇到道具会自动拾取,0x31道具可以改变密钥
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 | sub_402460()
{
...
if ( (v10 & 0xF) == 1 )
{
*((_DWORD *)v2 + 2) = x;
*((_DWORD *)v2 + 3) = y;
if ( (signed int)v10 >> 4 == 3 ) //0x31类型道具
{
v23[20] = v19 ^ (v22 + y) ^ ((v22 + y) ^ v9) & 0xF;
v12 = *((_DWORD *)v2 + 0x65) == 1;
*((_DWORD *)v2 + 4) = 3 * ((*((_DWORD *)v2 + 4) + 2) >> 1); //w = (w+2)/2*3,w初始值是3,经过3次迭代会等于十进制的33
if ( v12 && v19 == 3 )
{
v2[0x198] = 0x37; //第一次拾取0x31道具,修改迷宫密钥为k = 0x37
v13 = 0x37;
}
else
{
sub_401AB0(v2 + 0x110, v2 + 0x110, v2 + 0x8C); //大数乘法 a *= x
sub_401AB0(v2 + 0x13C, v2 + 0x13C, v2 + 0xB8); //大数乘法 b *= y
sub_401AB0(v2 + 0x168, v2 + 0x168, v2 + 0xE4); //大数乘法 c *= z
sub_4019F0(v2 + 0x194, v2 + 0x110, v2 + 0x13C, v2 + 0x168); //修改密钥 k = a - b - c
v13 = v2[0x198];
}
//变更密钥后,需要对数据用新密钥重新加密
v14 = v2 + 0x32;
v15 = v2 + 0xAA;
v16 = v13 ^ v19;
do
{
v17 = v14 - 30;
do
{
v18 = (int)(v17 + 5);
do
*v17++ ^= v16;
while ( v17 != (_BYTE *)v18 );
}
while ( v17 != v14 );
v14 += 30;
}
while ( v14 != v15 );
}
}
return 0;
}
|
sub_4026A0 指定位置使用道具,从使用道具的函数里可以分析出:迷宫是逐个关卡从低到高立体层叠的,0x11道具可以从空洞掉落到下一层,下一层是空洞会继续掉落下去
sub_402400 判断是否可进入上一关,如果可到达,则会来到上一关的右下角坐标(5,4)
sub_402380 判断是否可进入下一关,如果可到达,则会来到下一关的左上角坐标(0,0)
.text:004023CE movzx eax, byte ptr [ebx+198h]
.text:004023D5 cmp [ebx+10h], eax //检查最终密钥 if (k == w)
.text:004023D8 jnz short loc_4023F0
这个检查的含义是输入的前18个字符组成的大数需要特定的值
所有游戏的主体就用输入的key控制走路过程,从每层的左上角走到右下角进入下一关,直到第4关通关
单独看每一关的话,6x5的地图,似乎也并不复杂,就手动走着玩玩
因为高层的道具会掉落下去的原因,有时需要返回前面低级关卡,处理给适当的位置垫高的问题
开始也是拾取过第一关的道具,走到第三关后没路走不下去了
多次尝试后,发现拾取道具是个负担,无视道具反而容易看清路线,就想到了试试不拾取0x31道具能不能走通,
竟然真的走通了,路线步骤,如下:
01 12 13 06 3B 0B 0D 1E 06 17 3B 02 12 3B 01 10 1E 1E 10 06 3B 0D 0B 1E 06 10 17 0C 3B 0B 10 1E 10 1C 0C 17 3B 1A 12 1E 1C 11 3B 12 10 3B 19 17 15 17 3B 05 06 07 17 12 18 3B
每个步骤转成平面坐标表示是(v/5,v%5)
其中那些小于0x1E步骤都是两个一组,从一个位置拿到0x11类型的箱子,扔到另一个位置的0x00空洞里
0x1E是回到上一关,0x3B是进入下一关
迷宫虽然走通了,但是后面却有个crc判断:
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 | sub_402460()
{
...
if ( (v10 & 0xF) == 1 )
{
*((_DWORD *)v2 + 2) = x;
*((_DWORD *)v2 + 3) = y;
if ( (signed int)v10 >> 4 == 3 ) //0x31类型道具
{
v23[20] = v19 ^ (v22 + y) ^ ((v22 + y) ^ v9) & 0xF;
v12 = *((_DWORD *)v2 + 0x65) == 1;
*((_DWORD *)v2 + 4) = 3 * ((*((_DWORD *)v2 + 4) + 2) >> 1); //w = (w+2)/2*3,w初始值是3,经过3次迭代会等于十进制的33
if ( v12 && v19 == 3 )
{
v2[0x198] = 0x37; //第一次拾取0x31道具,修改迷宫密钥为k = 0x37
v13 = 0x37;
}
else
{
sub_401AB0(v2 + 0x110, v2 + 0x110, v2 + 0x8C); //大数乘法 a *= x
sub_401AB0(v2 + 0x13C, v2 + 0x13C, v2 + 0xB8); //大数乘法 b *= y
sub_401AB0(v2 + 0x168, v2 + 0x168, v2 + 0xE4); //大数乘法 c *= z
sub_4019F0(v2 + 0x194, v2 + 0x110, v2 + 0x13C, v2 + 0x168); //修改密钥 k = a - b - c
v13 = v2[0x198];
}
//变更密钥后,需要对数据用新密钥重新加密
v14 = v2 + 0x32;
v15 = v2 + 0xAA;
v16 = v13 ^ v19;
do
{
v17 = v14 - 30;
do
{
v18 = (int)(v17 + 5);
do
*v17++ ^= v16;
while ( v17 != (_BYTE *)v18 );
}
while ( v17 != v14 );
v14 += 30;
}
while ( v14 != v15 );
}
}
return 0;
}
|
sub_4026A0 指定位置使用道具,从使用道具的函数里可以分析出:迷宫是逐个关卡从低到高立体层叠的,0x11道具可以从空洞掉落到下一层,下一层是空洞会继续掉落下去
sub_402400 判断是否可进入上一关,如果可到达,则会来到上一关的右下角坐标(5,4)
sub_402380 判断是否可进入下一关,如果可到达,则会来到下一关的左上角坐标(0,0)
.text:004023CE movzx eax, byte ptr [ebx+198h]
.text:004023D5 cmp [ebx+10h], eax //检查最终密钥 if (k == w)
.text:004023D8 jnz short loc_4023F0
这个检查的含义是输入的前18个字符组成的大数需要特定的值
所有游戏的主体就用输入的key控制走路过程,从每层的左上角走到右下角进入下一关,直到第4关通关
单独看每一关的话,6x5的地图,似乎也并不复杂,就手动走着玩玩
因为高层的道具会掉落下去的原因,有时需要返回前面低级关卡,处理给适当的位置垫高的问题
开始也是拾取过第一关的道具,走到第三关后没路走不下去了
多次尝试后,发现拾取道具是个负担,无视道具反而容易看清路线,就想到了试试不拾取0x31道具能不能走通,
竟然真的走通了,路线步骤,如下:
01 12 13 06 3B 0B 0D 1E 06 17 3B 02 12 3B 01 10 1E 1E 10 06 3B 0D 0B 1E 06 10 17 0C 3B 0B 10 1E 10 1C 0C 17 3B 1A 12 1E 1C 11 3B 12 10 3B 19 17 15 17 3B 05 06 07 17 12 18 3B
每个步骤转成平面坐标表示是(v/5,v%5)
其中那些小于0x1E步骤都是两个一组,从一个位置拿到0x11类型的箱子,扔到另一个位置的0x00空洞里
0x1E是回到上一关,0x3B是进入下一关
迷宫虽然走通了,但是后面却有个crc判断:
sub_4026A0 指定位置使用道具,从使用道具的函数里可以分析出:迷宫是逐个关卡从低到高立体层叠的,0x11道具可以从空洞掉落到下一层,下一层是空洞会继续掉落下去
sub_402400 判断是否可进入上一关,如果可到达,则会来到上一关的右下角坐标(5,4)
sub_402380 判断是否可进入下一关,如果可到达,则会来到下一关的左上角坐标(0,0)
.text:004023CE movzx eax, byte ptr [ebx+198h]
.text:004023D5 cmp [ebx+10h], eax //检查最终密钥 if (k == w)
.text:004023D8 jnz short loc_4023F0
这个检查的含义是输入的前18个字符组成的大数需要特定的值
所有游戏的主体就用输入的key控制走路过程,从每层的左上角走到右下角进入下一关,直到第4关通关
单独看每一关的话,6x5的地图,似乎也并不复杂,就手动走着玩玩
因为高层的道具会掉落下去的原因,有时需要返回前面低级关卡,处理给适当的位置垫高的问题
开始也是拾取过第一关的道具,走到第三关后没路走不下去了
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-12-30 20:46
被ccfer编辑
,原因: