• 标 题:用Armadillo标准加壳的程序的脱壳和引入表修复方案---OLLYDBG (8千字)
  • 作 者:jwh51 
  • 时 间:2003-06-14 11:55:55
  • 链 接:http://bbs.pediy.com

用过ARMADILLO的人都知道,用它加壳有两种方式,一是使用COPYMEMII,一是标准加壳.用COPYMEMII的一般可用DILLODUMP脱(当然也有时脱不了),而用标准加壳用DILLODUMP是脱不了的,这是DILLODUMP中的说明,我们来看看:
NOTE: This only really works on programs that are at least protected to some extent. 
For example, it will not work on "Standard Protection" aramadillo files, which isn't
a big deal, because for those you do not need to have any "advanced" tools to dump. I plan
on released a "lite" version to support those files soon..
本人E文很菜,只能了解大意,是说标准加壳的脱壳比较简单,不需用工具.但是对我等菜来说,还是要用工具的好,不过既然现在还没有,还是手脱吧.
脱壳目标:SoundEdit pro v1.30.634,5月29日更新.
下载:
http://www.rmbsoft.com/getit.asp?pid=6&server=http://www.winsoft98.com/programs/sep13.exe
加壳程序:Armadillo v3.00a
工具:OLLYDBG,LOADPE,importREC
SoundEdit是一个声音编辑软件(国外的),采用了ARMADILLO的KEY加密,启动要你输入KEY,否则要等N秒才能让你启动,还有30天试用期,所以,如果脱了壳,上述现象都将没有了.现在开始脱壳历程.!!
第一步,DUMP出程序:
用OLLYDBG载入程序.在调试选项中忽略所有异常,这样可以少按SHIFT+F9
BP VirtualProtect,F9运行,这时会有异常,用SHIFT+F9过程序会断下来,这时你不停按F9,一般在第5次会出现注册框,OK后再次中断,这时你要注意堆棧开始记下F9的次数了.我这第20下时在堆棧出现如下信息:
0012F214   7342F406  /CALL to VirtualProtect from MSVBVM60.7342F400
说明程序,已经运行了.(VB是先运行MSVBVM60.DLL的,在其中也用调用VirtualProtect,如果是DELPHI等程序,可一直F9到程序运行为止)
现在重新载入程序,到出现这个信息的前一次中断停下来,然后按几次CTRL+F9到程序中(也就是地址较低的地方,一般都是004*****,005*****,本程序在这:
004DA060    83C4 04         ADD     ESP, 4
004DA063    8945 FC         MOV     DWORD PTR SS:[EBP-4], EAX
004DA066    837D B8 00      CMP     DWORD PTR SS:[EBP-48], 0
004DA06A    74 0A           JE      SHORT SoundEdi.004DA076
004DA06C    8B45 B8         MOV     EAXDWORD PTR SS:[EBP-48]
004DA06F    50              PUSH    EAX
004DA070    FF15 E8615000   CALL    DWORD PTR DS:[<&USER32.DestroyWi>; USER32.DestroyWindow
004DA076    8B45 FC         MOV     EAXDWORD PTR SS:[EBP-4]
004DA079    8BE5            MOV     ESPEBP
004DA07B    5D              POP     EBP
004DA07C    C3              RETN
这时小心地用F8,因为有一堆的JMP,JNZ,JO等,不过也用不了多久的,大概20多次就可来到这:
004DB483    61              POPAD
004DB484    6A 00           PUSH    0
004DB486    E8 6E000000     CALL    SoundEdi.004DB4F9
004DB48B    83C4 04         ADD     ESP, 4
004DB48E    6A 00           PUSH    0
004DB490    E8 46830000     CALL    SoundEdi.004E37DB
004DB495    83C4 04         ADD     ESP, 4
004DB498    837D E4 01      CMP     DWORD PTR SS:[EBP-1C], 1
004DB49C    75 11           JNZ     SHORT SoundEdi.004DB4AF
004DB49E    68 E8965000     PUSH    SoundEdi.005096E8
004DB4A3    FF15 0C975000   CALL    DWORD PTR DS:[50970C]    ,这个CALL用F7跟进
004DB4A9    83C4 04         ADD     ESP, 4
004DB4AC    8945 E4         MOV     DWORD PTR SS:[EBP-1C], EAX
004DB4AF    68 0C9E4D00     PUSH    SoundEdi.004D9E0C
在4db4a3这个CALL用f7跟进,然后继续F8,几次后就来到这:
00D0B5E0   /75 29           JNZ     SHORT 00D0B60B
00D0B5E2   |E8 A05AFFFF     CALL    00D01087
00D0B5E7   |FF76 04         PUSH    DWORD PTR DS:[ESI+4]
00D0B5EA   |8BF8            MOV     EDIEAX
00D0B5EC   |A1 CCEED100     MOV     EAXDWORD PTR DS:[D1EECC]
00D0B5F1   |FF76 08         PUSH    DWORD PTR DS:[ESI+8]
00D0B5F4   |8B48 70         MOV     ECXDWORD PTR DS:[EAX+70]
00D0B5F7   |3348 50         XOR     ECXDWORD PTR DS:[EAX+50]
00D0B5FA   |6A 00           PUSH    0
00D0B5FC   |3348 34         XOR     ECXDWORD PTR DS:[EAX+34]
00D0B5FF   |03F9            ADD     EDIECX
00D0B601   |E8 815AFFFF     CALL    00D01087
00D0B606   |50              PUSH    EAX
00D0B607   |FFD7            CALL    EDI                               SoundEdi.004059B0
看到最后这个CALL EDI吗,004059B0就是程序的OEP了,我们F7跟进:
00405996  - FF25 3C114000   JMP     DWORD PTR DS:[40113C]
0040599C  - FF25 8C104000   JMP     DWORD PTR DS:[40108C]
004059A2  - FF25 B0104000   JMP     DWORD PTR DS:[4010B0]
004059A8  - FF25 E8114000   JMP     DWORD PTR DS:[4011E8]
004059AE    0000            ADD     BYTE PTR DS:[EAX], AL
004059B0    68 787D4000     PUSH    SoundEdi.00407D78     ,这是OEP了,
004059B5    E8 EEFFFFFF     CALL    SoundEdi.004059A8
呵,典型的VB代码.拿出LOADPE,快快DUMP吧.我们把DUMP的程序保存为DUMPED.EXE
第二步,引入表的修复
以前总以为它的修复很难,但实际上只要修改程序流程,完全可得到正确的引入表的.
1.可先用importREC试试,有一个指针无效,如果CUT程序退出时会出错,所以要修复它.通过它我们可看到iat的rva为1000,错误指针为1030,(如果很多指针无效,只要记住一个无效的RVA就可以了)
2.重新载入程序,BP VirtualProtect,断下后f9,注意堆棧的变化,当出现如下信息时要注意了:
0012DB28   00D0887E  /CALL to VirtualProtect from 00D08878
0012DB2C   00401000  |Address = SoundEdi.00401000
0012DB30   000CB000  |Size = CB000 (831488.)
0012DB34   00000004  |NewProtect = PAGE_READWRITE
0012DB38   0012F034  \pOldProtect = 0012F034
它将往401000也就是IAT所在的地方写入信息:这是再按一下F9,又停下来,D 401000,我们可看到,IAT所在的位置已经写入了东西,还不是dll的地址,还记得那个无效指针的地址吗:401030,我们清掉断点,然后在在内存定位到401030处,"右键-->breakpoint-->hardware on write-->dword",然后按F9运行,程序停了下来:
00D0942F    8B85 5CFBFFFF   MOV     EAXDWORD PTR SS:[EBP-4A4]
00D09435    8B8D 48F9FFFF   MOV     ECXDWORD PTR SS:[EBP-6B8]
00D0943B    8908            MOV     DWORD PTR DS:[EAX], ECX
00D0943D    8B85 5CFBFFFF   MOV     EAXDWORD PTR SS:[EBP-4A4]       停在这
00D09443    83C0 04         ADD     EAX, 4
00D09446    8985 5CFBFFFF   MOV     DWORD PTR SS:[EBP-4A4], EAX
00D0944C  ^ E9 78FEFFFF     JMP     00D092C9
看到上述二行:MOV ECX,DWORD PRT [EBP-6B8],我们再往上找几行可看到这个语句:
00D093E3    E8 F8C0FEFF     CALL    00CF54E0
00D093E8    8985 48F9FFFF   MOV     DWORD PTR SS:[EBP-6B8], EAX
00D093EE    83BD 48F9FFFF 0>CMP     DWORD PTR SS:[EBP-6B8], 0
00D093F5    75 38           JNZ     SHORT 00D0942F
在第二行也有个[EBP-6B8],注意前面这个CALL,我们去看一看
00CF54E0    55              PUSH    EBP
00CF54E1    8BEC            MOV     EBPESP
00CF54E3    53              PUSH    EBX
00CF54E4    56              PUSH    ESI
00CF54E5    57              PUSH    EDI
00CF54E6    33FF            XOR     EDIEDI
00CF54E8    33DB            XOR     EBXEBX
00CF54EA    66:F745 0E FFFF TEST    WORD PTR SS:[EBP+E], 0FFFF
00CF54F0    75 03           JNZ     SHORT 00CF54F5
00CF54F2    8B5D 0C         MOV     EBXDWORD PTR SS:[EBP+C]
00CF54F5    57              PUSH    EDI
00CF54F6    FF15 A430D100   CALL    DWORD PTR DS:[D130A4]             kernel32.GetModuleHandleA
00CF54FC    3945 08         CMP     DWORD PTR SS:[EBP+8], EAX
00CF54FF    75 07           JNZ     SHORT 00CF5508
00CF5501    BE C053D100     MOV     ESI, 0D153C0
00CF5506    EB 60           JMP     SHORT 00CF5568
00CF5508    393D 9859D100   CMP     DWORD PTR DS:[D15998], EDI
00CF550E    B9 9859D100     MOV     ECX, 0D15998
00CF5513    74 3C           JE      SHORT 00CF5551
00CF5515    8B35 B8B1D100   MOV     ESIDWORD PTR DS:[D1B1B8]
00CF551B    A1 CCEED100     MOV     EAXDWORD PTR DS:[D1EECC]
00CF5520    F641 08 01      TEST    BYTE PTR DS:[ECX+8], 1
00CF5524    74 0E           JE      SHORT 00CF5534
00CF5526    8B50 70         MOV     EDXDWORD PTR DS:[EAX+70]
00CF5529    3350 60         XOR     EDXDWORD PTR DS:[EAX+60]
00CF552C    3350 3C         XOR     EDXDWORD PTR DS:[EAX+3C]
00CF552F    F6C2 80         TEST    DL, 80
00CF5532    75 13           JNZ     SHORT 00CF5547
00CF5534    8B50 70         MOV     EDXDWORD PTR DS:[EAX+70]
00CF5537    3350 64         XOR     EDXDWORD PTR DS:[EAX+64]
00CF553A    3350 58         XOR     EDXDWORD PTR DS:[EAX+58]
00CF553D    3350 20         XOR     EDXDWORD PTR DS:[EAX+20]
00CF5540    3316            XOR     EDXDWORD PTR DS:[ESI]
00CF5542    3955 08         CMP     DWORD PTR SS:[EBP+8], EDX
00CF5545    74 1E           JE      SHORT 00CF5565
00CF5547    83C1 0C         ADD     ECX, 0C
00CF554A    83C6 04         ADD     ESI, 4
00CF554D    3939            CMP     DWORD PTR DS:[ECX], EDI
00CF554F  ^ 75 CF           JNZ     SHORT 00CF5520
00CF5551    FF75 0C         PUSH    DWORD PTR SS:[EBP+C]
这里面有几个跳转,其中最后一个CF554F是往上跳的.我们看一个就可发现:
00CF5513    74 3C           JE      SHORT 00CF5551,这个跳正好可跳出这个循环.只要改这个跳,就不会破坏引入表了.
再次重新载入,BP VirtualProtect,出现注册框后OK,程序再断下来,这时清除断点(包括硬件断点),CTRL+F9回程序领空,把CF5513的74 3c改成eb 3c,按F9运行,程序运行后打开importREC,选中程序,入口填入59b0,-->IAT自动搜索-->获得输入信息",如果还有无效的大可放心的cut,因为它们本来就不是有用指针了(也可能是importREC把IAT的大小判断错了),.然后修复脱壳后的文件.OK,大功告成.
测试了下脱壳后的程序,运行正常,那个烦人的注册框没有,时间限制也注册了,别说30天,就是30年都没问题.