【GDOUCTF 2023】doublegame
收获
解决 exe 由于缺少 DLL 文件导致无法运行的问题
迷宫题,不过这个题有点小坑,对迷宫进行了改动,所以看到迷宫不要傻乎乎的直接复制粘贴,多看看代码里有没有对迷宫做修改
代码与程序输出结合分析,快速定位关键位置
(2023年4月16日)【GDOUCTF 2023】doublegame
思路
解压得到一个 doublegame.exe
程序,运行发现是一个贪吃蛇游戏
部分人可能像我一样,打开 exe 会弹出一个缺少 DLL 的错误,导致无法运行
详见本站的《运行程序遇到 “由于找不到 xxx.dll,无法继续执行代码”》一文
经过试验,后面蛇的速度会越来越快
用 64 位 IDA 打开,F5 反编译:
但是什么都没有
由于没有 main()
函数,shift + F12
查看一下字符串,定位到关键位置:
可以看到很多与 flag 有关的信息:
① 首先最关键的一点,告诉了 flag 的形式是 HZCTF{md5(path)+score}
② 注意下图,有一个由很多 '0'
和 ' '
组成的类似迷宫的东西,结合 md5(path)
可以大致推断 path
就是走迷宫的路径
③ 同时,还告诉了 the first game tell the score
,结合文件名 doublegame.exe
可知,这个程序应该有两个游戏,第一个游戏是贪吃蛇,第二个游戏是走迷宫,贪吃蛇得到 score
,走迷宫得到 path
注意到字符串里的 "GAME OVER"
和 "?(y/n):"
与贪吃蛇游戏闯关失败时的输出有关,跟进函数位置:
根据 sub_1400111F9("GAME OVER")
可以推出 sub_1400111F9()
函数的功能是 printf()
重命名一下,定位到关键 if
判断:
跟进上面两个红框中 printf()
的输出内容:
内容是十六进制数据,结合游戏的输出,这应该是输出的某些中文内容,最后 %d
是一个游戏中的数据
重点在后面的一个 if
判断:
if ( dword_140022CD0 > 13371337 )
sub_14001136B();
sub_1400110E6();
首先,最后的 sub_1400110E6()
函数会执行 sub_140012A40()
用于在本地生成一个 贪吃蛇最高得分记录.txt
的文本文件:
关键在于当 dword_140022CD0 > 13371337
时,会执行 sub_14001136B()
函数,sub_14001136B()
函数会执行 sub_140012CF0()
:
这个函数用来生成迷宫的,以及 switch()
中的 'w'
、'a'
、's'
、'd'
用来控制方向
由于这是第二个游戏,明显 dword_140022CD0 > 13371337
就是通关条件
(可能是分数 score > 13371337
就进入下一关,这里只是猜测,后面会验证,所以仅凭徒手玩游戏通关是几乎不可能的了)
将 sub_140012CF0()
函数提供的迷宫数据提取出来
但是这里有个小坑,很重要,没有发现的话是做不出来的:
在上方的一堆 '0'
和 ' '
都是迷宫的内容,注意最后有一个 v11[4] = 48
,48 是 '0'
的 ASCii 码
找到 v11
的位置,也就是将 @11111110101111111110
(为了看得更清楚,我把空格用 '1'
来表示) 这一行的第 5 个位置的空格改为 '0'
了
提取出修改后的迷宫:
(这里有个小技巧:由于 '0'
表示墙壁,' '
表示路,可以在 Pycharm 中全选 ' '
,空格会有高亮,路径会更显眼)
得到路径 path
:dddssssddwwwwddssddwwwwwwddddssaassddddwwwwddwwwwddd
MD5 加密后为:811173b05afff098b4e0757962127eac
这里来分析一下,为什么是个走迷宫,具体信息是怎么样的:
① 首先这里有个 while
循环,判断的是当前位置是否走到了出口,结合(v15,v16)
是(15,0)
对应 '@'
的位置,而(v17,v18)
是(7,20)
对应最后出口的那个点
② 再往下,注意到有一步操作会影响到后面的 if
条件,往左走的时候,如果当前位置是 '*'
的话,就将 v7[20] = 48
,否则后面的 if
不会执行,而是输出 "error"
,所以路径必须要经过 '*'
的位置
③ 最后,注意这个 if
条件
函数 sub_140011433(0)
会执行 sub_140011E10(unsigned int a1)
:
根据形式,sub_14001126C("%d", &v2)
应该是一个 scanf()
函数,让用户输入的 v2
就是 key
,而前面又提示说 the score is saving cat's key!\n
,可以知道这个 v2
就是 score
由于传参 a1 = 0
,v2
初值为 0,最后返回 v2
的值,而 sub_140011433(0)
的返回值为 v24
,且 v24
要等于 13376013
,所以 v2 = 0x1DC4 ^ 13376013
最后得到 v2 = 13371337
,验证了前面 score > 13371337
就进入下一关的猜想
于是得到 score
:13371337
结果
NSSCTF{811173b05afff098b4e0757962127eac13371337}
(最终要求将 HZCTF 改为 NSSCTF)