BUUCTF - re - [ACTF新生赛2020]Oruga
BUUCTF - re - Oruga下载好后直接用ida就可以打开,找到main函数 _int64 __fastcall main(__int64 a1, char **a2, char **a3){
__int64 result; // rax
__int64 v4; //
char v5; //
char s2; //
char s; //
unsigned __int64 v8; //
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 !=0x21 )
{
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='J'向左移动
}
else
{
v4 = 16; // a1='M'向下
}
}
else
{
v4 = 1; // a1='E'向右
}
}
else
{
v4 = -16; // a1='W'向上移动
}
这个函数其实就是一个迷宫,16*16,这个迷宫并不是很复杂可以直接手动写向下移动:M向左移动:J向上移动:E向右移动:W外层while循环,就是到0x21时停止,v2为当前位置,v3从输入的第六个字符开始遍历数组,v4实际是对v2位置的移动。第二处,用了个循环,if条件判断的是位置是否到达边界,越界退出整个迷宫就是用WEMJ控制移动,0可以移动(一直移动),到达非0位置停止,返回上一位置。左上角为起点,0x21为终点。手动解迷宫别人写的脚本:
#include <stdio.h>
char maze = {
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 == 0)
printf("□");//路
else if (maze == 0x21)
printf("★");//终点
else printf("■"); //障碍物
}
putchar('\n');
}
} flag{MEWEMEWJMEWJM} 代码用代码框处理一下吧,或者用markdown写,这样会好看一些。 写的不错,下次继续 向大佬学习
页:
[1]