【目标软件】 Processguard
【下载地址】 http://www.diamondcs.com.au/processguard/pgsetup_3300b4.exe
【脱壳工具】 OllyIce及相关工具
【作者声明】 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【调试过程】
   现在好多软件作者为了防止被脱壳,而设置了各式各样的自校验,有明有暗,有强有弱。最近刚搞定了一个小软件,感觉难度中等,把调试过程写出来,与大家分享,高手略过.
一、脱壳:
   未知壳,不过用Esp定律可轻松脱掉。OD载入后这样的:

代码:
004DC027 >  60              PUSHAD 004DC028    EB 0A           JMP SHORT 004DC034 004DC02A    44              INC ESP 004DC02B    6961 6D 6F6E644>IMUL ESP,[ECX+6D],43646E6F 004DC032    53              PUSH EBX 004DC033    00EB            ADD BL,CH 004DC035    02EB            ADD CH,BL 004DC037    05 E8F9FFFF     ADD EAX,-618 004DC03C    FF58 2D         CALL FAR FWORD PTR [EAX+2D]              ; 远调用


  注意忽略所有异常,F7走一步,下断hr ESP,F9运行后到达这里:

代码:
004DC14C    50              PUSH EAX 004DC14D    B8 DE690100     MOV EAX,169DE 004DC152    35 28314000     XOR EAX,403128 004DC157    8BD8            MOV EBX,EAX 004DC159    58              POP EAX 004DC15A    FFE3            JMP EBX       //这里F7进去,到达这里 004158F6    B8 C4B64D00     MOV EAX,004DB6C4   004158FB    50              PUSH EAX 004158FC    64:FF35 0000000>PUSH DWORD PTR FS:[0] 00415903    64:8925 0000000>MOV FS:[0],ESP


  去除ESP硬件断点,再F4一下,到达OEP

代码:
004158F6    55              PUSH EBP 004158F7    8BEC            MOV EBP,ESP 004158F9    6A FF           PUSH -1 004158FB    68 30744100     PUSH 00417430 00415900    68 805A4100     PUSH 00415A80                            ; JMP 到 msvcrt._except_handler3 00415905    64:A1 00000000  MOV EAX,FS:[0] 0041590B    50              PUSH EAX 0041590C    64:8925 0000000>MOV FS:[0],ESP 00415913    83EC 68         SUB ESP,68 00415916    53              PUSH EBX 00415917    56              PUSH ESI 00415918    57              PUSH EDI



  现在DUMP下来吧,用IM自动搜索一下IAT,找到了,可是里面有一个无效函数指针。

代码:
00417118  7C82DE40  kernel32.lstrlenW 0041711C  7C82F2FB  kernel32.GetLocalTime 00417120  00380425                  //这个是什么呢? 00417124  7C82C1BA  kernel32.CloseHandle 00417128  7C82C0C0  kernel32.GetDriveTypeW 0041712C  7C8024A8  kernel32.Sleep  



好,我们来跟踪一下它,在00417120 处下个内存访问断点,F9运行一下,断在这里:

代码:
00412A7D    A1 20714100     MOV EAX,[417120]            //进EAX 00412A82    A3 3C574200     MOV [42573C],EAX            //写入 [42573C]  00412A87    A1 70714100     MOV EAX,[417170] 00412A8C    68 D0824100     PUSH 004182D0                            ; UNICODE "Initializing ProcessGuard"



继续跟踪,在42573C处下内存访问断点,断在这里:

代码:
00412AFC    8135 3C574200 2>XOR DWORD PTR [42573C],894ADF25 00412B06    68 705D4200     PUSH 00425D70 00412B0B    68 7C814100     PUSH 0041817C                            ; UNICODE "Reboots" 00412B10    BE 48014200     MOV ESI,00420148                         ; UNICODE "SOFTWARE\Diamond Computer Systems\ProcessGuard v3.0" 不管它继续F9,过几次XOR以后到达这里: 00412DFD    FF15 3C574200   CALL [42573C]                 //开始调用地址了 00412E03    3BC3            CMP EAX,EBX 00412E05    74 59           JE SHORT 00412E60 00412E07    FFD0            CALL EAX



这时注意一下堆栈和寄存器,情况是这样的:

代码:
堆栈: 0012F010   7C800000  kernel32.7C800000 0012F014   0012FF10  ASCII "IsDebuggerPresent" 0012F018   00000000 0012F01C   001420D1 寄存器: EAX 0012FF10 ASCII "IsDebuggerPresent" ECX 0014D6D8 EDX 7C9B9D60 ntdll.7C9B9D60 EBX 00000000 ESP 0012F010 EBP 0012FF24 ESI 00000000 EDI 0012FF22 EIP 00412DFD procguar.00412DFD


下面我们F8一次,执行完这个函数,看看堆栈和寄存器的变化:

代码:
堆栈: 0012F018   00000000 0012F01C   001420D1 0012F020   00000000 寄存器: EAX 7C824860 kernel32.IsDebuggerPresent ECX 000008E4 EDX 00000001 EBX 00000000 ESP 0012F018 EBP 0012FF24 ESI 00000000 EDI 0012FF22 EIP 00412E03 procguar.00412E03


看到了吗?EAX值是什么?猜到了这个函数是什么了吧,对,GetProcAddress嘛,好像很多壳都是偷个这函数的。
好了,修正这个函数指针,脱壳完成。

二、修正自校验
运行软件后,还是有点问题,一点允许保护就异常退出,看来还有暗桩。弄了几次都不成功,后来想到是不是刚才修正的函数的问题,于是在401720处再次下内存访问断点,断在了这里:

代码:
00409CD5   .  8B35 20714100 MOV ESI,[<&kernel32.GetProcAddress>]     ;  kernel32.GetProcAddress 00409CDB   .  8D45 DC       LEA EAX,[EBP-24] 00409CDE   .  50            PUSH EAX                                 ; /ProcNameOrOrdinal 00409CDF   .  FF35 58574200 PUSH DWORD PTR [425758]                  ; |hModule = 7C800000 (kernel32) 00409CE5   .  C645 E6 57    MOV BYTE PTR [EBP-1A],57                 ; | 00409CE9   .  C645 E1 65    MOV BYTE PTR [EBP-1F],65                 ; | 00409CED   .  C645 DD 72    MOV BYTE PTR [EBP-23],72                 ; | 00409CF1   .  C645 DF 61    MOV BYTE PTR [EBP-21],61                 ; | 00409CF5   .  C645 E3 69    MOV BYTE PTR [EBP-1D],69                 ; | 00409CF9   .  C645 E4 6C    MOV BYTE PTR [EBP-1C],6C                 ; | 00409CFD   .  C645 DE 65    MOV BYTE PTR [EBP-22],65                 ; | 00409D01   .  C645 DC 43    MOV BYTE PTR [EBP-24],43                 ; | 00409D05   .  C645 E5 65    MOV BYTE PTR [EBP-1B],65                 ; | 00409D09   .  885D E7       MOV [EBP-19],BL                          ; | 00409D0C   .  C645 E0 74    MOV BYTE PTR [EBP-20],74                 ; | 00409D10   .  C645 E2 46    MOV BYTE PTR [EBP-1E],46                 ; | 00409D14   .  FFD6          CALL ESI             //这里是CreateFileW   00409D16   .  8945 1C       MOV [EBP+1C],EAX 00409D19   .  8D45 CC       LEA EAX,[EBP-34] 00409D1C   .  50            PUSH EAX                                 ; /ProcNameOrOrdinal 00409D1D   .  FF35 58574200 PUSH DWORD PTR [425758]                  ; |hModule = 7C800000 (kernel32) 00409D23   .  C645 D0 46    MOV BYTE PTR [EBP-30],46                 ; | 00409D27   .  C645 CE 61    MOV BYTE PTR [EBP-32],61                 ; | 00409D2B   .  C645 D1 69    MOV BYTE PTR [EBP-2F],69                 ; | 00409D2F   .  C645 CD 65    MOV BYTE PTR [EBP-33],65                 ; | 00409D33   .  C645 D2 6C    MOV BYTE PTR [EBP-2E],6C                 ; | 00409D37   .  C645 CC 52    MOV BYTE PTR [EBP-34],52                 ; | 00409D3B   .  C645 D3 65    MOV BYTE PTR [EBP-2D],65                 ; | 00409D3F   .  C645 CF 64    MOV BYTE PTR [EBP-31],64                 ; | 00409D43   .  885D D4       MOV [EBP-2C],BL                          ; | 00409D46   .  FFD6          CALL ESI        //这里是:ReadFile  00409D48   .  8945 C8       MOV [EBP-38],EAX 00409D4B   .  8D45 F0       LEA EAX,[EBP-10] 00409D4E   .  50            PUSH EAX                                 ; /ProcNameOrOrdinal 00409D4F   .  FF35 58574200 PUSH DWORD PTR [425758]                  ; |hModule = 7C800000 (kernel32) 00409D55   .  C645 F8 69    MOV BYTE PTR [EBP-8],69                  ; | 00409D59   .  C645 F0 47    MOV BYTE PTR [EBP-10],47                 ; | 00409D5D   .  C645 FA 65    MOV BYTE PTR [EBP-6],65                  ; | 00409D61   .  C645 F2 74    MOV BYTE PTR [EBP-E],74                  ; | 00409D65   .  C645 F1 65    MOV BYTE PTR [EBP-F],65                  ; | 00409D69   .  C645 F9 7A    MOV BYTE PTR [EBP-7],7A                  ; | 00409D6D   .  885D FB       MOV [EBP-5],BL                           ; | 00409D70   .  C645 F3 46    MOV BYTE PTR [EBP-D],46                  ; | 00409D74   .  C645 F6 65    MOV BYTE PTR [EBP-A],65                  ; | 00409D78   .  C645 F5 6C    MOV BYTE PTR [EBP-B],6C                  ; | 00409D7C   .  C645 F7 53    MOV BYTE PTR [EBP-9],53                  ; | 00409D80   .  C645 F4 69    MOV BYTE PTR [EBP-C],69                  ; | 00409D84   .  FFD6          CALL ESI         //这里是:GetFileSize                   00409D86   .  8945 0C       MOV [EBP+C],EAX 00409D89   .  8D45 A4       LEA EAX,[EBP-5C] 00409D8C   .  50            PUSH EAX                                 ; /ProcNameOrOrdinal 00409D8D   .  FF35 58574200 PUSH DWORD PTR [425758]                  ; |hModule = 7C800000 (kernel32) 00409D93   .  C645 B5 57    MOV BYTE PTR [EBP-4B],57                 ; | 00409D97   .  C645 AE 69    MOV BYTE PTR [EBP-52],69                 ; | 00409D9B   .  C645 AC 65    MOV BYTE PTR [EBP-54],65                 ; | 00409D9F   .  C645 B1 4E    MOV BYTE PTR [EBP-4F],4E                 ; | 00409DA3   .  C645 A7 4D    MOV BYTE PTR [EBP-59],4D                 ; | 00409DA7   .  C645 A6 74    MOV BYTE PTR [EBP-5A],74                 ; | 00409DAB   .  C645 AA 75    MOV BYTE PTR [EBP-56],75                 ; | 00409DAF   .  C645 A8 6F    MOV BYTE PTR [EBP-58],6F                 ; | 00409DB3   .  885D B6       MOV [EBP-4A],BL                          ; | 00409DB6   .  C645 A5 65    MOV BYTE PTR [EBP-5B],65                 ; | 00409DBA   .  C645 A4 47    MOV BYTE PTR [EBP-5C],47                 ; | 00409DBE   .  C645 AF 6C    MOV BYTE PTR [EBP-51],6C                 ; | 00409DC2   .  C645 B4 65    MOV BYTE PTR [EBP-4C],65                 ; | 00409DC6   .  C645 AB 6C    MOV BYTE PTR [EBP-55],6C                 ; | 00409DCA   .  C645 A9 64    MOV BYTE PTR [EBP-57],64                 ; | 00409DCE   .  C645 AD 46    MOV BYTE PTR [EBP-53],46                 ; | 00409DD2   .  C645 B3 6D    MOV BYTE PTR [EBP-4D],6D                 ; | 00409DD6   .  C645 B2 61    MOV BYTE PTR [EBP-4E],61                 ; | 00409DDA   .  C645 B0 65    MOV BYTE PTR [EBP-50],65                 ; | 00409DDE   .  FFD6          CALL ESI   //这里是:GetModuleFileNameW 00409DE0   .  395D 1C       CMP [EBP+1C],EBX         00409DE3   .  8BD0          MOV EDX,EAX 00409DE5   .  0F84 AD000000 JE 00409E98 00409DEB   .  395D C8       CMP [EBP-38],EBX 00409DEE   .  0F84 A4000000 JE 00409E98 00409DF4   .  395D 0C       CMP [EBP+C],EBX 00409DF7   .  0F84 9B000000 JE 00409E98 00409DFD   .  3BD3          CMP EDX,EBX 00409DFF   .  0F84 93000000 JE 00409E98              //上面4个是检验是否正确的得到了4个函数的地址 00409E05   .  33C0          XOR EAX,EAX 00409E07   .  66:899D 7CFDF>MOV [EBP-284],BX 00409E0E   .  B9 81000000   MOV ECX,81 00409E13   .  8DBD 7EFDFFFF LEA EDI,[EBP-282] 00409E19   .  F3:AB         REP STOS DWORD PTR ES:[EDI] 00409E1B   .  66:AB         STOS WORD PTR ES:[EDI] 00409E1D   .  68 04010000   PUSH 104 00409E22   .  8D85 7CFDFFFF LEA EAX,[EBP-284] 00409E28   .  50            PUSH EAX 00409E29   .  53            PUSH EBX 00409E2A   .  FFD2          CALL EDX    //CALL GetModuleFileNameW 00409E2C   .  53            PUSH EBX 00409E2D   .  53            PUSH EBX 00409E2E   .  6A 03         PUSH 3 00409E30   .  53            PUSH EBX 00409E31   .  6A 01         PUSH 1 00409E33   .  68 00000080   PUSH 80000000 00409E38   .  8D85 7CFDFFFF LEA EAX,[EBP-284] 00409E3E   .  50            PUSH EAX 00409E3F   .  FF55 1C       CALL [EBP+1C]    //CALL CreateFileW 00409E42   .  3BC3          CMP EAX,EBX 00409E44   .  8945 C4       MOV [EBP-3C],EAX 00409E47   .  74 4F         JE SHORT 00409E98 00409E49   .  83F8 FF       CMP EAX,-1 00409E4C   .  74 4A         JE SHORT 00409E98 00409E4E   .  53            PUSH EBX 00409E4F   .  50            PUSH EAX 00409E50   .  FF55 0C       CALL [EBP+C]     //CALL GetFileSize 00409E53   .  8BF0          MOV ESI,EAX 00409E55   .  56            PUSH ESI 00409E56   .  E8 4BBA0000   CALL <JMP.&msvcrt.??2@YAPAXI@Z> 00409E5B   .  8BF8          MOV EDI,EAX 00409E5D   .  3BFB          CMP EDI,EBX 00409E5F   .  59            POP ECX 00409E60   .  74 36         JE SHORT 00409E98 00409E62   .  53            PUSH EBX 00409E63   .  8D45 1C       LEA EAX,[EBP+1C] 00409E66   .  50            PUSH EAX 00409E67   .  56            PUSH ESI 00409E68   .  57            PUSH EDI 00409E69   .  FF75 C4       PUSH DWORD PTR [EBP-3C] 00409E6C   .  FF55 C8       CALL [EBP-38]              //CALL  ReadFile    00409E6F   .  FF75 C4       PUSH DWORD PTR [EBP-3C]                  ; /hObject 00409E72   .  FF15 24714100 CALL [<&kernel32.CloseHandle>]           ; \CloseHandle 00409E78   .  8D46 FC       LEA EAX,[ESI-4] 00409E7B   .  57            PUSH EDI 00409E7C   .  E8 E79B0000   CALL 00413A68             //这里是进行计算 00409E81   .  3B4437 FC     CMP EAX,[EDI+ESI-4]       //比较结果  00409E85   .  59            POP ECX 00409E86   .  8945 1C       MOV [EBP+1C],EAX 00409E89      74 06         JE SHORT 00409E91          //不跳就OVER了 00409E8B   .  61            POPAD 00409E8C   .  E9 230B0000   JMP 0040A9B4 00409E91   >  57            PUSH EDI





如果有兴趣可以跟进去计算一下,我是直接将409E89 处JE改为JMP了,结果正常运行了。程序还有一处自校验,跟这里差不多,不啰嗦了。
三、破解:
不多说了,很简单的。感觉写脱文比脱壳还费劲,写得不好,将就着看吧。