【文章标题】: XX切割系统脱壳手记(Visual Protect -> Visage壳)
【文章作者】: newsoft88
【作者邮箱】: newsoft88@126.com
【软件名称】: XX切割系统
【软件大小】: 2.9M
【下载地址】: 自己搜索下载
【加壳方式】: Visual Protect -> Visage
【保护方式】: Visual Protect -> Visage
【编写语言】: DEPLI
【使用工具】: OD,PEID、HEX、LOADPE
【操作平台】: WINXPSP2
【软件介绍】: 主要功能是在板材玻璃等行业中,对切割产品进行优化
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  该软件系商业软件,本教程只探讨对脱的IAT的修复,不汲软件的解密与版权!
  
  软件说明:XX切割系统的主要功能是在板材、玻璃等行业中,对切割产品进行优化排样,充分提高材料的利用率,减轻人工排样的工作量,提高工作效率并节约材料成本。
  接触一个软件的最基本流程是先查壳,没壳那是最好不过了,但天下没那么便宜的事,用PEID查壳,为:Visual Protect -> Visage,该 壳的特点是IAT变形做得好,反ANTI功能稍差,对软件的注册保护也是依靠壳来,这也是一个弱点点,就是说壳脱了也就完事了!
  
  废话少说,请出看家工具OD,载入警告,不管,提示有壳,不再分析,载入后停在这里:
  004E9F90 w>  55                       push ebp
  004E9F91     8BEC                     mov ebp,esp
  004E9F93     51                       push ecx
  004E9F94     53                       push ebx
  004E9F95     56                       push esi
  004E9F96     57                       push edi
  004E9F97     C705 B00E4F00 00000000   mov dword ptr ds:[4F0EB0],0
  
  因为软件有NAG试用提示窗,所以直接运行至试用提示窗,
  
  004EAE6E     FF15 880E4F00            call dword ptr ds:[4F0E88]        ; VP.[NONAME] //进入壳的调用,检查试用期的注册情况;在些下断!
  004EAE74     83BD F8FEFFFF 00         cmp dword ptr ss:[ebp-108],0
  004EAE7B     74 0D                    je short wscut.004EAE8A
  
  在CALL处跟进,进入下面的代码
  
  00814C14 V>  55                       push ebp
  00814C15     8BEC                     mov ebp,esp
  00814C17     B9 C1000000              mov ecx,0C1
  00814C1C     6A 00                    push 0
  00814C1E     6A 00                    push 0
  00814C20     49                       dec ecx
  
  单步跟入
  
  00814F34     A1 B4BC8100              mov eax,dword ptr ds:[81BCB4]
  00814F39     BA 10668100              mov edx,VP.00816610               ; ASCII "License Failure"
  
  此处检查授权失败,继续跟入
  
  寻找OEP
  直接在00815E36 下断,F9 ,进入试用窗口,点试用后,断在下面代码处
  00815E36    /75 0A                    jnz short VP.00815E42
  00815E38    |A1 DCBB8100              mov eax,dword ptr ds:[81BBDC]
  00815E3D    |E8 7E4CFDFF              call VP.007EAAC0
  00815E42    \B8 E06A8100              mov eax,VP.00816AE0               ; ASCII "Uncomress Sections"
  00815E47     E8 ECBDFFFF              call VP.00811C38
  00815E4C     8B45 08                  mov eax,dword ptr ss:[ebp+8]
  00815E4F     FF10                     call dword ptr ds:[eax]
  00815E51     A1 84BB8100              mov eax,dword ptr ds:[81BB84]
  
  一路走来,发现   jmp dword ptr ss:[ebp-4]   就是跳各正确的OEP
  
  00815F9B     BA 786B8100              mov edx,VP.00816B78               ; ASCII "CodeCRCMatch False"
  00815FA0     E8 F7E8F5FF              call VP.0077489C
  00815FA5     8B85 64FAFFFF            mov eax,dword ptr ss:[ebp-59C]
  00815FAB     E8 88BCFFFF              call VP.00811C38
  00815FB0     A1 DCBB8100              mov eax,dword ptr ds:[81BBDC]
  00815FB5     E8 064BFDFF              call VP.007EAAC0
  00815FBA     8B45 FC                  mov eax,dword ptr ss:[ebp-4]
  00815FBD     33D2                     xor edx,edx
  00815FBF     52                       push edx
  00815FC0     50                       push eax
  00815FC1     8D95 58FAFFFF            lea edx,dword ptr ss:[ebp-5A8]
  00815FC7     B8 08000000              mov eax,8
  00815FCC     E8 AF2FF6FF              call VP.00778F80
  00815FD1     8B8D 58FAFFFF            mov ecx,dword ptr ss:[ebp-5A8]
  00815FD7     8D85 5CFAFFFF            lea eax,dword ptr ss:[ebp-5A4]
  00815FDD     BA 946B8100              mov edx,VP.00816B94               ; ASCII "Finalizing 0x"
  00815FE2     E8 B5E8F5FF              call VP.0077489C
  00815FE7     8B85 5CFAFFFF            mov eax,dword ptr ss:[ebp-5A4]
  00815FED     E8 46BCFFFF              call VP.00811C38
  00815FF2   - FF65 FC                  jmp dword ptr ss:[ebp-4]          ; wscut.004D0060 //跳向OEP
  
  F8 跟进后,程序停在这里\\OEP
  
  004D0060     55                       push ebp
  004D0061     8BEC                     mov ebp,esp
  004D0063     83C4 EC                  add esp,-14
  004D0066     53                       push ebx
  004D0067     33C0                     xor eax,eax
  004D0069     8945 EC                  mov dword ptr ss:[ebp-14],eax
  004D006C     B8 68FD4C00              mov eax,wscut.004CFD68
  004D0071     E8 7E6CF3FF              call wscut.00406CF4
  004D0076     8B1D 88314D00            mov ebx,dword ptr ds:[4D3188]     ; wscut.004D4C34
  004D007C     33C0                     xor eax,eax
  004D007E     55                       push ebp
  004D007F     68 CE014D00              push wscut.004D01CE
  004D0084     64:FF30                  push dword ptr fs:[eax]
  
  
  此时打开ImpoetREC ,输入OEP :D0060 ,点自动查找,发现很函数无效! 现在终于知道,IAT已经加密

  
  为知道加密情况,我们任意找个函数,看看是什么情况:
  
  00406C30   - FF25 94524D00            jmp dword ptr ds:[4D5294]
  00406C36     8BC0                     mov eax,eax
  00406C38   - FF25 90524D00            jmp dword ptr ds:[4D5290]
  00406C3E     8BC0                     mov eax,eax
  00406C40   - FF25 8C524D00            jmp dword ptr ds:[4D528C]
  00406C46     8BC0                     mov eax,eax
  00406C48   - FF25 88524D00            jmp dword ptr ds:[4D5288]
  
  我们在 jmp dword ptr ds:[4D5294] 跟进:
  
  代码如下 :
  
  01238410     B8 90A21600              mov eax,16A290
  01238415     FFE0                     jmp eax
  
  0016A290     B8 A1B6807C              mov eax,kernel32.GetModuleHandleA
  0016A295     FFE0                     jmp eax
  
  此处一跟,我们知道:加密也简单:两次给值,就是跳向正确的函数了!
  因为函数加密的较多,扬以我写了一节代码来修正他;找一块空白地方;代码如下
  OEP处改跳向
  004D0060    /E9 076F0100              jmp wscut.004E6F6C
  004D0065    |90                       nop
  004D0066    |53                       push ebx
  004D0067    |33C0                     xor eax,eax
  004D0069    |8945 EC                  mov dword ptr ss:[ebp-14],eax
  
  修正IAT代码:
  
  004E6F6C     50                       push eax                                                  //保护现场
  004E6F6D     53                       push ebx
  004E6F6E     51                       push ecx
  004E6F6F     52                       push edx
  004E6F70     33D2                     xor edx,edx
  004E6F72     3E:8B0495 A4514D00       mov eax,dword ptr ds:[edx*4+4D51A4]                        //取加密数据
  004E6F7A     3D 00004000              cmp eax,wscut.00400000                     ; ASCII "MZP"  //看是否IAT已经加密
  004E6F7F     7D 10                    jge short wscut.004E6F91                                  //没有加密则跳走
  004E6F81     83F8 00                  cmp eax,0
  004E6F84     74 0B                    je short wscut.004E6F91                                   //为空则跳走
  004E6F86     8B48 01                  mov ecx,dword ptr ds:[eax+1]                              //取正确的函数
  004E6F89     3E:890C95 A4514D00       mov dword ptr ds:[edx*4+4D51A4],ecx                       //修正IAT表
  004E6F91     42                       inc edx                                                   //跳向下个处理
  004E6F92     81FA 40070000            cmp edx,740                                               //是否全部处理完了
  004E6F98   ^ 7E D2                    jle short wscut.004E6F6C
  004E6F9A     52                       pop edx                                                   //恢复现场
  004E6F9B     51                       pop ecx
  004E6F9C     53                       pop ebx
  004E6F9D     50                       pop eax
  004E6F9E   ^ E9 BD90FEFF              jmp wscut.004D0060                                        //返回OEP
  004E6FA3     90                       nop
  
  返回OEP后,撤消代码的修改,再打开ImpoetREC ,输入OEP :D0060 ,点自动查找,发现很多函数正常了,但还有少数函数不正确!这是壳加密的原因!
  
  我们用LOADPE  DUMP出文件,使用ImpoetREC 修正IAT,此时运行程序出错,说明还有函数未修复!
  
  
  下面是手工活,我们举一个为例,其他相同:
  
  0042D306   |.  8BF0                   mov esi,eax
  0042D308   |.  8935 EC4A4D00          mov dword ptr ds:[4D4AEC],esi
  0042D30E   |.  85F6                   test esi,esi
  0042D310   |.  75 0A                  jnz short 12345_.0042D31C
  0042D312   |.  B8 A0784000            mov eax,<jmp.&user32.ShowScrollBar>
  0042D317   |.  A3 EC4A4D00            mov dword ptr ds:[4D4AEC],eax
  0042D31C       68 80D44200            push 12345_.0042D480                       ;  ASCII "FlatSB_GetScrollRange"
  0042D321       53                     push ebx
  0042D322       E8 599CFDFF            call 12345_.00406F80                   //此处跳向壳内,解密函数!
  0042D327   |.  8BF0                   mov esi,eax
  0042D329   |.  8935 F04A4D00          mov dword ptr ds:[4D4AF0],esi
  0042D32F   |.  85F6                   test esi,esi
  0042D331   |.  75 0A                  jnz short 12345_.0042D33D
  
  
  上面的跳向壳内的加密也很直观,就是把FlatSB_GetScrollRange转换为相应的函数地址,就OK了,为此,我们将上面代码改为:
  
  0042D306   |.  8BF0                   mov esi,eax
  0042D308   |.  8935 EC4A4D00          mov dword ptr ds:[4D4AEC],esi
  0042D30E   |.  85F6                   test esi,esi
  0042D310   |.  75 0A                  jnz short 12345_.0042D31C
  0042D312   |.  B8 A0784000            mov eax,<jmp.&user32.ShowScrollBar>
  0042D317   |.  A3 EC4A4D00            mov dword ptr ds:[4D4AEC],eax
  0042D31C       B8 72011B5D            mov eax,comctl32.FlatSB_GetScrollRange
  0042D321       90                     nop
  0042D322       90                     nop
  0042D323       90                     nop
  0042D324       90                     nop
  0042D325       90                     nop
  0042D326       90                     nop
  0042D327   |.  8BF0                   mov esi,eax
  0042D329   |.  8935 F04A4D00          mov dword ptr ds:[4D4AF0],esi
  0042D32F   |.  85F6                   test esi,esi
  0042D331   |.  75 0A                  jnz short 12345_.0042D33D
  
  也就是直接函数给EAX,就可以了,其余还有几处相同!
  
  这样,重建PE后,再运行程序一切OK,已没有NAG了,也没有试用期限了!
  
  
--------------------------------------------------------------------------------
【经验总结】
  该程序没有SDK,也没有自己的加密方法,全是依靠壳的加密,也是程序的失败之处,解壳后程序也就昭然于天下,这也是软件作
  者要注意的问题,本人也是软件加密的学习,欢迎你和我交流!
  
--------------------------------------------------------------------------------
【版权声明】: 谢谢观看, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年08月25日 22:14:25