from:http://www.52pojie.cn/forum.php?mod=viewthread&tid=120450
你可以怀疑这个方法,真的假的一试就知道,如果不知道怎么找,可以把你的试验品传到网盘,有空我把针对你试验品的步骤帖给你。
有的OEP被抽了代码的只能找到伪OEP,也就是被抽掉之后剩下的头部地址。
你也可以直接无视这个方法,对你少一个选择,对我没有任何损失。
首先讲一下方法的原理。
每一个程序都是由无数个CALL加其参数组成了,在程序里,每一个CALL都是有返回地址的。当在程序领空的时候,返回到不能返回的时候。这个返回地址就是在程序的main函数里。
所以只要找到了最终程序领空的返回地址,也就找到了main函数的地方。main函数的起始位置也就是oep了。而OD是会记录每一个返回地址的。我们用OD就可以迅速找到OEP了,而且适合所有壳(除了有注册框的壳,因为你不过掉注册框就到不了程序的领空)。
下面以一个加ZP的壳为例(无注册框),来说明如何操作。
1. OD载入程序,入口点为
1 004711DA > E8 01000000 call 演示程序.004711E0 2 004711DF 5C pop esp 3 004711E0 872C24 xchg dword ptr ss:[esp],ebp 4 004711E3 8DAD 9CFEFFFF lea ebp,dword ptr ss:[ebp-164] 5 004711E9 872C24 xchg dword ptr ss:[esp],ebp 6 004711EC ^ E9 8AFEFFFF jmp 演示程序.0047107B 7 004711F1 B0 1D mov al,1D 8 004711F3 ^ 7C E8 jl short 演示程序.004711DD
2.直接shift+F9让程序跑起来,然后来到OD的堆栈窗口。直接拉到最下面。
1 0012FF54 0012FFA8 2 0012FF58 0044D294 演示程序.0044D294 3 0012FF5C 00010264 UNICODE "nclude=D:\Program Files\Microsoft Visual Studio\VC98\atl\include;D:\Program Files\Microsoft Visual S" 4 0012FF60 00000113 5 0012FF64 00000001 6 0012FF68 00000000 7 0012FF6C 000743DC 8 0012FF70 00000265 9 0012FF74 000002F8 10 0012FF78 7FFD7000 11 0012FF7C 0044D4A7 演示程序.0044D4A7 12 0012FF80 0012FF8C 指向下一个 SEH 记录的指针 13 0012FF84 0044D4B1 SE处理程序 14 0012FF88 0012FFA8 15 0012FF8C 0012FFB4 指向下一个 SEH 记录的指针 16 0012FF90 0044D4EA SE处理程序 17 0012FF94 0012FFA8 18 0012FF98 7C930208 ntdll.7C930208 19 0012FF9C FFFFFFFF 20 0012FFA0 7FFD7000 21 0012FFA4 00B817C0 22 0012FFA8 0012FFC0 23 0012FFAC 0044EDA0 演示程序.0044EDA0 24 0012FFB0 7FFD7000 25 0012FFB4 0012FFE0 指向下一个 SEH 记录的指针 26 0012FFB8 004039B0 SE处理程序 27 0012FFBC 0012FFC0 28 0012FFC0 0012FFF0 29 0012FFC4 7C817067 返回到 kernel32.7C817067 30 0012FFC8 7C930208 ntdll.7C930208 31 0012FFCC FFFFFFFF 32 0012FFD0 7FFD7000 33 0012FFD4 8054C6B8 34 0012FFD8 0012FFC8 35 0012FFDC 895C0020 36 0012FFE0 FFFFFFFF SEH 链尾部 37 0012FFE4 7C839AC0 SE处理程序 38 0012FFE8 7C817070 kernel32.7C817070 39 0012FFEC 00000000 40 0012FFF0 00000000 41 0012FFF4 00000000 42 0012FFF8 004711DA offset 演示程序.<ModuleEntryPoint> 43 0012FFFC 00000000
从下往上,找到第一个返回到程序领空的地址。
0012FFAC 0044EDA0 演示程序.0044EDA0
然后汇编窗口中跟随,来到这里:
1 0044EDA0 E8 db E8 2 0044EDA1 7B db 7B ; CHAR '{' 3 0044EDA2 4F db 4F ; CHAR 'O' 4 0044EDA3 FB db FB 5 0044EDA4 FF db FF
3. 点右键,选择分析-->从模块中删除分析,变成这样:
1 0044ED6B E8 586EFBFF call 演示程序.00405BC8 2 0044ED70 A1 D0FF4400 mov eax,dword ptr ds:[44FFD0] 3 0044ED75 8B00 mov eax,dword ptr ds:[eax] 4 0044ED77 E8 F8E5FFFF call 演示程序.0044D374 5 0044ED7C 8B0D AC004500 mov ecx,dword ptr ds:[4500AC] ; 演示程序.00451BD0 6 0044ED82 A1 D0FF4400 mov eax,dword ptr ds:[44FFD0] 7 0044ED87 8B00 mov eax,dword ptr ds:[eax] 8 0044ED89 8B15 14E94400 mov edx,dword ptr ds:[44E914] ; 演示程序.0044E960 9 0044ED8F E8 F8E5FFFF call 演示程序.0044D38C 10 0044ED94 A1 D0FF4400 mov eax,dword ptr ds:[44FFD0] 11 0044ED99 8B00 mov eax,dword ptr ds:[eax] 12 0044ED9B E8 6CE6FFFF call 演示程序.0044D40C 13 0044EDA0 E8 7B4FFBFF call 演示程序.00403D20 ; 刚才的位置
4.我们往上找
1 0044ED5B 0058 EB add byte ptr ds:[eax-15],bl 2 0044ED5E 44 inc esp 3 0044ED5F 0055 8B add byte ptr ss:[ebp-75],dl 4 0044ED62 EC in al,dx 5 0044ED63 83C4 F0 add esp,-10 6 0044ED66 B8 80EB4400 mov eax,演示程序.0044EB80 7 0044ED6B E8 586EFBFF call 演示程序.00405BC8 8 0044ED70 A1 D0FF4400 mov eax,dword ptr ds:[44FFD0] 9 0044ED75 8B00 mov eax,dword ptr ds:[eax] 10 0044ED77 E8 F8E5FFFF call 演示程序.0044D374 11 0044ED7C 8B0D AC004500 mov ecx,dword ptr ds:[4500AC] ; 演示程序.00451BD0 12 0044ED82 A1 D0FF4400 mov eax,dword ptr ds:[44FFD0] 13 0044ED87 8B00 mov eax,dword ptr ds:[eax] 14 0044ED89 8B15 14E94400 mov edx,dword ptr ds:[44E914] ; 演示程序.0044E960 15 0044ED8F E8 F8E5FFFF call 演示程序.0044D38C 16 0044ED94 A1 D0FF4400 mov eax,dword ptr ds:[44FFD0] 17 0044ED99 8B00 mov eax,dword ptr ds:[eax] 18 0044ED9B E8 6CE6FFFF call 演示程序.0044D40C 19 0044EDA0 E8 7B4FFBFF call 演示程序.00403D20 ; 刚才的位置
这里就是OEP的头部了。如果你熟悉各种语言的入口特征的话,马上就应该知道OEP的位置了。
看这里
1 0044ED5F 0055 8B add byte ptr ss:[ebp-75],dl 2 0044ED62 EC in al,dx
其实这个就是被混淆了的OEP。他只是在558B的前面加了个00, 我们想办法把00去掉。
00的地址是0044ED5F,那么55的地址是0044ED60(即是加1),我们CTRL+G,输入0044ED60,回车。我们的OEP就回来了,如下:
1 0044ED60 55 push ebp ; oep 2 0044ED61 8BEC mov ebp, esp 3 0044ED63 83C4 F0 add esp, -10 4 0044ED66 B8 80EB4400 mov eax, 0044EB80 5 0044ED6B E8 586EFBFF call 00405BC8 6 0044ED70 A1 D0FF4400 mov eax, dword ptr [44FFD0] 7 0044ED75 8B00 mov eax, dword ptr [eax] 8 0044ED77 E8 F8E5FFFF call 0044D374 9 0044ED7C 8B0D AC004500 mov ecx, dword ptr [4500AC] ; 演示程序.00451BD0 10 0044ED82 A1 D0FF4400 mov eax, dword ptr [44FFD0] 11 0044ED87 8B00 mov eax, dword ptr [eax] 12 0044ED89 8B15 14E94400 mov edx, dword ptr [44E914] ; 演示程序.0044E960 13 0044ED8F E8 F8E5FFFF call 0044D38C 14 0044ED94 A1 D0FF4400 mov eax, dword ptr [44FFD0] 15 0044ED99 8B00 mov eax, dword ptr [eax] 16 0044ED9B E8 6CE6FFFF call 0044D40C 17 0044EDA0 E8 7B4FFBFF call 00403D20
文中所用程序的下载地址:https://files.cnblogs.com/tk091/test3.zp.rar
至于找到oep后如何脱壳,这个就难说了,下面是我的脱壳过程。
对oep下硬件断点,重新载入后运行,删除分析模块。
od插件dump分别两个。
运行实际的程序,打开pe修复工具,填入oep,
显示无效的函数,全部无效,选择等级三修复即可,要几个几个的修复,如果一起修复则会死掉。