记一次CTF_1
记一次CTF的题。
CTF和平时破解的题不一样,需要从题目中的一些提示寻找突破口,有时还需要脑洞。
首先我们打开程序:
看到一个上下左右的提示,然后我们输入试着输入不同的值,发现输入1、3、4,都会弹出窗口,而输入2,则会继续这个循环。
在对程序有一个大概的了解之后,我们用IAD打开,查看一下伪代码:
main函数很好找,直接能看到:
void main()
{
char v0; // [sp+17h] [bp-35h]@1
int y; // [sp+30h] [bp-1Ch]@1
int x; // [sp+34h] [bp-18h]@1
signed int input; // [sp+38h] [bp-14h]@2
signed int i; // [sp+3Ch] [bp-10h]@14
int v5; // [sp+40h] [bp-Ch]@20
__main(); // 初始化
y = 0;
x = 0; // x,y为坐标
qmemcpy(&v0, _data_start__, 0x19u); // v0=*11110100001010000101111#
while ( 1 )
{
puts("you can choose one action to execute");
puts("1 up");
puts("2 down"); // 1.上 2.下 3.左 4.右
puts("3 left");
printf("4 right\n:");
scanf("%d", &input);
if ( input == 2 ) // input=2
{
++y; // y坐标增加1
}
else if ( input > 2 )
{ // input=3
if ( input == 3 )
{
--x; // x坐标减少1
}
else
{
if ( input != 4 ) // input =4
LABEL_13:
exit(1);
++x; // x坐标增加1
}
}
else
{
if ( input != 1 ) // input=1
goto LABEL_13;
--y; // y坐标减少1
}
for ( i = 0; i <= 1; ++i )
{
if ( *(&y + i) < 0 || *(&y + i) > 4 ) // 判断v1是否在0-4,否则退出
exit(1);
}
if ( *((_BYTE *)&v5 + 5 * y + x - 41) == '1' )// 判断坐标是否为墙
exit(1);
if ( *((_BYTE *)&v5 + 5 * y + x - 41) == '#' )// 判断坐标是否为终点
{
puts("\nok, the order you enter is the flag!");
exit(0);
}
}
}
图中已经将伪代码的逻辑进行了标注,我们已经可以比较清晰的看到,这是一个迷宫的地图,因此找到迷宫,有了上下左右,题目自然就解出来了。
那么地图在哪里呢。
在师傅的指点下,我找到了。
我们先看到这个
这里是判断坐标是否为墙和终点,我们来看看这里的逻辑:首先是(v5的地址+y*5+x-41),我们知道y于x是坐标,所以这个式子就可以变成
(v5的地址-41+坐标)
我们可以想:如果要判断是否为墙,那么一定要把坐标放在地图上比较,所以,这个v5的地址-41,一定是地图的地址。
而经过计算,我们发现v5的地址,其实就是前面v0的地址,所以地图就是
地图就是
*1111
01000
01010
00010
1111#
那么flag就是{222441144222}