开始先设置一下数字以16进制格式显示
看主函数
__int64 __fastcall main(int a1, char **a2, char **a3)
{
int v3; // eax
size_t v4; // rax
int v5; // ecx
char v6; // al
int v7; // ecx
int v9; // [rsp+3Ch] [rbp-404h]
char s[1000]; // [rsp+40h] [rbp-400h] BYREF
char **v11; // [rsp+428h] [rbp-18h]
int v12; // [rsp+434h] [rbp-Ch]
unsigned int v13; // [rsp+438h] [rbp-8h]
int v14; // [rsp+43Ch] [rbp-4h]
v13 = 0;
v12 = a1;
v11 = a2;
memset(s, 0, sizeof(s));
v14 = v12;
v9 = 0xC1C2064A;
while ( 1 )
{
while ( 1 )
{
while ( v9 == 0x8EA211B0 )
{
v6 = sub_4005A0(v11[1]);
v7 = 0xB732FD38;
if ( v6 )
v7 = 0x3C9B63CE;
v9 = v7;
}
if ( v9 != 0x8FD5B3CA )
break;
v13 = 0;
v9 = 0xA66258D6;
}
if ( v9 == 0xA66258D6 )
break;
switch ( v9 )
{
case 0xB732FD38:
printf("RUSH AGAIN!\n");
v13 = 1;
v9 = 0xA66258D6;
break;
case 0xC1C2064A:
v3 = 0xBCCA5E6;
if ( v14 != 2 )
v3 = 0xB732FD38;
v9 = v3;
break;
case 0xBCCA5E6:
v4 = strlen(v11[1]);
v5 = 0x8EA211B0;
if ( v4 != 0x44 )
v5 = 0xB732FD38;
v9 = v5;
break;
default:
v9 = 0x8FD5B3CA;
printf("Congratulations! You have rushed B! Flag is flag{md5(input)}...\n");
break;
}
}
return v13;
}
分析一下初始 v9 = 0xC1C2064A; ,那么执行的就是这一段,
case 0xC1C2064A:
v3 = 0xBCCA5E6;
if ( v14 != 2 )
v3 = 0xB732FD38;
v9 = v3;
break;
v9=0xB732FD38 就会退出,所以初始v14就要等于2
这里有个算字符串长度的,输入的字符串长度要等于68 ,v11[1]中存的是字符串指针的指针
case 0xBCCA5E6:
v4 = strlen(v11[1]);
v5 = 0x8EA211B0;
if ( v4 != 0x44 )
v5 = 0xB732FD38;
v9 = v5;
break;
重点就是sub_4005A0这个函数
一坨的while循环
看到这个经典的判断语句
经典迷宫题
转到16进制窗口,先提取出来,18个数据一行,把地图画出来
初始点位为(1,1)
地图
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 01 02 0B 0A 0A 09 02 0B 08 03 0B 0A 0A 0A 0A 09 00
00 06 09 05 03 08 06 09 05 03 0C 06 09 03 0A 09 04 00
00 01 06 0C 05 03 0A 0C 06 0E 0A 08 07 0C 01 06 09 00
00 07 0A 0B 0D 05 02 0B 0A 0A 0A 09 06 0A 0E 09 05 00
00 06 08 05 04 06 0A 0C 03 0B 08 06 0A 09 03 0C 05 00
00 03 09 06 0A 0A 0B 09 05 04 03 09 03 0C 04 03 0C 00
00 05 06 0A 09 03 0C 05 06 09 05 05 05 03 09 06 09 00
00 05 03 09 05 05 03 0C 03 0D 05 06 0C 05 05 03 0D 00
00 05 05 04 06 0C 06 0A 0C 05 05 01 03 0D 06 0C 05 00
00 05 07 0A 09 03 0B 0A 08 05 05 06 0C 07 09 01 05 00
00 05 06 08 06 0C 06 0A 0A 0C 06 0A 09 04 05 07 0C 00
00 05 03 0A 09 03 09 03 0A 0A 0B 08 05 03 0C 05 01 00
00 05 05 01 05 05 06 0C 03 09 06 09 06 0C 01 06 0D 00
00 05 06 0D 05 05 01 03 0D 06 08 07 0A 0A 0E 08 05 00
00 07 08 05 06 0C 06 0C 05 03 0A 0C 03 09 03 09 05 00
00 06 0A 0E 0A 0A 0A 0A 0C 06 0A 0A 0C 06 0C 06 1E 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
判断路能不能走,v14一共有4种取值,0,1,2,3
可以先将成立的情况列出来,byte_602040[] 的取值为0x00 - 0x0E (唯一一个0x1E就是终点),
byte_602040[] 取值 | v14 取值 |
---|---|
0x00 | 没有v14的值满足条件 |
0x01 | 0 |
0x02 | 1 |
0x03 | 0, 1 |
0x04 | 2 |
0x05 | 0,2 |
0x06 | 1,2 |
0x07 | 0,1,2 |
0x08 | 3 |
0x09 | 0,3 |
0x0A | 1,3 |
0x0B | 0,1,3 |
0x0C | 2,3 |
0x0D | 0,2,3 |
0x0E | 1,2,3 |
结束条件,要让条件成立byte_602040[] 就得大于等于0x10,满足条件的只有一个0x1E
如果路可以走,就变化v16和v15的值,v16是行 ,v15是列
这玩意麻烦就麻烦在你能走的路径是会变的,先分析前几步理一下思路,我把循环层数标了下,一共14层循环。。。
__int64 __fastcall sub_4005A0(__int64 a1)
{
unsigned int v1; // eax
unsigned int v2; // eax
unsigned int v3; // eax
int v4; // eax
int v5; // eax
int v6; // eax
unsigned int v7; // eax
unsigned int v8; // eax
int v9; // eax
unsigned int v10; // eax
unsigned int v12; // [rsp+68h] [rbp-20h]
unsigned __int8 v13; // [rsp+6Ch] [rbp-1Ch]
unsigned __int8 v14; // [rsp+6Dh] [rbp-1Bh]
char v15; // [rsp+6Eh] [rbp-1Ah]
char v16; // [rsp+6Fh] [rbp-19h]
__int64 v17; // [rsp+70h] [rbp-18h]
__int64 v18; // [rsp+78h] [rbp-10h]
unsigned __int8 v19; // [rsp+83h] [rbp-5h]
int v20; // [rsp+84h] [rbp-4h]
v18 = a1;
v17 = 0x1010000FFFF00LL;
v16 = 1;
v15 = 1;
v13 = 0;
v12 = 0x8CF907F5;
while ( 1 )
{ // 1
while ( 1 )
{ // 2
while ( 1 )
{ // 3
while ( 1 )
{ // 4
while ( 1 )
{ // 5
while ( 1 )
{ // 6
while ( 1 )
{ // 7
while ( 1 )
{ // 8
while ( 1 )
{ // 9
while ( 1 ) // 12
{ // 10
while ( 1 )
{ // 11
while ( 1 )
{ // 12
while ( 1 )
{ // 13
while ( v12 == 0x803BA95E )
{ // 14
v19 = 0;
v12 = 0xF4078EB1;
} // 14
if ( v12 != 0x8CF907F5 )
break;
v1 = 0xABC759CB;
if ( v13 < 0x44u )
v1 = 0xD87E0B66;
v12 = v1;
} // 13
if ( v12 != 0x8DA6A494 )
break;
++v13;
v12 = 0x8CF907F5;
} // 12
if ( v12 != 0x91BFBC64 )
break;
v14 = 1;
v12 = 0xBB25C497;
} //11
if ( v12 != 0x97DCB23D )
break;
v10 = 0x52BAF199;
if ( (byte_602040[0x12 * v16 + v15] & 0x10) != 0 )
v10 = 0x9F36EED5;
v12 = v10;
} //10
if ( v12 != 0x990181F1 )
break;
v14 = 3;
v12 = 0xBB25C497;
} //9
if ( v12 != 0x9F36EED5 )
break;
v19 = 1;
v12 = 0xF4078EB1;
} //8
if ( v12 != 0xABC759CB )
break;
v19 = 0;
v12 = 0xF4078EB1;
} //7
if ( v12 != 0xB397B4AE )
break;
v4 = 0x4157602D;
if ( v20 == 0x77 )
v4 = 0x4D29FD46;
v12 = v4;
} //6
if ( v12 != 0xBB25C497 )
break;
v9 = 0x1C918C9E;
if ( ((1 << v14) & byte_602040[0x12 * v16 + v15]) != 0 )
v9 = 0x23EDBCE0;
v12 = v9;
} //5
if ( v12 != 0xC91BB3A3 )
break;
v2 = 0x2C1C4A6F;
if ( v20 < 0x73 )
v2 = 0xE7D58653;
v12 = v2;
} //4
if ( v12 != 0xD87E0B66 )
break;
v20 = *(char *)(v18 + v13);
v12 = 0xC91BB3A3;
} //3
if ( v12 != 0xE7D58653 )
break;
v6 = 0x3EE42C64;
if ( v20 < 0x64 )
v6 = 0x1BB52CB7;
v12 = v6;
} //2
if ( v12 == 0xF4078EB1 )
break;
switch ( v12 )
{
case 0x1BB52CB7u:
v8 = 0x4157602D;
if ( v20 == 0x61 )
v8 = 0x990181F1;
v12 = v8;
break;
case 0x1C918C9Eu:
v19 = 0;
v12 = 0xF4078EB1;
break;
case 0x23EDBCE0u:
v16 += *((_BYTE *)&v17 + 2 * (3 - v14));
v15 += *((_BYTE *)&v17 + 2 * (3 - v14) + 1);
v12 = 0x97DCB23D;
break;
case 0x2C1C4A6Fu:
v3 = 0xB397B4AE;
if ( v20 < 0x77 )
v3 = 0x4495DA98;
v12 = v3;
break;
case 0x39324084u:
v14 = 0;
v12 = 0xBB25C497;
break;
case 0x3EE42C64u:
v7 = 0x4157602D;
if ( v20 == 0x64 )
v7 = 0x91BFBC64;
v12 = v7;
break;
case 0x4157602Du:
v12 = 0x803BA95E;
break;
case 0x4495DA98u:
v5 = 0x4157602D;
if ( v20 == 0x73 )
v5 = 0x39324084;
v12 = v5;
break;
case 0x4D29FD46u:
v14 = 2;
v12 = 0xBB25C497;
break;
default:
v12 = 0x8DA6A494;
break;
}
} //1
return v19;
}
初始 v12 = 0x8CF907F5; ,执行到第13层循环, v12 = 0xD87E0B66
然后会一直跳出到第 3层循环, 取flag的第一个字符到v20中, v12 = 0xC91BB3A3
然后到第4层循环, 0x73 就是 ‘s’ , 盲猜wsad控制上下左右,先假设第一步往右走即 v20 < 0x73 ,v12 = 0xE7D58653
到第2层循环 ,0x64 就是 ‘d’ ,v12=0x3EE42C64
到第1层循环, v12 = 0x91BFBC64
到第11层循环, v14 = 1 , v12 = 0xBB25C497
到第5层循环, 此时byte_602040 = 0x01,v14 = 1 很明显不满足条件, v12 = 0x1C918C9E
到第1层循环,v12 = 0xF4078EB1
再继续就直接退出循环了
然后可以假设第一步是 ‘s’ 的情况,此时 byte_602040 = 0x01,v14 = 0 可以满足条件
然后推出
‘w’ ,v14 = 2 ,
‘s’ ,v14 = 0
‘a’ ,v14 = 3
‘d’ ,v14 = 1
即 当v14 = 2 时,上一步一定是 w
简单的说就是根据当前位置来推断出下一步可以走哪几个位置
比如:
byte_602040 = 0x01 v14 = 0 ,即只能往下(s)走
然后下一步
byte_602040 = 0x06 v14可以取 1,2, 即可以往右(d)或者往上(w),因为这迷宫路径肯定也不能走重复的路径,也不能走死路,那么下一步只能往右走
下一步
byte_602040= 0x09 , v14可以取0,3,即可以往下(s)或者往左(a),0x00肯定不能走,所以也只能往下走
…
如此反复可以把路径画出来,大概是这样,这图是第一次画的可能有错,我画了两次,第二次忘存了,懒得再画了
最终路径:
sdsdwwdddsdsaassddwddddsddsassawwasssssddssdwdwwawwwdssdwdsssassdsss
然后flag就是把路径md5一下就行