找到的博客对这道题的描述太少太跳了,其实这道题还是有不少细节的。
首先查壳,发现upx壳,同时是32位的elf文件
放到虚拟机里脱壳
upx -d filename
脱壳之后再用ida打开,看到如下的main函数
关键函数
其中有两个函数比较麻烦:pipe()和fork()
根据网上其他大佬对这两个函数的解释,我简单分析了一下在这里的作用
首先说一下pipe(管道)函数:
顾名思义的“管道”,相信用过linux操作系统的大都用过“|”(管道符号),这个函数在这意思也是相近的,pipe函数可以定义一个二元的数组,其中第一个元素只读,第二个元素只可作写操作
读取第一个元素的时候就会得到第二个元素的内容,然后第二个元素被清空。
再来说说fork(叉子)函数:
fork()函数可以复制出一个子进程,与父进程同时运行,但是对于fork()函数,调用一次,返回两次:在子进程中返回0;在父进程中返回子进程的进程ID;出错则返回-1。
可以这样想象,2个进程一直同时运行,而且步调一致,在fork之后,他们分别作不同的工作,也就是分岔了。这也是fork为什么叫fork(叉子)的原因。
这2个进程共享代码空间,但是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝,指令指针也完全相同,也就是说虽然是两个进程了,但是彼此之间几乎是相同的。
了解了上面这些,就不难理解这里把fork()的值附给v5,然后判断v5是否为零是什么意思了——父进程返回子进程的ID故不为零,执行if(!v5)中的操作,而子进程返回0,则不执行其中的操作。这时,管道pipe的作用就发挥出来了,这个pipe就成为了沟通两个进程的桥梁,将值从父进程传入子进程(将write进去的值传到子进程的read操作处,传给buf)
很多博客都忽略的lol函数解析问题
继续分析父进程,很自然地开始分析lol函数,但是打开之后就只有个下面这个
对照一下汇编,发现不对呀!这反编译出问题了。
(绿色是ida同步功能,显示第一条什么都没有的语句,竟然对应了这么多汇编,这明显就是没有反编译这一段,而且这些汇编明显是在作某种加密操作)
再往下翻一翻发现异常:
0x080486b0和0x080486b7处的汇编代码有明显联系
由于0x080486b0处对ebp+var_C的赋值,导致函数的固定跳转,这绿色的一段没有反编译很可能与此有关。
通过之前的学习,我知道在c语言的各种编辑器中,如果采取release版的输出,汇编代码都会因为O2优化而与源代码有较大差异,ida的反编译也会做类似操作。
在这里固定跳转会导致不可能运行到的代码干脆不进行反编译,这样相当于减少了工作量,优化了反编译时间。
但我寻思,这也不应该呀,不管最后固定跳转到下面的哪一个分支,上面这些数据处理的代码是必须运行的呀!但是仔细考究会发现,这上面的数据处理代码全在处理一两个变量。
然而如果固定跳转到80486d3的话,这操作压根和上面这处理半天的变量没关系,ida也很“聪明”地把没必要的数据处理给抛弃了。所以才有了我们刚开始分析看到的怪异函数内容。
那么综合以上分析,问题就在于这条mov指令,我决定把它nop掉试试。
再f5就发现代码出来了
接下来干的事情就很常规了,根据这里的加密代码对read进来的那串字符进行操作最后就能得到flag了,这一块是其他博客的重点内容,在此我就不赘述了。