吾爱破解穿山甲脱壳系列
来论坛,总想为大家奉献点什么.于是,为了大家共同进步,特别推出穿山甲脱壳系列,以后,我还会为大家做其他的猛壳系列.系列之一:单进程标准版,脱文在1楼
系列之二:双进程标准版,5楼,脱文在6楼
系列之三:CopyMem-ll +Debug-Blocke,15楼,脱文在16楼(等待更新)
系列之四:单进程标准版+Enable Import Table Elimination+Enable Strategic Code Splicing,第34楼
脱文在35楼(等待更新)
首先是系列1:单进程标准版
大家有兴趣的可以拿去练习一下.
本帖里禁止水帖,只交流脱壳经验!谢谢合作,.我会长期更新! 占楼贴脱文.
由于是标准版加的壳,所以比较简单。
首先忽略所有的异常,隐藏下OD
00544000 > 60 pushad //停在这里
00544001E8 00000000 call Notepad.00544006
005440065D pop ebp
0054400750 push eax
0054400851 push ecx
005440090FCA bswap edx
0054400BF7D2 not edx
0054400D9C pushfd
0054400EF7D2 not edx
005440100FCA bswap edx
00544012EB 0F jmp short Notepad.00544023
下面来处理IAT。
方法一:
下断点:he GetModuleHandleA+9,SHIFT+F9多次后,看堆栈窗口,找适当的时机返回。
第一次:
0012943C /0012EB50
00129440 |00DA5805 返回到 00DA5805 来自 kernel32.GetModuleHandleA
00129444 |00DD1BA8 ASCII "kernel32.dll"
00129448 |00DD2B30 ASCII "VirtualAlloc"
0012944C |40C24480
第二次:
0012943C /0012EB50
00129440 |00DA5823 返回到 00DA5823 来自 kernel32.GetModuleHandleA
00129444 |00DD1BA8 ASCII "kernel32.dll"
00129448 |00DD2B24 ASCII "VirtualFree"
0012944C |40C24480
第三次:
00129188 /00129440
0012918C |00D88064 返回到 00D88064 来自 kernel32.GetModuleHandleA
00129190 |00129308 ASCII "kernel32.dll"
00129194 |00000000
到了第三次,明显缓冲比前几次到,所以到了时机返回了。
(具体的时机的判断,可以根据缓冲大小来判断,也可以通过一些标志来进行判断:如:看到VirtualAlloc和VirtualFree函数后,再一次SHIFT+F9,看到kernel32.dll就到了返回时机了,当然,具体的还是得自己去把握!)
接着,取消断点,ALT+F9返回。
00D880648B55 F4 mov edx,dword ptr ss: //返回到这里
00D880678B0D 84EFDD00mov ecx,dword ptr ds:
00D8806D890491 mov dword ptr ds:,eax
00D880708B55 F4 mov edx,dword ptr ss:
00D88073A1 84EFDD00 mov eax,dword ptr ds:
00D88078833C90 00 cmp dword ptr ds:,0
00D8807C75 5C jnz short 00D880DA
00D8807E8B4D F8 mov ecx,dword ptr ss:
00D880818B51 08 mov edx,dword ptr ds:
00D8808483E2 02 and edx,2
00D8808774 38 je short 00D880C1
00D88089B8 0F000000 mov eax,0F
00D8808EC1E0 02 shl eax,2
00D880918B0D 04CBDD00mov ecx,dword ptr ds: ; Notepad.00554370
00D880978B15 04CBDD00mov edx,dword ptr ds: ; Notepad.00554370
00D8809D8B35 04CBDD00mov esi,dword ptr ds: ; Notepad.00554370
00D880A38B5E 18 mov ebx,dword ptr ds:
00D880A6335A 10 xor ebx,dword ptr ds:
00D880A9331C01 xor ebx,dword ptr ds:
00D880AC83E3 10 and ebx,10
00D880AFF7DB neg ebx
00D880B11BDB sbb ebx,ebx
00D880B3F7DB neg ebx
00D880B50FB6C3 movzx eax,bl
00D880B885C0 test eax,eax
00D880BA75 05 jnz short 00D880C1
00D880BC ^ E9 1BFFFFFF jmp 00D87FDC
00D880C18D8D C8FEFFFFlea ecx,dword ptr ss:
00D880C751 push ecx
00D880C8FF15 88F0DC00call dword ptr ds: ; kernel32.LoadLibraryA
00D880CE8B55 F4 mov edx,dword ptr ss:
00D880D18B0D 84EFDD00mov ecx,dword ptr ds:
00D880D7890491 mov dword ptr ds:,eax
00D880DA8B55 F4 mov edx,dword ptr ss:
00D880DDA1 84EFDD00 mov eax,dword ptr ds:
00D880E2833C90 00 cmp dword ptr ds:,0
00D880E675 05 jnz short 00D880ED //NOP掉!
00D880E8 ^ E9 EFFEFFFF jmp 00D87FDC
00D880EDC785 BCFEFFFF 0>mov dword ptr ss:,0
00D880F7C785 C0FEFFFF 0>mov dword ptr ss:,0
00D881018B4D F8 mov ecx,dword ptr ss:
00D881048B51 04 mov edx,dword ptr ds:
00D881078995 C4FEFFFFmov dword ptr ss:,edx
下面我们找magic jmp!
首先找到kernel32.LoadLibraryA这个标志,这个标志下的第一个跳转就是所谓的magic jmp
一般情况下,这个跳转比较大的话,就改为jmp,而跳转比较小的话,就改nop
很明显,这个例子里,应该把magic jmp(不知道还该不该叫magic jmp)给nop掉。
至此,IAT处理完毕。
方法二:
下断点:
bp VirtualProtect,SHIFT+F9,观察堆栈,找适当的时机返回
一般返回的时机就是:当Size的值小于1000,且NewProtect为PAGE_READWRITE时
0012943800DAACFD /CALL 到 VirtualProtect 来自 00DAACF7
0012943C004C7034 |Address = Notepad.004C7034
0012944000000018 |Size = 18 (24.)
0012944400000004 |NewProtect = PAGE_READWRITE
001294480012BFF0 \pOldProtect = 0012BFF0
0012944C40C24480
对于本例,这个时候就可以返回了。
取消断点,ALT+F9返回。
00DAACFD6A 14 push 14 //返回到这里
00DAACFFE8 72CF0000 call 00DB7C76
00DAAD0483C4 04 add esp,4
00DAAD078985 84ABFFFFmov dword ptr ss:,eax
00DAAD0D83BD 84ABFFFF 0>cmp dword ptr ss:,0
00DAAD1474 59 je short 00DAAD6F
00DAAD168B0D 4468DE00mov ecx,dword ptr ds:
00DAAD1C898D 10AAFFFFmov dword ptr ss:,ecx
00DAAD228B95 74D8FFFFmov edx,dword ptr ss:
00DAAD280395 78D3FFFFadd edx,dword ptr ss:
00DAAD2E8B85 84ABFFFFmov eax,dword ptr ss:
00DAAD348910 mov dword ptr ds:,edx
00DAAD368B8D 9CD4FFFFmov ecx,dword ptr ss:
00DAAD3CC1E1 02 shl ecx,2
接着CTRL+F,搜索push 100(注意,去掉整个段块前面的勾)
00DAAF7068 00010000 push 100 //搜索到这里
00DAAF758D8D 40C1FFFFlea ecx,dword ptr ss:
00DAAF7B51 push ecx
00DAAF7C8B95 40C2FFFFmov edx,dword ptr ss:
00DAAF828B02 mov eax,dword ptr ds:
00DAAF8450 push eax
00DAAF85E8 8677FBFF call 00D62710 //跟随进去吧!
00DAAF8A83C4 0C add esp,0C
00DAAF8D8D8D 40C1FFFFlea ecx,dword ptr ss:
接着就找下面的CALL跟随,把段首改retn
00D6270CCC int3
00D6270DCC int3
00D6270ECC int3
00D6270FCC int3
00D6271055 push ebp //跟随到这里,把这里改成retn
00D627118BEC mov ebp,esp
00D6271383EC 2C sub esp,2C
00D62716833D 00B6DD00 0>cmp dword ptr ds:,0
00D6271D75 59 jnz short 00D62778
00D6271FC745 EC 6D7B9F2>mov dword ptr ss:,2B9F7B6D
00D6272668 00010000 push 100
00D6272BE8 46550500 call 00DB7C76
00D6273083C4 04 add esp,4
OK,这样处理后,也避开的IAT的加密
下面就去OEP!
下断点:bp CreateThread,SHIFT+F9
7C810637 > 8BFF mov edi,edi //断在这里
7C81063955 push ebp
7C81063A8BEC mov ebp,esp
7C81063CFF75 1C push dword ptr ss:
7C81063FFF75 18 push dword ptr ss:
7C810642FF75 14 push dword ptr ss:
7C810645FF75 10 push dword ptr ss:
7C810648FF75 0C push dword ptr ss:
7C81064BFF75 08 push dword ptr ss:
7C81064E6A FF push -1
7C810650E8 D7FDFFFF call kernel32.CreateRemoteThread
7C8106555D pop ebp
7C810656C2 1800 retn 18
取消断点,ALT+F9返回,接着就单步跟踪吧!
00DAF7858338 01 cmp dword ptr ds:,1
00DAF78875 40 jnz short 00DAF7CA
00DAF78A8B0D 04CBDD00mov ecx,dword ptr ds: ; Notepad.00554370
00DAF7908B15 04CBDD00mov edx,dword ptr ds: ; Notepad.00554370
00DAF7968B41 14 mov eax,dword ptr ds:
00DAF7993342 10 xor eax,dword ptr ds:
00DAF79C8B0D 04CBDD00mov ecx,dword ptr ds: ; Notepad.00554370
00DAF7A23341 44 xor eax,dword ptr ds:
00DAF7A58945 DC mov dword ptr ss:,eax
00DAF7A88B55 08 mov edx,dword ptr ss:
00DAF7AB8B42 04 mov eax,dword ptr ds:
00DAF7AE50 push eax
00DAF7AF8B4D 08 mov ecx,dword ptr ss:
00DAF7B28B51 08 mov edx,dword ptr ds:
00DAF7B552 push edx
00DAF7B66A 00 push 0
00DAF7B88B45 08 mov eax,dword ptr ss:
00DAF7BB8B48 0C mov ecx,dword ptr ds:
00DAF7BE51 push ecx
00DAF7BF8B55 F4 mov edx,dword ptr ss:
00DAF7C22B55 DC sub edx,dword ptr ss:
00DAF7C5FFD2 call edx //OK,跟踪到这,F7进去后,就来到OEP了!
00DAF7C78945 FC mov dword ptr ss:,eax
00DAF7CA8B45 FC mov eax,dword ptr ss:
00DAF7CD5E pop esi
00DAF7CE8BE5 mov esp,ebp
00DAF7D05D pop ebp
00DAF7D1C3 retn
下面就来到OEP了!
004A2ADCE8 B6A40000 call Notepad.004ACF97 //OEP
004A2AE1 ^ E9 16FEFFFF jmp Notepad.004A28FC
004A2AE6CC int3
004A2AE7CC int3
004A2AE8CC int3
004A2AE9CC int3
004A2AEACC int3
004A2AEBCC int3
004A2AECCC int3
004A2AEDCC int3
004A2AEECC int3
004A2AEFCC int3
004A2AF08B4C24 04 mov ecx,dword ptr ss:
004A2AF4F7C1 03000000test ecx,3
004A2AFA74 24 je short Notepad.004A2B20
接下来的工作就dump和修复了,具体不多说了。
修复时候,找到IAT后,把无效的全部剪掉即可!
好的,希望大家都能学会吧! 据说现在坛子大部分人都还是初级入门啊。。
这种猛壳。。。 看不懂。。
支持一个。。继续学习。。收藏了``长期关注这个帖子` 超人果然NB
壳王名不虚传 支持超人,感谢你的大作啊!
系列二
接着来个系列之二:双进程标准壳占楼,帖脱文
穿山甲之双进程标准壳
OD载入后,忽略所有异常,隐藏下OD
下面开始脱壳:
首先,处理双进程
方法一:
下断点:bp OpenMutexA,SHIFT+F9
7C80EA1B >8BFFmov edi,edi //断在这里
7C80EA1D55push ebp
7C80EA1E8BECmov ebp,esp
7C80EA2051push ecx
7C80EA2151push ecx
7C80EA22837D 10 00cmp dword ptr ss:,0
7C80EA2656push esi
7C80EA270F84 9F540300 je kernel32.7C843ECC
7C80EA2D64:A1 18000000mov eax,dword ptr fs:
7C80EA33FF75 10 push dword ptr ss:
观察下堆栈窗口:
0012F6F8 00517DDA/CALL 到 OpenMutexA 来自 Notepad.00517DD4
0012F6FC 001F0001|Access = 1F0001
0012F700 00000000|Inheritable = FALSE
0012F704 0012FD54\MutexName = "BAC::DA59F0CE25" ★注意下这里的数据,一会有用!
ALT+M,打开内存镜像
,观察.code段的地址为:00401000
接着,CTRL+G,来到00401000
输入下面的代码:
0040100060pushad
004010019Cpushfd
0040100268 54FD1200 push 12FD54//这里的数值就是刚才所要记录的数值!
0040100733C0xor eax,eax
0040100950push eax
0040100A50push eax
0040100BE8 2FD9407C call kernel32.CreateMutexA
004010109Dpopfd
0040101161popad
00401012- E9 04DA407C jmp kernel32.OpenMutexA
60 9C 68 54 FD 12 00 33 C0 50 50 E8 2F D9 40 7C 9D 61 E9 04 DA 40 7C
接着在首句新建EIP,然后F9,又来到刚才的断点处.
再CTRL+G,来到00401000处,撤消刚才的代码,然后取消断点!
至此,双进程转单进程完毕.
方法二:
下断点:bp OpenMutexA,SHIFT+F9
7C80EA1B >8BFFmov edi,edi //断在这里
7C80EA1D55push ebp
7C80EA1E8BECmov ebp,esp
7C80EA2051push ecx
7C80EA2151push ecx
7C80EA22837D 10 00cmp dword ptr ss:,0
7C80EA2656push esi
7C80EA270F84 9F540300 je kernel32.7C843ECC
7C80EA2D64:A1 18000000mov eax,dword ptr fs:
7C80EA33FF75 10 push dword ptr ss:
接着ALT+F9返回
00517DDA85C0test eax,eax//返回到这
00517DDC74 04 je short Notepad.00517DE2 //这个跳修改成相反的.即jne
00517DDEC645 E7 00mov byte ptr ss:,0
00517DE20FB645 E7 movzx eax,byte ptr ss:
00517DE685C0test eax,eax
00517DE80F84 95010000 je Notepad.00517F83
00517DEE8B0D E4435500 mov ecx,dword ptr ds:
再次SHIFT+F9,断下后ALT+F9返回
005181D385C0test eax,eax//返回到这
005181D50F85 71020000 jnz Notepad.0051844C//这个跳修改成相反的.即jz
005181DB6A 01 push 1
005181DDFF15 88405500 call dword ptr ds:[<&KERNEL32.GetCurrent>; kernel32.GetCurrentThread
005181E350push eax
005181E4FF15 84405500 call dword ptr ds:[<&KERNEL32.SetThreadP>; kernel32.SetThreadPriority
005181EAC685 3FF9FFFF 0>mov byte ptr ss:,0
然后再一次SHIFT+F9,取消断点.
至此,同样,双进程转单进程完毕!
下面,接着来处理IAT,同样二种方法(其实和系列一的方法一样了)
方法一:
下断点he GetModuleHandleA+9,SHIFT+F9多次,观察队栈,适当时机返回。
0012943C/0012EB50
00129440|00DA5805返回到 00DA5805 来自 kernel32.GetModuleHandleA
00129444|00DD1BA8ASCII "kernel32.dll"
00129448|00DD2B30ASCII "VirtualAlloc"
0012943C/0012EB50
00129440|00DA5823返回到 00DA5823 来自 kernel32.GetModuleHandleA
00129444|00DD1BA8ASCII "kernel32.dll"
00129448|00DD2B24ASCII "VirtualFree"
00129188/00129440
0012918C|00D88064返回到 00D88064 来自 kernel32.GetModuleHandleA
00129190|00129308ASCII "kernel32.dll"
00129194|00000000
来到这里,就是返回时机了.
取消断点,ALT+F9,返回程序代码段,然后修改magic jump
00D880648B55 F4 mov edx,dword ptr ss: //返回到这里
00D880678B0D 84EFDD00 mov ecx,dword ptr ds:
00D8806D890491mov dword ptr ds:,eax
00D880708B55 F4 mov edx,dword ptr ss:
00D88073A1 84EFDD00 mov eax,dword ptr ds:
00D88078833C90 00 cmp dword ptr ds:,0
00D8807C75 5C jnz short 00D880DA
00D8807E8B4D F8 mov ecx,dword ptr ss:
00D880818B51 08 mov edx,dword ptr ds:
00D8808483E2 02 and edx,2
00D8808774 38 je short 00D880C1
00D88089B8 0F000000 mov eax,0F
00D8808EC1E0 02 shl eax,2
00D880918B0D 04CBDD00 mov ecx,dword ptr ds:; Notepad.00554370
00D880978B15 04CBDD00 mov edx,dword ptr ds:; Notepad.00554370
00D8809D8B35 04CBDD00 mov esi,dword ptr ds:; Notepad.00554370
00D880A38B5E 18 mov ebx,dword ptr ds:
00D880A6335A 10 xor ebx,dword ptr ds:
00D880A9331C01xor ebx,dword ptr ds:
00D880AC83E3 10 and ebx,10
00D880AFF7DBneg ebx
00D880B11BDBsbb ebx,ebx
00D880B3F7DBneg ebx
00D880B50FB6C3movzx eax,bl
00D880B885C0test eax,eax
00D880BA75 05 jnz short 00D880C1
00D880BC^ E9 1BFFFFFF jmp 00D87FDC
00D880C18D8D C8FEFFFF lea ecx,dword ptr ss:
00D880C751push ecx
00D880C8FF15 88F0DC00 call dword ptr ds: ; kernel32.LoadLibraryA
00D880CE8B55 F4 mov edx,dword ptr ss:
00D880D18B0D 84EFDD00 mov ecx,dword ptr ds:
00D880D7890491mov dword ptr ds:,eax
00D880DA8B55 F4 mov edx,dword ptr ss:
00D880DDA1 84EFDD00 mov eax,dword ptr ds:
00D880E2833C90 00 cmp dword ptr ds:,0
00D880E675 05 jnz short 00D880ED//NOP掉吧!
00D880E8^ E9 EFFEFFFF jmp 00D87FDC
00D880EDC785 BCFEFFFF 0>mov dword ptr ss:,0
00D880F7C785 C0FEFFFF 0>mov dword ptr ss:,0
00D881018B4D F8 mov ecx,dword ptr ss:
这样处理后,IAT也处理完毕了!
方法二:下断点:bp VirtualProtect,SHIFT+F9,观察队栈,找适当时机返回
返回的时机就是:当Size的值小于1000,且NewProtect为PAGE_READWRITE时
00129438 00DAACFD/CALL 到 VirtualProtect 来自 00DAACF7
0012943C 004C7034|Address = Notepad.004C7034
00129440 00000018|Size = 18 (24.)
00129444 00000004|NewProtect = PAGE_READWRITE
00129448 0012BFF0\pOldProtect = 0012BFF0
这就是返回时机了!
取消断点,ALT+F9返回
00DAACFD6A 14 push 14 //返回到这里
00DAACFFE8 72CF0000 call 00DB7C76
00DAAD0483C4 04 add esp,4
00DAAD078985 84ABFFFF mov dword ptr ss:,eax
00DAAD0D83BD 84ABFFFF 0>cmp dword ptr ss:,0
00DAAD1474 59 je short 00DAAD6F
00DAAD168B0D 4468DE00 mov ecx,dword ptr ds:
00DAAD1C898D 10AAFFFF mov dword ptr ss:,ecx
00DAAD228B95 74D8FFFF mov edx,dword ptr ss:
00DAAD280395 78D3FFFF add edx,dword ptr ss:
CTRL+F,搜索push 100(取消前面的整个段块)
00DAAF7068 00010000 push 100 //搜索到这里
00DAAF758D8D 40C1FFFF lea ecx,dword ptr ss:
00DAAF7B51push ecx
00DAAF7C8B95 40C2FFFF mov edx,dword ptr ss:
00DAAF828B02mov eax,dword ptr ds:
00DAAF8450push eax
00DAAF85E8 8677FBFF call 00D62710//跟随进去吧!
00DAAF8A83C4 0C add esp,0C
00DAAF8D8D8D 40C1FFFF lea ecx,dword ptr ss:
找最进的的CALL处,跟随进去,把段首修改成retn
00D6270CCCint3
00D6270DCCint3
00D6270ECCint3
00D6270FCCint3
00D6271055push ebp //跟随到这,修改成retn
00D627118BECmov ebp,esp
00D6271383EC 2C sub esp,2C
00D62716833D 00B6DD00 0>cmp dword ptr ds:,0
00D6271D75 59 jnz short 00D62778
00D6271FC745 EC 6D7B9F2>mov dword ptr ss:,2B9F7B6D
00D6272668 00010000 push 100
至此,IAT同样处理完毕!
然后就是寻找OEP了!
下断点:bp CreateThread
7C810637 >8BFFmov edi,edi//断在这
7C81063955push ebp
7C81063A8BECmov ebp,esp
7C81063CFF75 1C push dword ptr ss:
7C81063FFF75 18 push dword ptr ss:
7C810642FF75 14 push dword ptr ss:
7C810645FF75 10 push dword ptr ss:
7C810648FF75 0C push dword ptr ss:
7C81064BFF75 08 push dword ptr ss:
7C81064E6A FF push -1
7C810650E8 D7FDFFFF call kernel32.CreateRemoteThread
7C8106555Dpop ebp
取消断点,ALT+F9返回,接着就单步走吧
00DAF7828B45 08 mov eax,dword ptr ss: ; Notepad.0055AE68
00DAF7858338 01 cmp dword ptr ds:,1
00DAF78875 40 jnz short 00DAF7CA
00DAF78A8B0D 04CBDD00 mov ecx,dword ptr ds:; Notepad.00554370
00DAF7908B15 04CBDD00 mov edx,dword ptr ds:; Notepad.00554370
00DAF7968B41 14 mov eax,dword ptr ds:
00DAF7993342 10 xor eax,dword ptr ds:
00DAF79C8B0D 04CBDD00 mov ecx,dword ptr ds:; Notepad.00554370
00DAF7A23341 44 xor eax,dword ptr ds:
00DAF7A58945 DC mov dword ptr ss:,eax
00DAF7A88B55 08 mov edx,dword ptr ss:
00DAF7AB8B42 04 mov eax,dword ptr ds:
00DAF7AE50push eax
00DAF7AF8B4D 08 mov ecx,dword ptr ss:
00DAF7B28B51 08 mov edx,dword ptr ds:
00DAF7B552push edx
00DAF7B66A 00 push 0
00DAF7B88B45 08 mov eax,dword ptr ss:
00DAF7BB8B48 0C mov ecx,dword ptr ds:
00DAF7BE51push ecx
00DAF7BF8B55 F4 mov edx,dword ptr ss:
00DAF7C22B55 DC sub edx,dword ptr ss:
00DAF7C5FFD2call edx//来到这里,F7进去,就可以来到OEP了!
00DAF7C78945 FC mov dword ptr ss:,eax
00DAF7CA8B45 FC mov eax,dword ptr ss:
00DAF7CD5Epop esi
00DAF7CE8BE5mov esp,ebp
-----------------------------------------------------------------------------------------------------------
004A2ADCE8 B6A40000 call Notepad.004ACF97 //这里就是OEP了
004A2AE1^ E9 16FEFFFF jmp Notepad.004A28FC
004A2AE6CCint3
004A2AE7CCint3
004A2AE8CCint3
004A2AE9CCint3
004A2AEACCint3
004A2AEBCCint3
004A2AECCCint3
004A2AEDCCint3
004A2AEECCint3
004A2AEFCCint3
004A2AF08B4C24 04 mov ecx,dword ptr ss:
004A2AF4F7C1 03000000 test ecx,3
最后的任务就是dump,修复了.
记住,找到IAT后,把所有的无效的指针剪掉即可!
OK,脱壳成功!
have fun! 只能看看,脱不下,,
站位置 超人大牛又一个精华贴将要诞生了~ 感谢大作。。。学习。