脱壳破解
OD载入 隐藏OD 忽略所有异常
这个壳是穿山甲4.0的 软件官方说是双层加壳 这个我自己也不知道怎么看 全当是吧:)
研究一晚上发现下三个断点就可以直接找到OEP了!因为这个软件是双进程先要转换为单进程!
下断bp OpenMutexA SHIFT+F9
7C80EC1B > 8BFF MOV EDI,EDI ; ntdll.7C930738//断在这里
7C80EC1D 55 PUSH EBP
7C80EC1E 8BEC MOV EBP,ESP
7C80EC20 51 PUSH ECX
7C80EC21 51 PUSH ECX
7C80EC22 837D 10 00 CMP DWORD PTR SS:[EBP+10],0
7C80EC26 56 PUSH ESI
7C80EC27 0F84 7A500300 JE kernel32.7C843CA7
此时堆栈
0012F798 00543DB8 /CALL 到 OpenMutexA 来自 游戏菜单.00543DB2
0012F79C 001F0001 |Access = 1F0001
0012F7A0 00000000 |Inheritable = FALSE
0012F7A4 0012FDD8 \MutexName = "75C:A5ED094E6" //0012FDD8
CTRL+G 00401000 输入代码
60 9C 68 D8 FD 12 00 33 C0 50 50 E8 2F DB 40 7C 9D 61 E9 04 DC 40 7C
在复制的代码处 新建EIP SHIFT+F9 再次断下 F2取消断点 CTRL+G->00401000 撤消修改
这样双进程就转换为单进程了!
此时 ALT+M 打开内存映象 在第一个.RSRC上 F2下断点 SHIFT+F9
断在这里 不管他 再ALT+M 在00401000 F2下断点 SHIFT+F9
7C93280D 66:8B50 0C MOV DX,WORD PTR DS:[EAX+C] //
7C932811 66:8955 B0 MOV WORD PTR SS:[EBP-50],DX
7C932815 8D70 10 LEA ESI,DWORD PTR DS:[EAX+10]
7C932818 8975 90 MOV DWORD PTR SS:[EBP-70],ESI
7C93281B 8B55 0C MOV EDX,DWORD PTR SS:[EBP+C]
7C93281E 66:F742 02 FFFF TEST WORD PTR DS:[EDX+2],0FFFF
7C932824 75 11 JNZ SHORT ntdll.7C932837
断在这里 现在就是要用F8慢慢跟了
00D8F68F 8B12 MOV EDX,DWORD PTR DS:[EDX]
00D8F691 8955 DC MOV DWORD PTR SS:[EBP-24],EDX
00D8F694 834D FC FF OR DWORD PTR SS:[EBP-4],FFFFFFFF
00D8F698 EB 11 JMP SHORT 00D8F6AB //跳
00D8F69A 6A 01 PUSH 1
00D8F69C 58 POP EAX
00D8F69D C3 RETN
00D8F69E 8B65 E8 MOV ESP,DWORD PTR SS:[EBP-18]
00D8F6A1 834D FC FF OR DWORD PTR SS:[EBP-4],FFFFFFFF
00D8F6A5 8B7D 08 MOV EDI,DWORD PTR SS:[EBP+8]
00D8F6A8 8B55 DC MOV EDX,DWORD PTR SS:[EBP-24]
00D8F6AB A1 E400DA00 MOV EAX,DWORD PTR DS:[DA00E4]
00D8F6B0 3190 88000000 XOR DWORD PTR DS:[EAX+88],EDX
00D8F6B6 A1 E400DA00 MOV EAX,DWORD PTR DS:[DA00E4]
00D8F6BB 3190 88000000 XOR DWORD PTR DS:[EAX+88],EDX
00D8F6C1 A1 E400DA00 MOV EAX,DWORD PTR DS:[DA00E4]
00D8F6C6 8B88 90000000 MOV ECX,DWORD PTR DS:[EAX+90]
00D8F6CC 3348 2C XOR ECX,DWORD PTR DS:[EAX+2C]
00D8F6CF 3348 18 XOR ECX,DWORD PTR DS:[EAX+18]
00D8F6D2 030D FC00DA00 ADD ECX,DWORD PTR DS:[DA00FC] ; 游戏菜单.00400000
00D8F6D8 8B17 MOV EDX,DWORD PTR DS:[EDI]
00D8F6DA 85D2 TEST EDX,EDX
00D8F6DC 75 1B JNZ SHORT 00D8F6F9 //跳
00D8F6DE FF77 18 PUSH DWORD PTR DS:[EDI+18]
00D8F6E1 FF77 14 PUSH DWORD PTR DS:[EDI+14]
00D8F6E4 FF77 10 PUSH DWORD PTR DS:[EDI+10]
00D8F6E7 8B90 90000000 MOV EDX,DWORD PTR DS:[EAX+90]
00D8F6ED 3350 40 XOR EDX,DWORD PTR DS:[EAX+40]
00D8F6F0 3350 04 XOR EDX,DWORD PTR DS:[EAX+4]
00D8F6F9 83FA 01 CMP EDX,1 //跳到这里 再F8
00D8F6FC 75 1E JNZ SHORT 00D8F71C
00D8F6FE FF77 04 PUSH DWORD PTR DS:[EDI+4]
00D8F701 FF77 08 PUSH DWORD PTR DS:[EDI+8]
00D8F704 6A 00 PUSH 0
00D8F706 FF77 0C PUSH DWORD PTR DS:[EDI+C]
00D8F709 8B90 90000000 MOV EDX,DWORD PTR DS:[EAX+90]
00D8F70F 3350 40 XOR EDX,DWORD PTR DS:[EAX+40]
00D8F712 3350 04 XOR EDX,DWORD PTR DS:[EAX+4]
00D8F715 2BCA SUB ECX,EDX
00D8F717 FFD1 CALL ECX ; 游戏菜单.004FE118 //这里就是OEP F7
F7后到这里
004FE118 55 PUSH EBP //这就是OEP 看样子是DELPHI的
004FE119 8BEC MOV EBP,ESP
004FE11B 83C4 F0 ADD ESP,-10
004FE11E B8 60DC4F00 MOV EAX,游戏菜单.004FDC60
004FE123 E8 8885F0FF CALL 游戏菜单.004066B0
004FE128 A1 B4315000 MOV EAX,DWORD PTR DS:[5031B4]
004FE12D 8B00 MOV EAX,DWORD PTR DS:[EAX]
004FE12F E8 9CA4F7FF CALL 游戏菜单.004785D0
OD不要关 -- 打开LordPE-修正映象大小--完全转存--保存为*.EXE文件 好作到这里先停着 从新加载一次目标文件 再重复作下面这个操作
下断bp OpenMutexA SHIFT+F9
7C80EC1B > 8BFF MOV EDI,EDI ; ntdll.7C930738//断在这里
7C80EC1D 55 PUSH EBP
7C80EC1E 8BEC MOV EBP,ESP
7C80EC20 51 PUSH ECX
7C80EC21 51 PUSH ECX
7C80EC22 837D 10 00 CMP DWORD PTR SS:[EBP+10],0
7C80EC26 56 PUSH ESI
7C80EC27 0F84 7A500300 JE kernel32.7C843CA7
此时堆栈
0012F798 00543DB8 /CALL 到 OpenMutexA 来自 游戏菜单.00543DB2
0012F79C 001F0001 |Access = 1F0001
0012F7A0 00000000 |Inheritable = FALSE
0012F7A4 0012FDD8 \MutexName = "75C:A5ED094E6" //0012FDD8
CTRL+G 00401000 输入代码
60 9C 68 D8 FD 12 00 33 C0 50 50 E8 2F DB 40 7C 9D 61 E9 04 DC 40 7C
在复制的代码处 新建EIP SHIFT+F9 再次断下 F2取消断点 CTRL+G->00401000 撤消修改
这样双进程就转换为单进程了
因为第一次保存的是没有跳过IAT加密的文件也就是 魔法跳转 没有修改 所以运行时会出问题
下面我们来修改 魔法跳转 并去跳过IAT加密 下断点 HE GetModuleHandleA SHIFT+F9运行
中断在
7C80B529 > 8BFF MOV EDI,EDI ; ntdll.7C930738 //断中这里;注意看堆栈
7C80B52B 55 PUSH EBP
7C80B52C 8BEC MOV EBP,ESP
7C80B52E 837D 08 00 CMP DWORD PTR SS:[EBP+8],0
7C80B532 74 18 JE SHORT kernel32.7C80B54C
7C80B534 FF75 08 PUSH DWORD PTR SS:[EBP+8]
7C80B537 E8 682D0000 CALL kernel32.7C80E2A4
7C80B53C 85C0 TEST EAX,EAX
此时堆栈返回
0012FF38 0060F4FB /CALL 到 GetModuleHandleA 来自 mz.0060F4F5
0012FF3C 00000000 \pModule = NULL
0012FF40 00000000
下面是每次 F9的堆栈返回
F9+1
0012E244 77C079B2 /CALL 到 GetModuleHandleA 来自 77C079AC
0012E248 77BE31BC \pModule = "kernel32.dll"
0012E24C 77C31A70
F9+2
0012EC78 7365D4A4 /CALL 到 GetModuleHandleA 来自 msctfime.7365D49E
0012EC7C 0012EC80 \pModule = "C:\WINDOWS\system32
tdll.dll"
0012EC80 575C3A43
F9+3
0012E884 77F45BB0 /CALL 到 GetModuleHandleA 来自 77F45BAA
0012E888 77F44FF4 \pModule = "KERNEL32.DLL"
0012E88C 00000001
F9+4
0012F6B8 005F8D7B /CALL 到 GetModuleHandleA 来自 mz.005F8D75
0012F6BC 00000000 \pModule = NULL
0012F6C0 001534B8
F9+5
0012967C 00D82FF1 /CALL 到 GetModuleHandleA 来自 00D82FEB //此时缓冲时间有点长
00129680 00D93D6C \pModule = "kernel32.dll"
00129684 00D95D7C ASCII "VirtualAlloc" //看到这个就差不多快到了
F9+6
0012967C 00D8300E /CALL 到 GetModuleHandleA 来自 00D83008
00129680 00D93D6C \pModule = "kernel32.dll"
00129684 00D95D70 ASCII "VirtualFree" //看到这个下一次就是返回时机了
F9+7
0012941C 00D75345 /CALL 到 GetModuleHandleA 来自 00D7533F //就是这里
00129420 00129558 \pModule = "kernel32.dll"
00129424 0012EBA4
调式--硬件断点--删除断点--ALT+F9返回
00D75345 8B0D 34CFD900 MOV ECX,DWORD PTR DS:[D9CF34] //返回到这里
00D7534B 89040E MOV DWORD PTR DS:[ESI+ECX],EAX
00D7534E A1 34CFD900 MOV EAX,DWORD PTR DS:[D9CF34]
00D75353 393C06 CMP DWORD PTR DS:[ESI+EAX],EDI
00D75356 75 16 JNZ SHORT 00D7536E
00D75358 8D85 DCFEFFFF LEA EAX,DWORD PTR SS:[EBP-124]
00D7535E 50 PUSH EAX
00D7535F FF15 90E0D800 CALL DWORD PTR DS:[D8E090] ; kernel32.LoadLibraryA
//不记得是哪位大哥说过 在返回的LoadLibraryA下面的第一个JE就是MJ了 呵呵
00D75365 8B0D 34CFD900 MOV ECX,DWORD PTR DS:[D9CF34]
00D7536B 89040E MOV DWORD PTR DS:[ESI+ECX],EAX
00D7536E A1 34CFD900 MOV EAX,DWORD PTR DS:[D9CF34]
00D75373 393C06 CMP DWORD PTR DS:[ESI+EAX],EDI
00D75376 0F84 2F010000 JE 00D754AB //这个就是我们要找的MJ了 JE改为JMP
00D7537C 33C9 XOR ECX,ECX
00D7537E 8B03 MOV EAX,DWORD PTR DS:[EBX]
00D75380 3938 CMP DWORD PTR DS:[EAX],EDI
00D75382 74 06 JE SHORT 00D7538A
这时我们再下另一个断点 BP GetTickCount SHIFT+F9 运行
中断在这里
7C8092AC > BA 0000FE7F MOV EDX,7FFE0000 //中断点
7C8092B1 8B02 MOV EAX,DWORD PTR DS:[EDX]
7C8092B3 F762 04 MUL DWORD PTR DS:[EDX+4]
7C8092B6 0FACD0 18 SHRD EAX,EDX,18
7C8092BA C3 RETN
F2取消断点 ALT+F9 返回程序
返回到这里
00D8C003 FF15 7C62D900 CALL DWORD PTR DS:[D9627C] ; kernel32.GetTickCount
00D8C009 8985 A4D4FFFF MOV DWORD PTR SS:[EBP-2B5C],EAX
00D8C00F 6A 01 PUSH 1
00D8C011 58 POP EAX
00D8C012 85C0 TEST EAX,EAX
00D8C014 0F84 A8030000 JE 00D8C3C2
看到代码
00D8C003 FF15 7C62D900 CALL DWORD PTR DS:[D9627C] ; kernel32.GetTickCount //这里了 一***有两处 向下找另一处
另一处代码
00D8C3C2 FF15 7C62D900 CALL DWORD PTR DS:[D9627C] ; kernel32.GetTickCount //另一处
00D8C3C8 2B85 A4D4FFFF SUB EAX,DWORD PTR SS:[EBP-2B5C]
00D8C3CE 8B8D A8D4FFFF MOV ECX,DWORD PTR SS:[EBP-2B58]
00D8C3D4 6BC9 32 IMUL ECX,ECX,32
00D8C3D7 81C1 D0070000 ADD ECX,7D0
00D8C3DD 3BC1 CMP EAX,ECX
00D8C3DF 76 07 JBE SHORT 00D8C3E8 //把这个改为 JMP 再F9运行
程序停在
00D8C977 8B8D 18C1FFFF MOV ECX,DWORD PTR SS:[EBP-3EE8]
00D8C97D 8B09 MOV ECX,DWORD PTR DS:[ECX]
00D8C97F 8901 MOV DWORD PTR DS:[ECX],EAX
00D8C981 8B85 18C1FFFF MOV EAX,DWORD PTR SS:[EBP-3EE8]
00D8C987 83C0 04 ADD EAX,4
00D8C98A 8985 18C1FFFF MOV DWORD PTR SS:[EBP-3EE8],EAX
00D8C990 ^ EB CA JMP SHORT 00D8C95C
00D8C992 96 XCHG EAX,ESI
00D8C993 66:87C9 XCHG CX,CX
00D8C996 96 XCHG EAX,ESI
现在我们再打开ImportREC--OEP处填写FE118 (004FE118-00400000)--自动查找IAT--获取输入表--显示无效的--剪切指针--修复转存文件--选中你用LORDPE保存的EXE文件 OK 完成