【文章标题】: 说说处理加密IAT的一种常用方法
【文章作者】: wynney
【下载地址】: 打包下载
【作者声明】: 凑热闹~^_^
--------------------------------------------------------------------------------
【详细过程】

  零、前言 

  在论坛上看到很多朋友说一些教程看不懂,需要多讲一些原理,抽点空写了这篇文章,大侠飘过:)

  一、引述 
  
  在讲述这个方法之前,我们先看一个实例,壳子是CrypToCrackPeProtector 0.93的,最后一个区段名是.ccp3p。它加密
  的软件的输入表是加密了的,算是一个简单的加密壳了。
  
  忽略所有异常
  
  

引用:
  0046B000 >  5B              pop     ebx                              ; EP
  0046B001    81E3 00FFFFFF   and     ebx, FFFFFF00
  0046B007    66:813B 4D5A    cmp     word ptr [ebx], 5A4D
  0046B00C    75 33           jnz     short 0046B041
  0046B00E    8BF3            mov     esi, ebx
  
??
  
引用:
  00400000   00001000   CrypToCr              PE header     Imag   R         RWE
  00401000   0004A000   CrypToCr   .text      code          Imag   R         RWE
  0044B000   0000C000   CrypToCr   .rdata                   Imag   R         RWE
  00457000   00009000   CrypToCr   .data      data          Imag   R         RWE
  00460000   00003000   CrypToCr   .idata                   Imag   R         RWE
  00463000   00008000   CrypToCr   .rsrc      resources     Imag   R         RWE
  0046B000   00002000   CrypToCr   .ccp3p     SFX,imports   Imag   R         RW
  
??
  我们先在.rsrc区段F2,F9,再在.text段F2,F9,就到OEP了
  
  
引用:
  004271B0    55              push    ebp                        ; OEP
  004271B1    8BEC            mov     ebp, esp
  004271B3    6A FF           push    -1
  004271B5    68 600E4500     push    00450E60
  004271BA    68 C8924200     push    004292C8
  004271BF    64:A1 00000000  mov     eax, dword ptr fs:[0]
  004271C5    50              push    eax
  004271C6    64:8925 0000000>mov     dword ptr fs:[0], esp
  004271CD    83C4 A8         add     esp, -58
  004271D0    53              push    ebx
  004271D1    56              push    esi
  004271D2    57              push    edi
  004271D3    8965 E8         mov     dword ptr [ebp-18], esp
  004271D6    FF15 DC0A4600   call    dword ptr [460ADC]         ; 应该是GetVersion,其他的IAT也都加密了
  
??
  我们需要找到,IAT加密的地方
  
  重新加载目标程序,命令行DD 460ADC,下内存访问断点,F9几次
  
  
引用:
  0046B338    893C8A          mov     dword ptr [edx+ecx*4], edi     ;  中断在这,看寄存器
  0046B33B    807F 05 55      cmp     byte ptr [edi+5], 55
  0046B33F    73 0C           jnb     short 0046B34D
  0046B341    2B47 01         sub     eax, dword ptr [edi+1]
  
??
  
引用:
  EAX 7C8114AB kernel32.GetVersion
  ECX 0000005A
  EDX 00460974 CrypToCr.00460974
  EBX 00400000 CrypToCr.00400000
  ESP 0013FFB4
  EBP 7C800000 kernel32.7C800000
  ESI 00460014 CrypToCr.00460014
  EDI 0046B823 CrypToCr.0046B823
  EIP 0046B338 CrypToCr.0046B338
  
??
  可以看到eax里才是真正的IAT了,把edi改成eax,然后到00401000段下断,F9,到达OEP
  IAT全部都恢复了:)
  
  
  
引用:
  /*
  Script written by wynney
  
  Date:   2007-04-13
  Script:CrypToCrackPeProtector Fixer
  Environment : OllyDbg 1.1, ODBGScript 1.52,Winxp Sp2
  Debugging options: Tick all items in OllyDbg's Debugging Options-Exceptions
  
  Thanks :
           kanxue     - author of HideOD       
           hnhuqiong  - author of ODbgScript 1.52
  */
  var OEP
  var temp
  var IAT
  
  Start:
                find eip,#2D000000805055FF5424??5A595B8B7C2404#
                cmp $RESULT,0
                je Error
                mov temp,$RESULT
                mov IAT,temp
                mov OEP,temp
                sub OEP,25
                add IAT,12
                bp IAT
                esto
                bc IAT
                repl eip,#893C8A#,#89048A#,3
                bp OEP
                esto
                bc OEP
                sti
  
  Done:
                dpe "\\UnPacked.exe", eip
                cmt eip,"OEP"
                ret
              
  Error:
                msg "错误"
                ret
  

  
   二、PELock 1.0x 
  
  前面看了之后,大家应该明白点了,这是最基本的IAT加密法子,从中我们也可以看到最基本的IAT处理法子
  但是,有很多壳有壳校验或内存校验,例如:PELock

  
  我们用上面的方法,再入PELock.exe程序,F9,Alt+E,双击目标程序所在行,Ctrl+B:FF 25
  
  
引用:
  0098089F  - FF25 E4314000   jmp     dword ptr [4031E4]
  009808A5  - E9 B014A8FF     jmp     Dll_Load.00401D5A
  009808AA    B0 FF           mov     al, 0FF
  009808AC    15 C4314000     adc     eax, 4031C4
  009808B1  - E9 F214A8FF     jmp     Dll_Load.00401DA8
  009808B6    F2:             prefix repne:
  009808B7    FF15 C0314000   call    dword ptr [4031C0]
  
??
  重新加载目标程序,DD 4031E4,下内存访问断点,几次F9
  
  
引用:
  00034661    8919            mov     dword ptr [ecx], ebx             ; 中断在这,看寄存器
  00034663    EB 03           jmp     short 00034668
  00034665    92              xchg    eax, edx
  00034666    E1 7C           loopde  short 000346E4
  
??
  
引用:
  EAX 77BF27FA msvcrt.__CxxFrameHandler
  ECX 004031E4 ASCII """:"
  EDX 77BE0000 msvcrt.77BE0000
  EBX 003B0325
  ESP 0013FFAC
  EBP 0003062D
  ESI 003A0426
  EDI 003A038F ASCII "MSVCRT.dll"
  EIP 00034661
  
??
  eax里才是真正的IAT,ebx里是壳的地址。
  那么我们把ebx改成eax,F9运行看看,出现错误:(
  那么我们再来看一次,看看是那里出错,改了ebx之后,一路F8,F7交替走
  
  
引用:
  00034351    2B848D 143B0000 sub     eax, dword ptr [ebp+ecx*4+3B14]   ; 到这就走不下去了
  00034358    D3C0            rol     eax, cl
  0003435A    49              dec     ecx
  
??
  看来00034351处就是CrC校验的地方了
  我们解决他的法子有2个,这里说个简单的法子吧
  
  同时对00034661和00034351下内存断点,运行到00034661后把eax改成ebx,F9运行到00034351马上又把ebx改成eax,
  如此往替,所有的IAT就都修复完了,这个操作如果手动的确是麻烦,呵呵,用脚本吧?
  
  
  
引用:
  Compar:
  cmp  eip,IATAddr         //处理输入表的位置
  je FixIAT
  cmp  eip,CrCAddr        //CRC的位置
  jne GotoOEP
  esto
  jmp Compar
  
  FixIAT:
  ASM IATAddr,"mov [ecx],eax" 
  sti
  ASM IATAddr,"mov [ecx],ebx" 
  esto
  jmp Compar
  

  
   三、ASProtect 1.31 
  
    说下两个分支的处理

    
引用:
    00D1574B    8B5424 0C       mov     edx, dword ptr [esp+C]           ; 找到这里
    00D1574F    8902            mov     dword ptr [edx], eax             ; ①ebp里是IAT,把eax改成ebp
    00D15751    8B4424 0C       mov     eax, dword ptr [esp+C]
    00D15755    8906            mov     dword ptr [esi], eax
    00D15757    0FB74424 04     movzx   eax, word ptr [esp+4]
    00D1575C    0143 08         add     dword ptr [ebx+8], eax
    
????
    
    
引用:
    00D15672    8B5424 0C       mov     edx, dword ptr [esp+C]           
    00D15676    8902            mov     dword ptr [edx], eax             ; ②ebp里是IAT,把eax改成ebp
    00D15678    8D4C24 0C       lea     ecx, dword ptr [esp+C]
    00D1567C    8A5424 07       mov     dl, byte ptr [esp+7]
    00D15680    8BC3            mov     eax, ebx
    00D15682    E8 F9F7FFFF     call    00D14E80                         ; ③加密Call,nop掉
    00D15687    8BC6            mov     eax, esi
    00D15689    83E8 02         sub     eax, 2
    00D1568C    66:8338 00      cmp     word ptr [eax], 0
    00D15690    75 10           jnz     short 00D156A2                   ; ④改jmp
    
??
  IAT处理完毕,撤消修改,以免后面出现内存保护错误
  
   四、ASProtect 2.0 Alpha 
  
   两个分支的处理

   
引用:
    00A8CEAD    8B5424 0C       mov     edx, dword ptr [esp+C]   
    00A8CEB1    8902            mov     dword ptr [edx], eax      ; ①ebp里才是IAT,把eax改成ebp
    00A8CEB3    8B4424 0C       mov     eax, dword ptr [esp+C]
    00A8CEB7    8906            mov     dword ptr [esi], eax
    00A8CEB9    0FB74424 04     movzx   eax, word ptr [esp+4]
    00A8CEBE    0143 08         add     dword ptr [ebx+8], eax
    
????
    
    
引用:
    00A83780    53              push    ebx                       ; ②找到这,Patch这里
    00A83781    8BD8            mov     ebx, eax
    00A83783    8BC3            mov     eax, ebx
    00A83785    E8 56FFFFFF     call    00A836E0
    00A8378A    C603 E8         mov     byte ptr [ebx], 0E8       ; 这里是IAT加密,给改成EB了
    00A8378D    43              inc     ebx
    00A8378E    8903            mov     dword ptr [ebx], eax
    00A83790    5B              pop     ebx
    00A83791    C3              retn 3
    
????
    自己Patch代码
  
    
引用:
    00A83780    66:C700 FF15    mov     word ptr [eax], 15FF      ; Call类型的,如果是jmp类型的把15FF改成25FF
    00A83785    83C0 02         add     eax, 2
    00A83788    8910            mov     dword ptr [eax], edx
    00A8378A    892A            mov     dword ptr [edx], ebp      ; ebp是正确的IAT
    00A8378C    90              nop
    00A8378D    90              nop
    00A8378E    90              nop
    00A8378F    90              nop
    00A83790    90              nop
    00A83791    C3              retn
    
??
  IAT处理完毕,最好是撤消修改,以免后面出现内存保护错误

   五、MoleBox 
  
  上面我们说的都是比较明显的加密IAT,现在来看个不明显的
  
  MoleBox这个就不用多说了,很容易到达OEP,我们看看IAT表,部分IAT是加密的
  
  
引用:
  00406DF8  - FF25 04756300   jmp     dword ptr [637504]               ; flashfxp.0073BED3
  00406DFE    8BC0            mov     eax, eax
  00406E00  - FF25 00756300   jmp     dword ptr [637500]               ; flashfxp.0073BE34
  00406E06    8BC0            mov     eax, eax
  00406E08  - FF25 FC746300   jmp     dword ptr [6374FC]               ; flashfxp.0073BFCE
  
??
  重新加载程序,DD 637504,下内存访问断点,几次F9
  
  
引用:
  00715B6F    FF96 20CB3200   call    dword ptr [esi+32CB20]           ; 从这里出来的
  00715B75    09C0            or      eax, eax
  00715B77    74 07           je      short 00715B80
  00715B79    8903            mov     dword ptr [ebx], eax             ; 到达这里,注意eax
  00715B7B    83C3 04         add     ebx, 4
  00715B7E  ^ EB E1           jmp     short 00715B61
  
??
  
引用:
  EAX 0073BED3 flashfxp.0073BED3     ;填充无效指针
  ECX 0013FFE0
  EDX 00CA09D8
  EBX 00637504 flashfxp.00637504
  ESP 0013FFA4
  EBP 7C800000 kernel32.7C800000
  ESI 00401000 flashfxp.00401000
  EDI 007128E0 flashfxp.007128E0
  
??
  he 00715B6F
  
  重载,F9,中断下来后F7,跟踪发现
  
  
引用:
  0073C4E9    FF75 E4         push    dword ptr [ebp-1C]               ; [ebp-1C]里才是真正的IAT
  0073C4EC    8B0D 34707400   mov     ecx, dword ptr [747034]
  0073C4F2    E8 3E070000     call    0073CC35                         ; 加密Call
  0073C4F7    8945 E0         mov     dword ptr [ebp-20], eax          ; call会产生一个值给eax,0或1
  0073C4FA    837D E0 00      cmp     dword ptr [ebp-20], 0            ; eax再给[ebp-20],再比较
  0073C4FE    74 08           je      short 0073C508                   ; 为0则不加密,为1则加密,Magic Jump,改jmp
  0073C500    8B45 E0         mov     eax, dword ptr [ebp-20]          ; 加密则把值传回eax
  0073C503    8B00            mov     eax, dword ptr [eax]             ; [eax]里就是无效指针,传给eax
  0073C505    8945 E4         mov     dword ptr [ebp-1C], eax          ; 无效指针再传给[ebp-1C]
  0073C508    834D FC FF      or      dword ptr [ebp-4], FFFFFFFF
  0073C50C    E8 02000000     call    0073C513
  0073C511    EB 1C           jmp     short 0073C52F
  0073C513    A1 34707400     mov     eax, dword ptr [747034]
  0073C518    8945 D4         mov     dword ptr [ebp-2C], eax
  0073C51B    837D D4 00      cmp     dword ptr [ebp-2C], 0
  0073C51F    74 0D           je      short 0073C52E
  0073C521    8B45 D4         mov     eax, dword ptr [ebp-2C]
  0073C524    83C0 10         add     eax, 10
  0073C527    50              push    eax
  0073C528    FF15 18F07300   call    dword ptr [<&KERNEL32.LeaveCriti>; ntdll.RtlLeaveCriticalSection
  0073C52E    C3              retn
  0073C52F    8B45 E4         mov     eax, dword ptr [ebp-1C]          ; IAT或无效指针再传给eax
  0073C532    8B4D F0         mov     ecx, dword ptr [ebp-10]
  0073C535    64:890D 0000000>mov     dword ptr fs:[0], ecx
  0073C53C    5F              pop     edi
  0073C53D    5E              pop     esi
  0073C53E    5B              pop     ebx
  0073C53F    C9              leave
  0073C540    C2 0800         retn    8                                ; 返回后把eax的值传给IAT表地址
  
??
  我们把Magic Jump改成jmp之后IAT不再加密:)
  这里需要说明的是,这个法子跟我原先的文章里的法子是不一样的,但是可以达到相同的效果
  
  于是,我们可以写个脚本
  
  
  
引用:
  /*
  Script written by wynney
  
  Date:   2007-04-13
  Script:MoleBox
  Environment : OllyDbg 1.1, ODBGScript 1.52,Winxp Sp2
  Debugging options: Tick all items in OllyDbg's Debugging Options-Exceptions
  
  Thanks :
           kanxue     - author of HideOD       
           hnhuqiong  - author of ODbgScript 1.52
  */
  #log
  var temp
  
  log eip
  STI
  STO
  mov temp,esp
  bphws temp,"r"                //esp定律,用来找OEP
  esto
  bphwcall
  find eip,#8945??837D??0074088B45??8B008945??834D??FF#
  cmp $RESULT,0
  je err
  mov temp,$RESULT
  repl temp,#8945??837D??0074088B45??8B008945??834D??FF#,#8945??837D??00EB088B45??8B008945??834D??FF#,21
  sti
  sti
  mov temp,eax
  bp temp
  esto
  bc temp
  sti
  mov temp,esp
  bphws temp,"r" 
  esto
  bphwcall
  mov temp,eip
  add temp,0D
  bp temp
  esto
  bc temp
  sti
  dpe "\\UnPacked.exe", eip
  cmt eip, "This is the OEP!  Found By: wynney "  
  ret
  
  err:
  msg "error"
  ret 
  

  
--------------------------------------------------------------------------------
【经验总结】
  1、若有的壳有内存访问断点校验,可以换用内存写入断点,或者是硬件访问/写入断点
  2、如果不是很明显的寄存器填充,那么一般IAT加密就在附近,多跟踪下:)
  3、很多时候,并不是单纯的修改可以解决的,需要自己Patch代码,多了解下汇编吧,这个是别人教不会的
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年04月14日 wynney