findKey 题解
前言
通常来说,一道题目的知识点少而散,通常本人是不写题解的,但是鉴于在解决这一问题的过程中,尝试汲取前人经验而未果,决定还是自己写一篇
初见流程
看成分
养成一个比较好的习惯,看看程序的表层有什么信息,所以这里通过die的命令行工具diec先看一眼有点什么:

目前的信息是:x86的32位架构,用C++编写写程序,所以一些奇特的语言特性基本没有,也没有壳之类的东西,所以逆向的前置工作就可以简化为直接IDA了
看行为
先把程序运行一下看看大概有点什么,只不过这题的程序似乎无法正常验证结果,打开没有什么可以交互的内容,所以也就不放图片了
于是进入第二部分,开始IDA静态分析,这边先尝试在函数视窗搜索了main但是没有结果,然后又去找了一下start函数
这个是有的,但是点开也就只看见了一堆API的调用和初始化,对于解题,基本没用
但是可以看见一个WinMain的调用于是也进去看了一眼
直观上来说,只是执行了一些窗口的展示的准备工作,以及一两个没有明显含义的函数(这里进去可以看到一个关键函数被赋值给了一项属性,但我当时没注意到而且也不清楚调用逻辑)
所以开始进行另一种路径的调查,按下Shift + F12调出String视窗,发现开头就有一个flag{}
于是通过交叉引用两次跳转后到达了调用这个字符串的text段
代码分析
花指令处理
本来打算直接看看反汇编函数,但突然发现这个部分只是被识别出了汇编指令,但是没有被定义为函数,显然这里出问题了,但是我们还是翻到这里函数的开头,也就是push ebp这样的字段处尝试按P定义函数
结局是:显然报错了![]()
于是我们到40191F处看看情况
注意到有不少的push offset byte_428C54,看上去比较可疑,因为有些花指令确实是通过重复某些嵌入代码来做干扰的
但是做事别太草率,我们还是先看报错写的function has undefined instruction/data at the specified address
这里提到在这个地址有未定义的数据或结构,但是显然汇编指令根本就没这个地址
那么为什么会提到这个?
答案在后面的跳转指令中jmp short near ptr loc_40191D+2,这个跳转中写到40191D+2其实也就是40191F,根据指令,IDA的分析会照本宣科去目标处分析行为
但这里的问题是,分析器被导向了一段指令的中间,因此线性分析的.text:0040191D push offset byte_428C54和跳转要求的从40191F分析指令冲突了
这里有一种可以让分析继续的解决方案:把191D和191E的字节内容修改为nop也就是90,因为x86的汇编指令是变长指令,也就是说一串字节的指令含义要看上下文有什么,同一个字节对应的含义是多样的
错误地处理
这样如果把前两个字节的指令当成某种运行时会被处理的刻意错误,提前清理掉,就可以让分析继续进行,代码会有另一种含义,如果能正常分析到retn,程序的原意就有可能被解读出来了
但是,这里都直接假设了前两个指令是错误的,无效的,而没有去理解程序的行为
这也是我想要抨击的一些题解的行为:完全无视程序实际含义,无脑乱删指令,看程序能分析了,就自以为是地往后走了,还敢写出来丢人现眼
有些人则是连jmp指令都没理会,直接就是看见两个push offset byte_428C54连一块就直接删除了其中一个然后说“就好了”,并堂而皇之地贴出删除后分析出的反汇编代码
并在后面的分析中直接写到某某函数对某字符串进行了什么操作,完全属于看了正确题解,然后猜个一知半解,自己根本没看函数行为,因为显然如果按照其前文处理方式,那个函数完全无法做到其后文描述的效果
大量这样乱写的题解完全是在污染网络信息质量,对他人学习相关内容造成误导
分析逻辑修正代码
这里合理的分析逻辑应该是注意到401939与40193B是一对连续的jz和jnz,类似一种if接else的跳转效果,而且两个跳转其实是同一个目标地址,属于永真跳转
换句话说:40193D的jmp完全是被无视的指令,仅仅在静态分析的时候会对IDA的分析流程造成干扰
所以我们事实上应该把这个部分(40193D - 40193F)改为nop来解决掉IDA分析时进入到一段指令半中央的问题

然后我们重新回到函数开头处按P重新分析和定义函数
函数行为分析
接下来要做的事情就是比较常规的函数分析,我们优先从有flag{}的片段上下文开始看
这里就不做过多赘述,sub_40101E的逻辑分析一下是将第一个参数的字符串md5加密并赋值给第三个参数指向的空间,在这里就是直接对自己加密并改写了
这里同时也是我刚才说到的地方,按照部分题解所说的修改方案,第三个参数根本不存在,又要到哪里正确分析后续逻辑?不过我不否认可以猜测到代码逻辑,但是前半段乱改后半段瞎猜,这显然不是合理的解题逻辑
后面则是sub_401005用第一个参数的字符串对第二个参数的字符串进行异或加密,具体内容不赘述
所以整个加密的逻辑就是输入一个1-6位的字符串,然后对输入进行md5哈希加密并与硬编码的、被SS异或加密的字符串比较,一致后再与另一端硬编码的字符串异或加密(由于最后显示的是加密后的内容,也许可以理解为解密)
所以我们要输入的内容就是异或解密的密钥Key了,逆向一下就能findKey,然后再异或解密获取flag为: flag{n0_Zu0_n0_die}
建议: 由于这里的1-6位字符没有具体限制,无法掩码攻击,推荐去线上网站的md5彩虹表直接查表,爆破所有可见字符大概有千百亿个可能的结果,要跑大概十多小时