BUUCTF - re - [ACTF新生赛2020]Oruga下载好后直接用IDA就可以打开,找到main函数 _int64 __fastcall main(__int64 a1, char **a2, char **a3)
[C++] 纯文本查看 复制代码 {
__int64 result; // rax
__int64 v4; // [rsp+0h] [rbp-40h]
char v5; // [rsp+9h] [rbp-37h]
char s2[4]; // [rsp+Ah] [rbp-36h]
char s[40]; // [rsp+10h] [rbp-30h]
unsigned __int64 v8; // [rsp+38h] [rbp-8h]
​
v8 = __readfsqword(0x28u);
memset(s, 0, 0x19uLL);
printf("Tell me the flag:", 0LL);
scanf("%s", s);
strcpy(s2, "actf{");
LODWORD(v4) = 0;
while ( (signed int)v4 <= 4 ) // v4为8字节,低4位存储索引,高四位存储值
{
*((_BYTE *)&v4 + (signed int)v4 + 4) = s[(signed int)v4];
LODWORD(v4) = v4 + 1;
}
v5 = 0;
if ( !strcmp((const char *)&v4 + 4, s2) ) // 比较flag头
{
if ( (unsigned __int8)sub_78A((__int64)s) )
printf("That's True Flag!", s2, v4);
else
printf("don't stop trying...", s2, v4);
result = 0LL;
}
通过这些代码,我们知道flag的头为actf{进入到主要的函数分析sub_78Awhile ( byte_201020[v2] !=0x21 )
[C++] 纯文本查看 复制代码 {
v2 -= v4; // 当前坐标
// 减去上次移动多移动的一次
if ( *(_BYTE *)(v3 + a1) != 87 || v4 == -16 )
{
if ( *(_BYTE *)(v3 + a1) != 69 || v4 == 1 )
{
if ( *(_BYTE *)(v3 + a1) != 77 || v4 == 16 )
{
if ( *(_BYTE *)(v3 + a1) != 74 || v4 == -1 )
return 0LL; // 判断最后一位是否为'}'
//
v4 = -1; // a1[v3]='J'向左移动
}
else
{
v4 = 16; // a1[v3]='M'向下
}
}
else
{
v4 = 1; // a1[v3]='E'向右
}
}
else
{
v4 = -16; // a1[v3]='W'向上移动
}
这个函数其实就是一个迷宫,16*16,这个迷宫并不是很复杂可以直接手动写向下移动:M向左移动:J向上移动:E向右移动:W外层while循环,就是到0x21时停止,v2为当前位置,v3从输入的第六个字符开始遍历数组,v4实际是对v2位置的移动。第二处,用了个循环,if条件判断的是位置是否到达边界,越界退出整个迷宫就是用WEMJ控制移动,0可以移动(一直移动),到达非0位置停止,返回上一位置。左上角为起点,0x21为终点。手动解迷宫别人写的脚本:
[C++] 纯文本查看 复制代码 #include <stdio.h>
char maze[256] = {
0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x23, 0x23,
0x00, 0x00, 0x00, 0x23, 0x23, 0x00, 0x00, 0x00, 0x4F, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x4F, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x4C, 0x00, 0x4F, 0x4F, 0x00, 0x4F, 0x4F, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x4C, 0x00, 0x4F, 0x4F, 0x00, 0x4F, 0x4F, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x4C, 0x4C, 0x00, 0x4F, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00,
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x45, 0x45,
0x00, 0x00, 0x00, 0x30, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x45,
0x54, 0x54, 0x54, 0x49, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00,
0x00, 0x54, 0x00, 0x49, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x45, 0x00,
0x00, 0x54, 0x00, 0x49, 0x00, 0x4D, 0x00, 0x4D, 0x00, 0x4D, 0x21, 0x00, 0x00, 0x00, 0x45, 0x45
};
int main(void)
{
int i, j;
for (i = 0; i < 16; i++)
{
for (j = 0; j < 16; j++)
{
if (i == 0 && j == 0)
printf("☆"); //起点
else if (maze[16 * i + j] == 0)
printf("□"); //路
else if (maze[16 * i + j] == 0x21)
printf("★"); //终点
else printf("■"); //障碍物
}
putchar('\n');
}
} flag{MEWEMEWJMEWJM} |