【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)



























