X-CTF-maze
文件地址:https://github.com/PIG-007/X-CTF
1.拖入exeinfope.exe查看版本位数,64位,载入IDA.
2.由于题目maze的提示,还有函数中一直出现的8,再加上判断语句中
asc_601060[8 * (signed int)v9 + SHIDWORD(v9)] != ‘#’
以及字符串:
“ ******* * **** * **** * *** *# *** *** *** *********”
可知是走迷宫题目,也就是将该字符串以8位为一个行,形成一个8*8的迷宫:
按照1的路径一直走,共走18步。
3.然后再仔细分析,在linux中运行,需要输入flag,再在IDA中发现有输入长度要求,得是nctf{xxxxx(18个)}这种形式。然后分析迷宫,发现取最短路径走到#刚好是18个。
4.现在开始寻找方向:很容易发现四个if语句:(这里得右键对应的数字-R转成字符形式,才能看到对应数字的ascii码)
if ( v4 == ‘O’ )
if ( v4 == ‘o’ )
if ( v4 == ‘.’ )
if ( v4 == ‘0’ )
这个应该就是代表上下左右了,那么现在还得判断究竟是哪个代表哪个。这里有两种方法。一是接着看代码,进去里面仔细分析,可以推出。二是通过远程调试来判断。
▲方法一:我们进入到四个if语句中的每个函数中看看,有类似如下语句:
v1 = (*a1)–;
v1 = *a1 + 1;
传入的值分别是:&v10+4,和&v10,这里不同的IDA反汇编出来的参数不一样,但看v10的类型是一个int型的指针,4个字节为一个int,&v10+4代表int指针往下拨动一个int,也就是常说的指针+1,有的时候IDA也会反汇编为&v10+1,这是代表的是&(V10+1)也是一样的,只是括号没有写出来。这里我们可以将鼠标移动到变量上,按下Y快捷键,输入int[2]来修改,之后再按N快捷键修改变量名称为direction,最终变成
这样就清晰多了,至于为什么要int[2],因为迷宫都是二维的,一般可用x0y坐标轴来表示,这样我们就可将direction[1]l来代表x轴,direction代表y轴,反之亦然。如下:
那么就是O和o代表x轴左右,0和.代表y轴上下或者反过来,则flag就有两种,都列举出来提交试试就可以得到正确答案。
▲尝试第二种方法,远程linux下调试:这里还需要看看接下来的代码:
所有方向判断语句之后都会跳转到LABEL_14,由此可以断定得是判断正确才会break来使得label20不被运行,从而跳出打印错误flag的语句,所以这里需要使得v6=1,然后再向上找找,有这样的语句:
而v7又是方向判断函数的返回值,所以在运行时可以尝试看v7的值来判断输入的正确与否。于是在该处下断点,或者对应汇编代码中:mov bpl, al。(鼠标放在v7上,显示al,说明v7是存放在al这个变量上的),尝试性输入nctf{000000000000000000},输入够了就行,然后在运行中看v7,也就是al的值,如果被赋值为1,则0就代表向右,因为我们迷宫中第一步就是向右的,否则就换下一个试。依次类推,可以通过调试来摸清方向。
断点停住,查看al的值为1,本来应该说明0代表向右,但是如果输入
nctf{oooooooooooooooooo},al的值也是1。这里是因为右和下都能走,但是源代码中还有一个判断逻辑:
代表撞墙逻辑,也就是如果撞墙上了,仍然会打印错误Flag。查看迷宫,发现向下会撞墙上,而对应nctf{oooooooooooooooooo}调试的时候,接着单步执行,会发现程序再一次进入方向判断函数,并没有直接进入撞墙的逻辑中,说明nctf{oooooooooooooooooo}的第一个才是右,而nctf{000000000000000000}会撞墙上,虽然v7的值是1,但仍然会导致错误。所以0代表下,o代表右,依次类推就可以判断出方向。
最终flag为:nctf{o0oo00O000oooo..OO}
(Linux远程调试可以看其它文章)