下载查看:
ida64打开,f5分析:
输入一个24位字符串,存储到s1里,经过一系列判断处理,才能到达congratulations!
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
__int64 v3; // rbx
int v4; // eax
bool v5; // bp
bool v6; // al
const char *v7; // rdi
int v9; // [rsp+0h] [rbp-28h]
int v10; // [rsp+4h] [rbp-24h]
v10 = 0;
v9 = 0;
puts("Input flag:");
scanf("%s", &s1);
if ( strlen(&s1) != 24 || strncmp(&s1, "nctf{", 5uLL) || *(&byte_6010BF + 24) != '}' )// 要求输入的s1长度为24,开头和结束应该是nctf{}
//
{
LABEL_22:
puts("Wrong flag!");
exit(-1);
}
v3 = 5LL;
if ( strlen(&s1) - 1 > 5 )
{
while ( 1 )
{
v4 = *(&s1 + v3); // 从第1个字符开始,跨过nctf{
v5 = 0;
if ( v4 > 'N' )
{
if ( (unsigned __int8)v4 == 'O' ) // 如果等于O,v10就减一,赋值给v6,列数减1,向左
{
v6 = sub_400650(&v10);
goto LABEL_14;
}
if ( (unsigned __int8)v4 == 'o' ) // 如果等于o,v10就加1,赋值给v6,列数加1,向右
{
v6 = sub_400660(&v10);
goto LABEL_14;
}
}
else
{
if ( (unsigned __int8)v4 == '.' )
{
v6 = sub_400670(&v9); // 行数减1,向上
goto LABEL_14;
}
if ( (unsigned __int8)v4 == '0' ) // 行数加1,向下
{
v6 = sub_400680(&v9);
LABEL_14: // v6赋值给v5
v5 = v6;
goto LABEL_15;
}
}
LABEL_15:
if ( !(unsigned __int8)sub_400690((__int64)asc_601060, v10, v9) )// 不是空格或者#就结束
goto LABEL_22;
if ( ++v3 >= strlen(&s1) - 1 ) // 处理下一个字符,并判断是不是结尾
{
if ( v5 )
break;
LABEL_20:
v7 = "Wrong flag!";
goto LABEL_21;
}
}
}
if ( asc_601060[8 * v9 + v10] != '#' ) // #是最终正确答案,从这里看出,v9和v10就是不断找寻正确的符号,从这里看出v9类似于行数,v10类似于列数
goto LABEL_20;
v7 = "Congratulations!";
LABEL_21:
puts(v7);
return 0LL;
}
结合asc_601060,画出如下迷宫
正确顺序:右下右右下下左下下下右右右右上上左左
答案:nctf{o0oo00O000oooo..OO}
400690必须是空格或者#才能返回1。
__int64 __fastcall sub_400690(__int64 a1, int a2, int a3)
{
__int64 result; // rax
result = *(unsigned __int8 *)(a1 + a2 + 8LL * a3);
LOBYTE(result) = (_DWORD)result == ' ' || (_DWORD)result == '#';
return result;
}