【文章标题】: ASProtect 2.1x SKE dll文件脱壳+重定位表修复+优化
【作    者】: machenglin
【软件名称】: TestDog.dll
【大    小】: 306K
【加壳方式】: ASProtect 2.1x SKE->Alexey Solodovnikov
【编写语言】: Borland Delphi
【工    具】: WinXP、OllyDbg、PEiD、LordPE、RecImport、Dll_LoadEx、ReloX。
【操作平台】: WinXP sp2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  
      很多的大侠已经做过N多的ASProtect 2.1x SKE->Alexey Solodovnikov的exe软件的教程,有关ASProtect 2.1x SKE->Alexey Solodovnikov的dll教程不是很多。通过对dll脱壳的学习练习,参考了fly、Volx、syscom、linex等很多的大侠的教程,菜鸟就将dll脱壳的笔记发出来,希望高手能指正错误,给初学者提供一些思路。
  
  用 PEid 0.94 显示为 ASProtect 2.1x SKE -> Alexey Solodovnikov
  用flyDBG载入,ALT+O, 设置内存访问异常,以及下面“同时忽略以下指定的异常或者异常范围”,其余选项全部忽略。
     
  
  008D2001 >  60               pushad                                     ; OD入口     
  008D2002    E8 03000000      call TestDogj.008D200A
  008D2007  - E9 EB045D45      jmp 45EA24F7
  008D200C    55               push ebp
  008D200D    C3               retn
  008D200E    E8 01000000      call TestDogj.008D2014
  
  ---------------------------------------------------------------------------------------------------------------
  一、找到OEP    
  
  Shift+F9,一直到第二次出现855CCAEF。
  
  Alt+M,在该dll的code段,F2下断。
  
  Shift+F9,来到OEP了。
  
  008BFF4C    55               push ebp
  008BFF4D    8BEC             mov ebp,esp
  008BFF4F    83C4 B4          add esp,-4C
  008BFF52    B8 E4FD8B00      mov eax,TestDogj.008BFDE4
  008BFF57    E8 E064FBFF      call TestDogj.0087643C
  008BFF5C    E8 EF38FBFF      call TestDogj.00873850
  008BFF61    8D40 00          lea eax,dword ptr ds:[eax]
  008BFF64    0000             add byte ptr ds:[eax],al
  ---------------------------------------------------------------------------------------------------------------
  二、发现IAT、call xxxxxxxx。
  
  Ctrl+B:FF 25。
  
  008711D8  - FF25 A8318C00    jmp dword ptr ds:[8C31A8]                    ; kernel32.CloseHandle
  008711DE    8BC0             mov eax,eax
  008711E0  - FF25 A4318C00    jmp dword ptr ds:[8C31A4]                    ; kernel32.CreateFileA
  008711E6    8BC0             mov eax,eax
  008711E8    E8 13EE2D00      call 00B50000                                ; call xxxxxxxx①
  008711ED    7B 8B            jpo short TestDog1.0087117A
  008711EF    C0E8 0B          shr al,0B
  008711F2    EE               out dx,al
  008711F3    2D 00D48BC0      sub eax,C08BD400                             ; call xxxxxxxx①
  008711F8    E8 03EE2D00      call 00B50000
  
  右键--->数据窗口跟随--->内存地址。
  
  在数据窗口右键--->长型--->地址。
  
  向上滚动来到IAT开始。
  
  008C3104  1FFC7DB3
  008C3108  7C93188A  ntdll.RtlDeleteCriticalSection                        ; IAT开始②
  008C310C  7C9210ED  ntdll.RtlLeaveCriticalSection
  008C3110  7C921005  ntdll.RtlEnterCriticalSection
  008C3114  7C809FA1  kernel32.InitializeCriticalSection
  .................
  008C3134  7C80A0C7  kernel32.WideCharToMultiByte
  008C3138  7C809CAD  kernel32.MultiByteToWideChar
  008C313C  768C6426                                                        ; IAT加密
  008C3140  7C810311  kernel32.lstrcpynA
  008C3144  7C80C729  kernel32.lstrcpyA
  008C3148  397191AA                                                        ; IAT加密
  008C314C  4524D92E                                                        ; IAT加密
  008C3150  5083EFAF                                                        ; IAT加密
  008C3154  7C80AC28  kernel32.GetProcAddress
  008C3158  82EE7A98                                                        ; IAT加密
  ..................
  008C36F0  5D17BD2E  comctl32.ImageList_Destroy
  008C36F4  5D17BB5B  comctl32.ImageList_Create
  008C36F8  00000000
  008C36FC  77DC3238  ADVAPI32.StartServiceA                                ; IAT结束③
  008C3700  BC9A88FE
  向上滚动来到IAT结束。
  
  现在,我们得到这些必要的数据,开始解决IAT加密的问题。
  ----------------------------------------------------------------------------------------------------------------
  三、测试IAT加密
  
  Ctrl+F2重起OD,在OD入口处Shift+F9,一直到第一次出现0B6。                 ; 未知命令
  
  0097EA55    C601 B6          mov byte ptr ds:[ecx],0B6                   ; 第一次出现0B6。            
  0097EA58    6323             arpl word ptr ds:[ebx],sp
  0097EA5A    DEAA B86B9C6B    fisubr word ptr ds:[edx+6B9C6BB8]
  0097EA60    75 11            jnz short 0097EA73
  0097EA62    E5 8F            in eax,8F
  0097EA64    FE               ???                                          ; 未知命令
  
  右键--->搜索--->文本字符串,在第一个85下双击,来到这里。
  
  0097EBF6   /EB 0A            jmp short 0097EC02
  0097EBF8   |68 E8F49700      push 97F4E8                                  ; ASCII "85"
  0097EBFD   |E8 2A62FEFF      call 00964E2C
  0097EC02   \A1 1C379800      mov eax,dword ptr ds:[98371C]
  0097EC07    8B00             mov eax,dword ptr ds:[eax]
  0097EC09    E8 0A8CFFFF      call 00977818                                ; 在这里F2下断。
  0097EC0E    84C0             test al,al
  0097EC10    75 0A            jnz short 0097EC1C
  0097EC12    68 E8F49700      push 97F4E8                                  ; ASCII "85"
  0097EC17    E8 1062FEFF      call 00964E2C
  0097EC1C    A1 EC379800      mov eax,dword ptr ds:[9837EC]
  
  在0097EC09这个call下F2断点,Shift+F9,中断在这里,F2取消断点,F7进入这个call。
  
  向下拉动,在0097795A这个call下F2断点。F9,中断,F2取消断点,F7进入这个call。
  
  00977939   /75 0A            jnz short 00977945
  0097793B   |68 94799700      push 977994                                  ; ASCII "180"
  00977940   |E8 E7D4FEFF      call 00964E2C
  00977945   \834424 08 04     add dword ptr ss:[esp+8],4
  0097794A    47               inc edi
  0097794B    EB 1A            jmp short 00977967
  0097794D    83C7 02          add edi,2
  00977950    8BC7             mov eax,edi
  00977952    50               push eax
  00977953    55               push ebp
  00977954    8D4424 10        lea eax,dword ptr ss:[esp+10]
  00977958    50               push eax
  00977959    56               push esi
  0097795A    E8 59FCFFFF      call 009775B8                                ; 在0097795A下F2断点。
  0097795F    0FB707           movzx eax,word ptr ds:[edi]
  
  F9,中断,F2取消断点,F7进入这个call。
  
  009775F2    3BF0             cmp esi,eax                                  ; 下F2断点。
  009775F4    75 5E            jnz short 00977654    
  009775F6    EB 01            jmp short 009775F9
  009775F8    C7               ???                                          ; 未知命令
  
  在数据窗口定位IAT区段,Ctrl+G:008C3108 (IAT头)。
  
  在009775F2地址连续F9,注意数据窗口第一个出现了,看积存器ESI为6D,继续F9。
  ====================================================
  008C3100  00000000
  008C3104  59A77327
  008C3108  7C93188A  ntdll.RtlDeleteCriticalSection
  008C310C  29026569
  008C3110  2023122F
  ====================================================
  
  通过测试,6D、1C是没有加密,A8是加密,最好能测试完全部的IAT。
  -----------------------------------------------------------------------------------------------------------------
  四、测试IAT加密
  
  Ctrl+F2重起,重复进行到009775F2这个比较,F2断点,F9,中断。
  
  用OD的插件HideOD申请内存,我这里分配给00B40000。
  
  修改009775F4:
  009775F4    75 5E            jnz short 00977654                           ; jnz short 00977654-->jmp 00B40000
  
  F8步进,来到申请内存00B40000,键入以下补丁代码。
  ===============================
  je  009775F9
  com esi,1C
  je  00977654 
  mov esi,1C
  jmp 00977654
  ================================
  0F 84 F3 75 E3 FF 83 FE 10 0F 84 45 76 E3 FF BE 10 00 00 00 E9 3B 76 E3 FF 90 
  
  定位数据窗口在IAT区段,Shift+F9,现在IAT已经全部解密了。
  
  但注意的一点是要检查所有的IAT是否完全解密,有时候它是和解密的参数数据是对应的,不一定用一个没加密的参数解密所有加
  密的参数,也许有些地址只响应所对应的解密参数。
  
  撤消申请内存和009775F4的修改,准备下面再用。
  
  00977188    8945 F0          mov dword ptr ss:[ebp-10],eax
  0097718B    B8 00070000      mov eax,700
  00977190    E8 B7B3FDFF      call 0095254C                                ; 记住这个地址,一会用。
  00977195    8945 E4          mov dword ptr ss:[ebp-1C],eax
  00977198    C645 EF 00       mov byte ptr ss:[ebp-11],0
  0097719C    8B7D F8          mov edi,dword ptr ss:[ebp-8]
  0097719F    8B75 E4          mov esi,dword ptr ss:[ebp-1C]
  
  继续Shift+F9,到达最后一次的855CCAEF。
  
  Alt+M,在该dll的code段,F2下断,Ctrl+F9,来到OEP。
  
  Ctrl+G:00977190
  
  修改:
  00977190    E8 B7B3FDFF      call 0095254C                                ; call 0095254C-->jmp 00B40043
  
  Ctrl+G:00B40000。
  ----------------------------------------------------------------------------------------------------------------
  00B40000    0000             add byte ptr ds:[eax],al
  00B40002    0000             add byte ptr ds:[eax],al
  00B40004    0000             add byte ptr ds:[eax],al
  00B40006    0000             add byte ptr ds:[eax],al
  00B40008    0000             add byte ptr ds:[eax],al
  00B4000A    BA 00108700      mov edx,871000                               ; code段头④
  00B4000F    803A E8          cmp byte ptr ds:[edx],0E8
  00B40012    75 14            jnz short 00B40028
  00B40014    8B42 01          mov eax,dword ptr ds:[edx+1]
  00B40017    03C2             add eax,edx
  00B40019    05 05000000      add eax,5
  00B4001E    3D 0000B600      cmp eax,0B60000                              ; call xxxxxxxx①
  00B40023    75 03            jnz short 00B40028
  00B40025    EB 0C            jmp short 00B40033
  00B40027    90               nop
  00B40028    42               inc edx
  00B40029    81FA 00008C00    cmp edx,8C0000                               ; data段头⑤
  00B4002F  ^ 72 DE            jb short 00B4000F
  00B40031  - EB FE            jmp short 00B40031
  00B40033    8915 0001B400    mov dword ptr ds:[B40100],edx
  00B40039    60               pushad
  00B4003A    FFE2             jmp edx
  00B4003C    90               nop
  00B4003D    90               nop
  00B4003E    90               nop
  00B4003F    90               nop
  00B40040    90               nop
  00B40041    90               nop
  00B40042    90               nop
  00B40043    60               pushad
  00B40044    B8 08318C00      mov eax,8C3108                               ; IAT开始②
  00B40049    90               nop
  00B4004A    3910             cmp dword ptr ds:[eax],edx
  00B4004C    75 23            jnz short 00B40071
  00B4004E    8B0D 0001B400    mov ecx,dword ptr ds:[B40100]
  00B40054    C701 FF250000    mov dword ptr ds:[ecx],25FF
  00B4005A    8941 02          mov dword ptr ds:[ecx+2],eax
  00B4005D    61               popad
  00B4005E    90               nop
  00B4005F    8B15 0001B400    mov edx,dword ptr ds:[B40100]
  00B40065    90               nop
  00B40066    90               nop
  00B40067    90               nop
  00B40068  ^ EB BE            jmp short 00B40028
  00B4006A    90               nop
  00B4006B    90               nop
  00B4006C    90               nop
  00B4006D    90               nop
  00B4006E    90               nop
  00B4006F    90               nop
  00B40070    90               nop
  00B40071    83C0 04          add eax,4
  00B40074    3D FC368C00      cmp eax,8C36FC                               ; IAT结束③
  00B40079  ^ 7E CF            jle short 00B4004A
  00B4007B  ^ EB E0            jmp short 00B4005D
  00B4007D    90               nop
  00B4007E    90               nop
  00B4007F    90               nop
  00B40080    0000             add byte ptr ds:[eax],al
  00B40082    0000             add byte ptr ds:[eax],al
  -----------------------------------------------------------------------------------------------------------------
  00 00 00 00 00 00 00 00 00 00 BA 00 10 87 00 80 3A E8 75 14 8B 42 01 03 C2 05 05 00 00 00 3D 00 00 B6 00 75 03 EB 
  0C 90 42 81 FA 00 00 8C 00 72 DE EB FE 89 15 00 01 B4 00 60 FF E2 90 90 90 90 90 90 90 60 B8 08 31 8C 00 90 39 10 
  75 23 8B 0D 00 01 B4 00 C7 01 FF 25 00 00 89 41 02 61 90 8B 15 00 01 B4 00 90 90 90 EB BE 90 90 90 90 90 90 90 83 
  C0 04 3D FC 36 8C 00 7E CF EB E0 90 90 90

  在00B4000A新建EIP,F9运行,OK。
  
  在数据窗口,Ctrl+G:008711E8,检查call xxxxxxxx修复。
  -----------------------------------------------------------------------------------------------------------------
  008711E8  - FF25 A0318C00    jmp dword ptr ds:[8C31A0]                    ; kernel32.GetFileType
  008711EE    8BC0             mov eax,eax
  008711F0  - FF25 9C318C00    jmp dword ptr ds:[8C319C]                    ; kernel32.GetFileSize
  008711F6    8BC0             mov eax,eax
  008711F8  - FF25 98318C00    jmp dword ptr ds:[8C3198]                    ; kernel32.GetStdHandle
  008711FE    8BC0             mov eax,eax
  00871200  - FF25 94318C00    jmp dword ptr ds:[8C3194]                    ; kernel32.RaiseException
  00871206    8BC0             mov eax,eax
  00871208  - FF25 90318C00    jmp dword ptr ds:[8C3190]                    ; kernel32.ReadFile
  0087120E    8BC0             mov eax,eax
  00871210  - FF25 8C318C00    jmp dword ptr ds:[8C318C]                    ; ntdll.RtlUnwind
  00871216    8BC0             mov eax,eax
  00871218  - FF25 88318C00    jmp dword ptr ds:[8C3188]                    ; kernel32.SetEndOfFile
  0087121E    8BC0             mov eax,eax
  00871220  - FF25 84318C00    jmp dword ptr ds:[8C3184]                    ; kernel32.SetFilePointer
  00871226    8BC0             mov eax,eax
  00871228  - FF25 80318C00    jmp dword ptr ds:[8C3180]                    ; kernel32.UnhandledExceptionFilter
  0087122E    8BC0             mov eax,eax
  00871230  - FF25 7C318C00    jmp dword ptr ds:[8C317C]                    ; kernel32.WriteFile
  00871236    8BC0             mov eax,eax
  00871238  - FF25 BC318C00    jmp dword ptr ds:[8C31BC]                    ; USER32.CharNextA
  0087123E    8BC0             mov eax,eax
  00871240  - FF25 78318C00    jmp dword ptr ds:[8C3178]                    ; kernel32.ExitProcess
  -----------------------------------------------------------------------------------------------------------------
  看来已经全部修复了。
  
  好了,现在用LordPE-->dump, 选择下面的脱壳dll进程,完整转存为dump.dll。
  
  打开RecImport,选loaddll进程,选dll,填入OEP:008BFF4C-870000=4FF4C,RVA:008C3108-400000=4C3108,获取输入表,剪切
  无效指针,修复抓取文件,存为dump_.dll。
  
  重新启动OD,载入dump_.dll,F9运行,单独运行正常。修改文件名为原版TestDog.dll,启动主程序,出现错误,看来是重定位表
  引起。
  -----------------------------------------------------------------------------------------------------------------
  五、修复重定位表reloc。
  
  运行Dll_LoadEx,复制一个原版的dll,load原版的dll和复制原版的dll。
  
  运行LordPE,注意下面镜象地址不同,镜象大小一样的二个dll。完整转存为1.dll、2.dll。
  
  运行ReloX。
  1、分别载入1.dll、2.dll;
  2、按elect Section,勾选CODE、DATA、BBS、idata四个区段,OK;
  3、Compare, 稍等即完成;
  4、按Fix PE Module,选择需要修复重定位表的dll,修复成功。
  
  修改镜象地址,原来的镜象地址为00400000,修改为00870000。
  
  启动主程序,跑的很顺畅。
  
  -----------------------------------------------------------------------------------------------------------------
  六、优化脱壳文件。
  
  原版dll文件字节是306K,脱壳后文件为568K,还是大概优化一下。
  
  把段.mackt、.reloc保存到磁盘,记住.data 的Voffset=62000。
  
  清除.rsrc后的所有区块。
  
  打开WinHex,载入文件-->位置-->偏移地址:62000,选块开始,到文件尾选块结束,编辑-->移除。
  
  定位到PE头,将.rsrc后到PE尾块选择-->编辑-->用00填充,保存文件。
  
  打开LordPE,从磁盘载入段.mackt、修改为Voffset=00850000,修改.rsrc的Vsize为85000-5D000=28000。
  
  再从磁盘载入段.reloc。
  
  优化结束,文件字节从568K-->428K。
  
  测试结果,OK。
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  附练习文件。
  
--------------------------------------------------------------------------------
【版权声明】: 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!