本人是逆向界的一枚小学生,喜欢唱,跳,搜字符串,以及回收站,这个分析是好早前分析的了,如有不对的地方,还请各位大佬海涵
执行完以后这里在判断下栈够不够,够就继续循环取中间码,如果不够就在扩充,因为有可能执行被VM后的代码导致开始开辟0x200的栈不够,所以需要判断,如果不够就在开,然后把寄存器环境在从新拷贝
然后第二次可以看到把中间码3D拿出来,然后esi+1,然后跳过去
然后用EDI+2C,根据上面分析的可以看到EDI+2C是原本的EBP,然后将原本的EBP压入栈顶
然后在跳回来,取出中间码0x59,继续在跳走执行
然后取出刚刚压进去原来的EBP给EAX,然后把原来程序用的EBP-4,然后把eax MOV进去,然后就完成了push ebp的操作
然后在回来,这次拿出0x65
然后我们跳过来,在取中间码2C给EAX,然后把刚开始压入栈顶的EBP弹到虚拟机用的寄存器环境里的EBP
然后在回来,拿出9A
继续JMP过来,可以看到把栈顶又抬了0x4的大小
然后在回来,这次拿出中间码0x27
然后跳过来后把原来程序用的EBP给虚拟机的寄存器环境里+0X10的位置,因为刚才push了,然后EBP-4了,也就是说现在EBP是原来程序用的栈的栈顶, 然后这块虚拟机用的寄存器环境的栈顶也得移动栈针,也得-4,所以把他原来的拿过来赋值,
然后在跳回去,在拿出3D
跳过来拿出0x10给EAX,然后把EDI+10在压入栈顶,EDI+10就是上一步赋值过来的,这里看的迷糊的看最开始的分析,EDI+0X10就是真实程序用的ESP
继续跳回去,还是拿出3D,3D是压寄存器操作
继续执行,拿出2C,还是上面的操作,把EBP压入栈顶
然后拿出0xB5
JMP过去,因为刚才把EBP和ESP都压人栈顶了,这个时候访问栈顶,把ESP给EBP,完成mov EBP,ESP的操作,然后也把标志寄存器更新了一下
然后在跳回去,拿出0x65
JMP过来,拿出中间码0x65,根据上面的分析,0x65就是把当前栈顶的值更新到虚拟寄存器环境中
然后在跳回来,拿出9A,根据上面分析的,9A是抬栈
然后在回来,拿出中间码0x27
根据上面分析,0x27是把程序用的EBP给虚拟的ESP
在跳回去,拿出操作数0x9D,开始压栈
跳过来以后,可以看到在拿出操作数,压入当前的栈顶
然后在跳回去,拿出操作数CD
然后跳过来,从栈顶拿出刚压的,然后程序用的EBP抬4个字节,然后把字符串压进去,这个时候才完成了把一个字符串地址压入程序用的栈的操作
在跳回去,拿出操作数0x9A,因为刚才压到栈顶的字符串没用了,要弹走
在回来(执行完抬栈了),然后在回来看到又是一个抬栈,因为上面mov ebp,esp的时候,抬的时候只抬了一个,这个时候再把另外一个抬走
然后再回来,拿出操作数0x27,更新虚拟寄存器环境里的esp
这个时候在压栈
我们跟过来看下,可以看到压入printf的地址了
跳回来看到又是压栈
跳过来给可以看到给栈顶压了一个1
然后在跳回来,拿出操作数0x9D,继续压
调过来看到又压入0xFFFFFFFF
跳回来又看到压栈
这里又压了一个0xFFFFFFFF
跳回来这次拿到0x31
JMP过来,可以看到ADD esp,0x10,把栈顶刚压入的4个参数弹走,然后从新把printf的地址压进去,现在栈顶只有一个printf的地址
然后回来,拿出中间码0xC0
跳过来,然后把printf的地址给eax,然后在拿出中间码给edx
因为一直对强壳里面所谓的虚拟机感兴趣,但是反调试,反虚拟机等很烦人,所以当时找了个demo,只有虚拟机,没有其他乱七八糟的东西,当然这个虚拟机可能跟其他强壳比起来弱爆了,但是原理大致相通,也有可能现在的虚拟机都不这样玩了,但是作为学习来说还是能学到比较多的思路的,当时对壳还是比较感兴趣的,但是这个分析完以后,emmmmmmm
废话不多说,开搞,我们先运行程序,可以看到就是输出两段字符串,程序很简单,第二个输出字符串的函数是被VM了(虚拟机执行的函数我暂时称为被VM的代码),所以我们对第二个函数分析就行了
因为是控制台程序,所以我们直接定位到main函数,可以看到,框出的地方就是VM的代码了
还犹豫什么,F7进去盘他
这里进去看到压了一个参数,我们内存窗口看看
我们发现压入的是字符串,好了,今天的分析就到这了,我们下次再见,我还要去拯救苇名
好了,我们看下到底压了个什么鬼进去了
好家伙,这都是什么鬼,没字符串我还逆个屁啊
我们继续走,可以看到这里就是主要代码了,可以看到这里首先保存了一堆寄存器,紧接着两次开辟栈空间,我们上面说了,既然是虚拟机,那么寄存器环境和栈环境什么的,都要模拟出来,这里第一次抬0x200的大小是构造一个栈空间,第二次抬0x40是构造寄存器环境
往下走,可以看到给esi赋值了,就是刚才我们不知道什么鬼的那些东西,我们暂且把这些称为中间码,毕竟他也要面子的嘛
这里我画一个图,助于理解,第一次抬了0x200后把栈顶给了edi,那么说明虚拟机的栈是用edi来访问的,寄存器环境是用esp来访问的
继续走,我们看到拿出了第一个中间码,然后跳了
可以看到这里是在取开始压入的寄存器的值,然后给虚拟机的寄存器环境赋值
那么我们先记录下
EDI:VMContext栈底 寄存器环境
+0 EFLAGS
+4 EDX
+10 ESP
+18 ESI
+1C EBX
+20 EAX
+24 EDI
+28 ECX
+2C EBP
+0 EFLAGS
+4 EDX
+10 ESP
+18 ESI
+1C EBX
+20 EAX
+24 EDI
+28 ECX
+2C EBP
中间码
F6 初始化寄存器环境
执行完以后这里在判断下栈够不够,够就继续循环取中间码,如果不够就在扩充,因为有可能执行被VM后的代码导致开始开辟0x200的栈不够,所以需要判断,如果不够就在开,然后把寄存器环境在从新拷贝
然后第二次可以看到把中间码3D拿出来,然后esi+1,然后跳过去
跳过来以后拿出了中间码0x2C给EAX
然后用EDI+2C,根据上面分析的可以看到EDI+2C是原本的EBP,然后将原本的EBP压入栈顶
然后在跳回来,取出中间码0x59,继续在跳走执行
然后取出刚刚压进去原来的EBP给EAX,然后把原来程序用的EBP-4,然后把eax MOV进去,然后就完成了push ebp的操作
好家伙,折腾这么大一圈就完成了一个push ebp
我们都知道,函数进来得保存栈的环境,给当前函数开辟新的栈空间和栈底等,那么push ebp完了以后就该是 mov ebp,esp了,我们接着看这虚拟机的骚操作
然后在回来,这次拿出0x65
然后我们跳过来,在取中间码2C给EAX,然后把刚开始压入栈顶的EBP弹到虚拟机用的寄存器环境里的EBP
还是画个图,不然容易乱
然后在回来,拿出9A
继续JMP过来,可以看到把栈顶又抬了0x4的大小
然后在回来,这次拿出中间码0x27
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-5-19 18:41
被Buu编辑
,原因: