【调试 DLL】TestDLL.DLL
【调试环境】WinXP、Ollydbg1.10、LordPE、DLL_Loader、ImportRect1.6
【参考文章】fly的:用Ollydbg手脱ASProtect V1.23RC4加壳的DLL
【学习目的】初次练习使用Ollydbg

一、找OEP
  (1)
    用OllyDbg加载 TestDLL.DLL
    F9运行,按Shift-F9跳过异常18次后来到:(下面代码是 ASProtect 1.2 经典特征)

    007DFC2A   3100           XOR DWORD PTR DS:[EAX],EAX
    007DFC2C   64:8F05 000000>POP DWORD PTR FS:[0]
    007DFC33   58             POP EAX
    007DFC34   833D 34397E00 >CMP DWORD PTR DS:[7E3934],0
    007DFC3B   74 14          JE SHORT 007DFC51
    007DFC3D   6A 0C          PUSH 0C
    007DFC3F   B9 34397E00    MOV ECX,7E3934
    007DFC44   8D45 F8        LEA EAX,DWORD PTR SS:[EBP-8]
    007DFC47   BA 04000000    MOV EDX,4
    007DFC4C   E8 4BC7FFFF    CALL 007DC39C
    007DFC51   FF75 FC        PUSH DWORD PTR SS:[EBP-4]
    007DFC54   FF75 F8        PUSH DWORD PTR SS:[EBP-8]
    007DFC57   8B45 F4        MOV EAX,DWORD PTR SS:[EBP-C]
    007DFC5A   8338 00        CMP DWORD PTR DS:[EAX],0
    007DFC5D   74 01          JE SHORT 007DFC60
    007DFC5F   50             PUSH EAX
    007DFC60   FF75 F0        PUSH DWORD PTR SS:[EBP-10]
    007DFC63   FF65 EC        JMP DWORD PTR SS:[EBP-14]   <-在此处设断点
    007DFC66   5F             POP EDI
    007DFC67   5E             POP ESI
    007DFC68   5B             POP EBX
    007DFC69   8BE5           MOV ESP,EBP
    007DFC6B   5D             POP EBP
    007DFC6C   C3             RETN
 (2)
    再次按Shift-F9断在:007DFC63 处,寄存器窗口如下:
    EAX 100582D1 TestDll.100582D1
    ECX 0006FB6C
    EDX 00000000
    EBX 007F5ADA    
    ESP 0006FB40  <-在此地址上右键->在转存中跟随
    EBP 0006FB74
    ESI 007B0000
    EDI 007D0000
    EIP 007DFC63

    转存窗口:
    0006FB40 :    10000000    100582D1    2F1B414A    0006FB88
                                           ---**---    
                                 此处右键->断点->硬件访问->Word
  (3)
    按F9中断在异常处,再按Shift-F9,来到
    007F5C1E   05 B4F1E6D0    ADD EAX,D0E6F1B4
    007F5C23   5C             POP ESP
    007F5C24   0BC9           OR ECX,ECX
    007F5C26   74 02          JE SHORT 007F5C2A
    007F5C28   8901           MOV DWORD PTR DS:[ECX],EAX
    007F5C2A   03C3           ADD EAX,EBX
    007F5C2C   894424 1C      MOV DWORD PTR SS:[ESP+1C],EAX
    007F5C30   61             POPAD
    007F5C31   FFE0           JMP EAX  <--转到OEP

        1、到这里,仅仅是介绍了找到OEP的方法,此时还不能够Dump,因为ASProtect1.2的壳中
    使用了HookApi技术,有很多API被改做调用外壳中的变形代码了。所以,为了简便起见,最
    好要在Dump之前就将IAT中的这些API修正过来,这样ImportRect就可能全部找到了。

       2、可以在此处查找到Import,方法是:随便从程序找一个API调用,如:
    call dword ptr ds:[1003B040] ; APIFunction,在转存中跟随1003B040,上下看到许多函数地址,
    很明显的可以找到IAT开始和结束的地址(下面还将具体介绍查找IAT的方法)。


二、避开IAT加密

 (1)找到IAT变形处   
    
   [方法_1]
    重新加载TestDll.Dll,F9运行中断在异常处,Shift-F9,Shift_F9,向上翻看找到如下代码:
    007DF4A2   8BCB           MOV ECX,EBX
    007DF4A4   8D85 FFFEFFFF  LEA EAX,DWORD PTR SS:[EBP-101]
    007DF4AA   8BD6           MOV EDX,ESI
    007DF4AC   E8 AB4FFFFF    CALL 007D445C
    007DF4B1   6A 0A          PUSH 0A
    007DF4B3   B9 12397E00    MOV ECX,7E3912
    007DF4B8   8BD3           MOV EDX,EBX
    007DF4BA   8D85 FFFEFFFF  LEA EAX,DWORD PTR SS:[EBP-101]
    007DF4C0   E8 D7CEFFFF    CALL 007DC39C
    007DF4C5   8DB5 FFFEFFFF  LEA ESI,DWORD PTR SS:[EBP-101]
    007DF4CB   56             PUSH ESI
    007DF4CC   8B45 0C        MOV EAX,DWORD PTR SS:[EBP+C]
    007DF4CF   50             PUSH EAX
    007DF4D0   E8 17FCFFFF    CALL 007DF0EC              <-*** 这就是典型特征
    007DF4D5   E8 7EFEFFFF    CALL 007DF358              <-***(此函数完成API变形,nop掉)
    007DF4DA   8B17           MOV EDX,DWORD PTR DS:[EDI] <-***
    007DF4DC   8902           MOV DWORD PTR DS:[EDX],EAX <-***(edx是IAT中的一个地址)
    007DF4DE   EB 7B          JMP SHORT 007DF55B

   [方法_2]
    直接CTRL-S搜索:
    MOV EDX,DWORD PTR DS:[EDI]
    MOV DWORD PTR DS:[EDX],EAX

   [方法_3]
    在第(一)中的最后确定了IAT位置后,直接在内存地址上设置断点。

  (2)获取没变形的IAT
     在将007DF4D5处的call改成nop后,在数据窗口查看各个IAT是否已经全部 恢复,一旦恢复,立刻转
到007DF4D5处,将nop掉的call改回原来的call 007DF358,因为下面接着就是自校验,如果不改,程序
就不能够到达OEP了。然后通过:[一、找OEP] 的方法到达OEP。

三、Dump代码
      用LoadPE完全Dump TestDLL.DLL,Dump文件为dump.dll。此时的Dump.dll的IAT中的API已经几乎没
   有变形的了。

四、查找重定位表(参看fly的:用Ollydbg手脱ASProtect V1.23RC4加壳的DLL )

   ASProtect壳没有加密重定位表,这使得其脱壳要简单。             
   再次用Ollydbg载入TestDll.dll,F9中断在异常处。
   下断:BPX GetModuleHandleA,选择全部设置断点。
   当我们在GetModuleHandleA处中断2次后,清除所有断点,Alt+F9返回。

   返回后CTRL-S在“整个段块”搜索命令序列:

   代码:
   --------------------------------------------------------------------------------
   mov dx,word ptr ds:[ebx]
   movzx eax,dx
   shr eax,0C
   sub ax,1
   --------------------------------------------------------------------------------

   007DF90C   8B00           MOV EAX,DWORD PTR DS:[EAX]
   007DF90E   8B40 10        MOV EAX,DWORD PTR DS:[EAX+10] <-**[eax+10]=就是重定位表的RVA
   007DF911   8B4C24 04      MOV ECX,DWORD PTR SS:[ESP+4]
   007DF915   2BCA           SUB ECX,EDX
   007DF917   890C24         MOV DWORD PTR SS:[ESP],ECX
   007DF91A   833C24 00      CMP DWORD PTR SS:[ESP],0
   007DF91E   74 5F          JE SHORT 007DF97F
   007DF920   8B5C24 04      MOV EBX,DWORD PTR SS:[ESP+4]
   007DF924   03D8           ADD EBX,EAX
   007DF926   EB 51          JMP SHORT 007DF979
   007DF928   8D43 04        LEA EAX,DWORD PTR DS:[EBX+4]
   007DF92B   8B00           MOV EAX,DWORD PTR DS:[EAX]
   007DF92D   83E8 08        SUB EAX,8
   007DF930   D1E8           SHR EAX,1
   007DF932   8BFA           MOV EDI,EDX
   007DF934   037C24 04      ADD EDI,DWORD PTR SS:[ESP+4]
   007DF938   83C3 08        ADD EBX,8
   007DF93B   8BF0           MOV ESI,EAX
   007DF93D   85F6           TEST ESI,ESI
   007DF93F   7E 38          JLE SHORT 007DF979
   **************** 下面这是找到处 ********************
   007DF941   66:8B13        MOV DX,WORD PTR DS:[EBX]
   007DF944   0FB7C2         MOVZX EAX,DX
   007DF947   C1E8 0C        SHR EAX,0C
   007DF94A   66:83E8 01     SUB AX,1
   ****************************************************
   007DF94E   72 23          JB SHORT 007DF973
   007DF950   66:83E8 02     SUB AX,2
   007DF954   74 02          JE SHORT 007DF958
   007DF956   EB 11          JMP SHORT 007DF969
   007DF958   66:81E2 FF0F   AND DX,0FFF
   007DF95D   0FB7C2         MOVZX EAX,DX
   007DF960   03C7           ADD EAX,EDI
   007DF962   8B1424         MOV EDX,DWORD PTR SS:[ESP]
   007DF965   0110           ADD DWORD PTR DS:[EAX],EDX
   007DF967   EB 0A          JMP SHORT 007DF973
   007DF969   B8 90F97D00    MOV EAX,7DF990              ; ASCII "4"
   007DF96E   E8 69F0FFFF    CALL 007DE9DC
   007DF973   83C3 02        ADD EBX,2
   007DF976   4E             DEC ESI
   007DF977  ^75 C8          JNZ SHORT 007DF941
   007DF979   8B13           MOV EDX,DWORD PTR DS:[EBX]
   007DF97B   85D2           TEST EDX,EDX
   007DF97D  ^75 A9          JNZ SHORT 007DF928 <-** 退出循环时候,EBX = 重定位表结束地址VA
   007DF97F   59             POP ECX
   007DF980   5A             POP EDX
   007DF981   5F             POP EDI
   007DF982   5E             POP ESI
   007DF983   5B             POP EBX
   007DF984   C3             RETN

   得到重定位表信息:
   RVA=52000,大小=10055dc4-10052000=3dc4


五、修复IAT   
   启动ImportRect,Option中去掉:Use PE Head From Disk 选项,在OEP处填入找到的OEP,点
   击IAT AutoSearch,找到IAT,GetImport取得Import。
   ImportRect指示有一个不能识别的函数,需要手动修复:
   ********************************************************************
   [Kernel32]
     rva:0003b26c   prt:007dc424
   ********************************************************************
   LoadPE查看TestDll的ImageBase为0x10000000,则
   (1) 在转存中查看10000000+3b26c = 1003b26c,得到[1003b26c] = 7dc424
   (2) 在CPU窗口:右键->前往->表达(E) 或 CTRL-G,输入:7dc424,确认。
   (3) 看到反汇编代码如下:
     007DC424   55             PUSH EBP
     007DC425   8BEC           MOV EBP,ESP
     007DC427   8B55 0C        MOV EDX,DWORD PTR SS:[EBP+C]
     007DC42A   8B45 08        MOV EAX,DWORD PTR SS:[EBP+8]
     007DC42D   3B05 BC207E00  CMP EAX,DWORD PTR DS:[7E20BC]
     007DC433   75 09          JNZ SHORT 007DC43E
     007DC435   8B0495 EC217E0>MOV EAX,DWORD PTR DS:[EDX*4+7E21EC>
     007DC43C   EB 07          JMP SHORT 007DC445
     007DC43E   52             PUSH EDX
     007DC43F   50             PUSH EAX
     007DC440   E8 AF7FFFFF    CALL 007D43F4 ;JMP to KERNEL32.GetProcAddress <-**OllyDbg 提示出来
     007DC445   5D             POP EBP
     007DC446   C2 0800        RETN 8

     OllyDbg提示得很明确,这是个GetProcAddress。

   (4) 在ImportRect双击出错的rva,在弹出的窗口下面的Name中输入:GetProcAddress 并确定。
   (5) FixDump。
   (6) 启动LoadPE,将重定位表填入:RVA=52000 size=3dc4,保存。

   至此,TestDll.DLL完全脱壳,测试正常。

                                                           Spring.W
                                                           2005.3.4