初来看雪,在潜水许久之后我也来发发帖子,希望对跟我一样的初学者能有一些帮助
为了不让软件的作者告我侵权,本次所用的软件就是微软的扫雷游戏,用小P查一下,使用C++编译的(Microsoft Visual C++ 7.0 Method2 [Debug])先用ASPack加壳,具体过程我就不多说了,这不是重点。加完后再用小P查,变为(ASPack 2.12 -> Alexey Solodovnikov)
现在开始我们的脱壳。
方法一 纯手工单步步入发
用OD载入,开进入后显示如下:
01020001 > 60 PUSHAD
01020002 E8 03000000 CALL winmine.0102000A
01020007 - E9 EB045D45 JMP 465F04F7
0102000C 55 PUSH EBP
0102000D C3 RETN
0102000E E8 01000000 CALL winmine.01020014
01020013 EB 5D JMP SHORT winmine.01020072
01020015 BB EDFFFFFF MOV EBX,-13
0102001A 03DD ADD EBX,EBP
0102001C 81EB 00000200 SUB EBX,20000
01020022 83BD 22040000 0>CMP DWORD PTR SS:[EBP+422],0
01020029 899D 22040000 MOV DWORD PTR SS:[EBP+422],EBX
我们看到,第二行就有一个Call,用来调用子程序,接着F8到第二行,用F7跟进。这是手工单步步入最关键的地方,在遇到刚开始就出现的Call,一定要F7跟进。
进入后显示如下:
0102000A 5D POP EBP ; winmine.01020007
0102000B 45 INC EBP
0102000C 55 PUSH EBP
0102000D C3 RETN
0102000E E8 01000000 CALL winmine.01020014
01020013 EB 5D JMP SHORT winmine.01020072
我们在第五行又遇到了一个Call,继续用F8到第五行,然后F7跟进,也许有的初学者会说上面还有一个retn,但你在步过后发现,他在跳上后还是指向了0102000E处,或者,你如果不放心,直接在0102000E处F4(即运行的选定位置处),一样可以。
然后我们就不要在步入了,,因为我们在步入之后发现:
01020014 5D POP EBP ; winmine.01020013
01020015 BB EDFFFFFF MOV EBX,-13
0102001A 03DD ADD EBX,EBP
0102001C 81EB 00000200 SUB EBX,20000
01020022 83BD 22040000 0>CMP DWORD PTR SS:[EBP+422],0
01020029 899D 22040000 MOV DWORD PTR SS:[EBP+422],EBX
0102002F 0F85 65030000 JNZ winmine.0102039A
01020035 8D85 2E040000 LEA EAX,DWORD PTR SS:[EBP+42E]
0102003B 50 PUSH EAX
0102003C FF95 4D0F0000 CALL DWORD PTR SS:[EBP+F4D]
离我们最近的call也有第十行,所以就不要在步入了,一般ASPack的壳两处Call就可以了,至于别的壳也是差不多。所以我们就一直F8下去,此时不要心急,不要点得太快,因为最关键的在下面:
0102012D 0BC9 OR ECX,ECX
0102012F 74 2E JE SHORT winmine.0102015F
01020131 78 2C JS SHORT winmine.0102015F
01020133 AC LODS BYTE PTR DS:[ESI]
01020134 3C E8 CMP AL,0E8
01020136 74 0A JE SHORT winmine.01020142
01020138 EB 00 JMP SHORT winmine.0102013A
0102013A 3C E9 CMP AL,0E9
0102013C 74 04 JE SHORT winmine.01020142
0102013E 43 INC EBX
0102013F 49 DEC ECX
01020140 ^ EB EB JMP SHORT winmine.0102012D
01020142 8B06 MOV EAX,DWORD PTR DS:[ESI]
看见没有,01020140处有一个向上的跳转,指向0102012D,我们此刻点击它的下一处地址01020142处,按F4。然后接着一路F8,如果有向上的跳转,就用上面的方法绕过。
经过了N次F8和F4,我们终于到了这里:
010203A9 8985 A8030000 MOV DWORD PTR SS:[EBP+3A8],EAX
010203AF 61 POPAD
010203B0 75 08 JNZ SHORT winmine.010203BA
010203B2 B8 01000000 MOV EAX,1
010203B7 C2 0C00 RETN 0C
010203BA 68 213E0001 PUSH winmine.01003E21
010203BF C3 RETN
接着按F8到010203BF(RETN)上,再按一下,就跳到程序真正的入口了,在上面点右键——>用Ollydump脱壳调试进程,再然后点脱壳,保存就行了。
完事后用小P检查一下——Microsoft Visual C++ 7.0 Method2 [Debug],脱壳成功!
总结:上述方法是利用绕过壳的跳转找到软件的OEP的,相当于步过了壳的所有代码,在面对一般的壳,如ASPack,UPX是很好用,因为它们的壳的代码不长,如果是一些高级壳,F8会让你按到手软的。
方法二 一步跳转法
还记得我们用第一种方法是最后的代码吗?
010203A9 8985 A8030000 MOV DWORD PTR SS:[EBP+3A8],EAX
010203AF 61 POPAD
010203B0 75 08 JNZ SHORT winmine.010203BA
010203B2 B8 01000000 MOV EAX,1
010203B7 C2 0C00 RETN 0C
010203BA 68 213E0001 PUSH winmine.01003E21
010203BF C3 RETN
看到没有,010203AF处为POPAD,那么有人就想到了,能不能用查找命令直接找到popad,然后自然就找到retn呢?答案是肯定的。
当这个方法也比较局限,我只在UPX和ASPack上用过。
用OD载入扫雷,按CTRL+F(查找命令),在弹出的查找命令框中输入popad,然后点查找,注意不要选“整个块”,点击“查找”,再查找到一个后,发现不是我们想要的,按ctrl+L(查找下一个),直到找到我们要的popad,然后用F8到RETN,接着脱壳。
总结:这种方法利用了retn附近的特殊码来进行查找,从而找到retn,但具有一定的局限性,我也是只在UPX和ASPack壳上用过,大家自己看着办吧。
方法三 ESP追入法
看看我们的壳的开头:
01020001 > 60 PUSHAD
01020002 E8 03000000 CALL winmine.0102000A
01020007 - E9 EB045D45 JMP 465F04F7
0102000C 55 PUSH EBP
0102000D C3 RETN
0102000E E8 01000000 CALL winmine.01020014
01020013 EB 5D JMP SHORT winmine.01020072
01020015 BB EDFFFFFF MOV EBX,-13
0102001A 03DD ADD EBX,EBP
0102001C 81EB 00000200 SUB EBX,20000
01020022 83BD 22040000 0>CMP DWORD PTR SS:[EBP+422],0
01020029 899D 22040000 MOV DWORD PTR SS:[EBP+422],EBX
注意这句:01020001 > 60 PUSHAD
众所周知,pushad是进栈语令,那么,有进就有出,出时就到了程序入口,所以,我们先按一下F8让它进栈,接着在01020002上,我们看右边的寄存器,ESP后面是红的值0007FFA4,既有数据进栈,我们在命令行(最下面)里输入dd(显示堆栈格式数据) 0007FFA4,然后按回车,在左下方弹出的地址上点右键——>断点——>硬盘访问——>字。
然后按F9让程序运行,我们可以看见,直接到了RETN。
总结:这种方法主要是利用第一句中的pushad,因为有了入栈,我们才有了后面通过在ESP上下断的思路,大家在以后见到第一句是入栈命令,如:pushad,pushfd的,都可以用这种方法,看到右侧的寄存器中ESP后数值为红色,既有数据进栈。
第四种:利用OD自己检测
载入扫雷,在“调试”——>“调试选项”中有一“SFX”选项卡,中间有一项——“字节方式跟踪真正入口处”,我当时有点被小雷了,照这么说OD可以自己查找OEP,所以我就选了这一项,结果……OD做到了,在弹出的入口处脱壳,一样可以成功。我真的被雷了……
总结:这种方法比较诡异,我没在多数的壳上试过,但也是种偷懒的方法,就是有时速度有点慢。
声明:上述方法大部分都是网上常用的方法,所以你如果说我抄袭我不想说什么话来辩解,但这篇文章是我一个字一个字敲出来的,这四种方法我也是个试了不下十遍的,这点我可以凭良心保证,虽然这年头良心不值钱。我只是希望上述方法对跟我一样的初学者有一定的帮助,还有我的总结,我觉得这些心得比方法更重要。要说的就是这么多,不想辩解什么。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!