题目来源
2021 虎符CTF
初步分析
我们首先使用file
命令初步分析
这是一个运行在Linux上的Mips32架构的可执行文件
逆向分析
我们使用IDA打开文件
main()
我们观察main函数:
发现主要的处理过程应该在pre()和server_check_redemption_code()两个函数
pre()
pre()
函数中,只对flag的长度做了要求,为14字节,仍然通过server_check_redemption_code()
函数来判断flag,我们可以推断对flag的检查主要在该函数中
server_check_redemption_code()
这个函数主要功能在如下两个部分:
将输入映射到二维数组
这里我们a2
即是我们输入的flag,v10
是flag的长度。
我们主要关注循环中判断处的逻辑
当j == a2[i]
时,s[i][j] = i + 1
即s[i][a2[i]] = i + 1
, 即每一行a2[i]
的位置值为i + 1
。
计算偏移值
这里a1
是作为参数给定的字符串。
根据上一步我们计算出的表,为使v7 == v10
成立,我们需要使得a1
中存在子字符串为我们的flag,这样才能让v7
依次由0变化到v10,此时k
是子字符串结束的位置,那么k - v10 + 1
即是flag相对于a1
的偏移量。
我们再回到pre()
函数中调用server_check_redemption_code()
处:
这里要求返回不为-1,即是要求输入的flag为"Ninja Must Die 3 Is A Cruel Game, So Hard For Me"
的子串。
我们回到main()
函数中调用server_check_redemption_code()
处:
这里要求返回值为7,根据我们之前对server_check_redemption
的分析,即是要求flag的第一个字母是"I Love Ninja Must Die 3. Beautiful Art And Motive Operation Is Creative."
下标为7的字符,即第八个字符,而pre()
中又要求flag长度为14,因此flag为"Ninjia Must Die"
。
Flag
flag{Ninja Must Die}
感想
好用的工具是很重要的,比赛的时候我用的IDA版本不能反编译mips,就用ghidra了,可读性很差,最后没能做出来。