查壳
用exeinfope查看,显示100%packed,这个文件貌似是签名不完整无法确定壳的类型是什么,但加了壳对静态分析的影响不太大(相对动态分析而言,动态分析的话貌似得手动脱壳,我对动态分析还不太会,等以后学会了再写文章来详细说)。
用IDA静态分析
进来以后翻找一下左边的函数窗口,没有发现main函数,这里提一个小技巧,SHITF + F12快捷键可以打开string window(字符串窗口),看看有没有什么线索。
果然在最下边一行发现了格式非常像flag的东东,双击它进入汇编界面。
后边的DATA_XRTF叫做交叉引用,就是字面意思啦,后边的这个抽象的函数sub_1400118C0里边用到了Str2这个字符串。双击这个函数进入到图形界面
这里可以用到一个IDA的神级功能“反编译”,按下F5,就可以得到伪代码,也就是反编译出来的代码,因为和源代码有出入,所以称为伪代码。
我们这里来一步步分析一下
signed __int64其实就是c语言里面大家很熟悉的long long类型,熟悉windows api的同学应该知道这是一个预定义类型
_#if defined (_INTEGRAL_MAX_BITS) && \
_INTEGRAL_MAX_BITS >= 64
typedef signed __int64 int64;
typedef unsigned __int64 uint64;
#else
#error __int64 type not supported
#endif
size_t同理其实是unsigned int类型
上边这一段说实话有些抽象哈,暂时水平看不懂啥意思,不过还好不影响解题。再往下走。
这里大家不要被第一个if语句给看迷糊了,可以看出来这个if语句是跳出for循环的关键,j和j_strlen是没有任何关系的。双击j_strlen(Str2)进入这个函数可以看到
返回值是strlen(Str),意思就是把Str2的字符串长度赋值给v2,v8每次循环加一,v8大于v2时跳出循环。再往下看,看到
111和48这两个数对IDA不熟的同学肯定就蒙了,告诉大家两个快捷键,按h可以把ascii码切换16进制和10进制,按r可以切换到字符,或者鼠标右键这个数字也可以切换
把他们切换成字符后就很明了了
如果为o就改为0。经过变换之后Str2={hell0_w0rld},再往下走。
黄色高亮的函数推理分析应该是printf这个函数(毕竟点进去看也看不明白这个函数在干嘛…)。sub_14001128F看着像是scanf函数,而且正好再“input the flag"后边。
然后是一个字符串比较函数strncmp,他有三个参数,最后一个参数是比较的字符数,而strcmp是两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇"\0"为止。当str1和str2相等时,返回值为0,加上一个!(非),相等时调用sub_1400111D1函数,输出this is the right flag!\n。
到这里这个程序的大概逻辑就理清了,str2的值经过o向0的变化,就得到了str1的值
那么str1就是{hell0_w0rld}咯,flag就得到啦。