脱壳破解

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 完成