下载文件用记事本打开显示为ELF64文件
直接使用ida打开搜索关键字符串,定位关键代码,然后F5反汇编
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
const char *v3; // rsi
signed __int64 v4; // rbx
signed int v5; // eax
char v6; // bp
char v7; // al
const char *v8; // rdi
__int64 v10; // [rsp+0h] [rbp-28h]
v10 = 0LL;
puts("Input flag:");
scanf("%s", &s1, 0LL);//获取flag
if ( strlen(&s1) != 24 || (v3 = "nctf{", strncmp(&s1, "nctf{", 5uLL)) || *(&byte_6010BF + 24) != 125 )//flag长度为24位,前5个字符位nctf{,最后一个字符为‘}’
{
LABEL_22:
puts("Wrong flag!");
exit(-1);
}
v4 = 5LL;//从第5个字符开始判断
if ( strlen(&s1) - 1 > 5 )
{
while ( 1 )
{
v5 = *(&s1 + v4);//v5=flag[v5]
v6 = 0;
if ( v5 > 78 )
{
v5 = (unsigned __int8)v5;
if ( (unsigned __int8)v5 == 79 )
{
v7 = sub_400650((char *)&v10 + 4, v3);
goto LABEL_14;
}
if ( v5 == 111 )
{
v7 = sub_400660((char *)&v10 + 4, v3);
goto LABEL_14;
}
}
else
{
v5 = (unsigned __int8)v5;
if ( (unsigned __int8)v5 == 46 )
{
v7 = sub_400670(&v10, v3);
goto LABEL_14;
}
if ( v5 == 48 )
{
v7 = sub_400680(&v10, v3);
LABEL_14:
v6 = v7;
goto LABEL_15;
}
}
LABEL_15:
v3 = (const char *)HIDWORD(v10);
if ( !(unsigned __int8)sub_400690(asc_601060, HIDWORD(v10), (unsigned int)v10) )
goto LABEL_22;
if ( ++v4 >= strlen(&s1) - 1 )
{
if ( v6 )
break;
LABEL_20:
v8 = "Wrong flag!";
goto LABEL_21;
}
}
}
if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != 35 )//从这里可以看出601060处保存的是一个数组
//最后要判断的是横纵坐标相等,且这个值为23h,从汇编代码中可以看出
//dword ptr [rsp+28h+var_28+4]保存的是横坐标
//dword ptr [rsp+28h+var_28],保存的是纵坐标
goto LABEL_20;
v8 = "Congratulations!";
LABEL_21:
puts(v8);
return 0LL;
}
1.题目解析,maze代表的是迷宫,转换到对应的视图模式,可以看到对应的,这里按‘r'进行操作。
2.可以看到程序会根据字符"." ,"0","o" , "O"分别跳到不同的位置进行操作 ,
会调用sub_400690这个函数,对这个函数进行分析
3.取出值和20h和23h比较,当两个都不相等的时候就会出错
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
const char *v3; // rsi
signed __int64 v4; // rbx
signed int v5; // eax
char v6; // bp
char v7; // al
const char *v8; // rdi
__int64 v10; // [rsp+0h] [rbp-28h]
v10 = 0LL;
puts("Input flag:");
scanf("%s", &s1, 0LL);//获取flag
if ( strlen(&s1) != 24 || (v3 = "nctf{", strncmp(&s1, "nctf{", 5uLL)) || *(&byte_6010BF + 24) != 125 )//flag长度为24位,前5个字符位nctf{,最后一个字符为‘}’
{
LABEL_22:
puts("Wrong flag!");
exit(-1);
}
v4 = 5LL;//从第5个字符开始判断
if ( strlen(&s1) - 1 > 5 )
{
while ( 1 )
{
v5 = *(&s1 + v4);//v5=flag[v5]
v6 = 0;
if ( v5 > 78 )
{
v5 = (unsigned __int8)v5;
if ( (unsigned __int8)v5 == 79 )
{
v7 = sub_400650((char *)&v10 + 4, v3);
goto LABEL_14;
}
if ( v5 == 111 )
{
v7 = sub_400660((char *)&v10 + 4, v3);
goto LABEL_14;
}
}
else
{
v5 = (unsigned __int8)v5;
if ( (unsigned __int8)v5 == 46 )
{
v7 = sub_400670(&v10, v3);
goto LABEL_14;
}
if ( v5 == 48 )
{
v7 = sub_400680(&v10, v3);
LABEL_14:
v6 = v7;
goto LABEL_15;
}
}
LABEL_15:
v3 = (const char *)HIDWORD(v10);
if ( !(unsigned __int8)sub_400690(asc_601060, HIDWORD(v10), (unsigned int)v10) )
goto LABEL_22;
if ( ++v4 >= strlen(&s1) - 1 )
{
if ( v6 )
break;
LABEL_20:
v8 = "Wrong flag!";
goto LABEL_21;
}
}
}
if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != 35 )//从这里可以看出601060处保存的是一个数组
//最后要判断的是横纵坐标相等,且这个值为23h,从汇编代码中可以看出
//dword ptr [rsp+28h+var_28+4]保存的是横坐标
//dword ptr [rsp+28h+var_28],保存的是纵坐标
goto LABEL_20;
v8 = "Congratulations!";
LABEL_21:
puts(v8);
return 0LL;
}
1.题目解析,maze代表的是迷宫,转换到对应的视图模式,可以看到对应的,这里按‘r'进行操作。
2.可以看到程序会根据字符"." ,"0","o" , "O"分别跳到不同的位置进行操作 ,
会调用sub_400690这个函数,对这个函数进行分析
3.取出值和20h和23h比较,当两个都不相等的时候就会出错
esi里面保存的相当于是计数器,rdi里面保存的是asc_601060,所以这里相当于和asc_601060处的值进行比较。
这里查看601060处的值,结果如下:
转换成每行8列,相当于一个迷宫游戏,如何从20走到23
20 20 2A 2A 2A 2A 2A 2A
2A 20 20 20 2A 20 20 2A
2A 2A 2A 20 2A 20 2A 2A
2A 2A 20 20 2A 20 2A 2A
2A 20 20 2A 23 20 20 2A
2A 2A 20 2A 2A 2A 20 2A
2A 2A 20 20 20 20 20 2A
2A 2A 2A 2A 2A 2A 2A 2A
4.这里是取出横纵坐标,和数组的地址,然后传入406090函数进行判断操作
20 20 2A 2A 2A 2A 2A 2A
2A 20 20 20 2A 20 20 2A
2A 2A 2A 20 2A 20 2A 2A
2A 2A 20 20 2A 20 2A 2A
2A 20 20 2A 23 20 20 2A
2A 2A 20 2A 2A 2A 20 2A
2A 2A 20 20 20 20 20 2A
2A 2A 2A 2A 2A 2A 2A 2A
4.这里是取出横纵坐标,和数组的地址,然后传入406090函数进行判断操作
5.这里使用了二分查找法进行比较,加快比较的速度,eax里面保存的是输入的数据。
6.这里r14和r15分别保存的是横纵坐标
这几个函数分别对横纵坐标进行增减操作。当当与走迷宫进行变换操作
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!