吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 13308|回复: 22
收起左侧

[原创] 促进钢蛋壳升级-简单分析及脱VProtect1.72demo版加密VB程序

[复制链接]
wuqing1501 发表于 2010-7-18 02:54

【文章标题】: 促进钢蛋壳升级-简单分析及脱VProtect1.72demo版加密VB程序
【文章作者】: wuqing1501(笨笨鼠)
【作者邮箱】: 看个人资料
【作者主页】: 看个人资料
【作者QQ号】: 看个人资料
【软件名称】: vprotect1.72DEMO
【下载地址】: upk就有
【使用工具】: 老三样了
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
      今天闲来无事就看了看钢蛋壳的 IAT加密,在1.62和1.63的时候 就看过那个时候的IAT加密比较简单,当然在VM中的加密还是不好搞的 因为有太多的垃圾代码,一直没有搞定,所以就一直放下不看了,今天老是感觉应该看看VM中的加密是如何修复的,于是就有了这篇文章了。
      开始吧!
      为了方便研究,我直接用VProtect1.72DEMO版给VB程序加壳分别选取最大速度,中等强度和最高强度!呵呵,为什么选VB程序呢?因为VB的简单修复方式也容易些,用其他IAT被处理的会更复杂一些修复也难,还是先从最简单的看看吧!
      准备好了加壳的软件就可以开始了!
      在1.62、1.63的时候到OEP是很简单的,直接在CODE段下内存访问断点,然后F9,过了NAG窗口后,就挺停在了解码的位置,然后F7、F8、F9各一次就到达OEP了!但是这次1.72的好像对内存断点进行了处理,也不知道是不是我的系统的问题,用上面的方法就不行了,到达解码位置后,按F7软件就出错了!所以我们换个方法吧!这个软件的大流程是不变的,只要断在解码的地方,然后CODE段下断点,F9就到OEP了,既然壳不然下内存断点,那我们就在CODE段下个硬件写入断点吧,这样解码的时候照样能段下来,断在解码位置后,这次再按F7、F8就没有事了,然后再在CODE段下F2或者内存访问都行,F9一次直接到达OEP!
      好了我们正式开始吧
  
  1.先看下最大速度吧
  
  0043A180 >  3BC0            CMP EAX,EAX                              ; OD载入后停在这里
  0043A182    74 1C           JE SHORT 0043A1A0
  0043A184    EB 00           JMP SHORT 0043A186
  0043A186    DB2D 8CA14300   FLD TBYTE PTR DS:[43A18C]
  0043A18C    FFFF            ???                                      ; Unknown command
  0043A18E    FFFF            ???                                      ; Unknown command
  0043A190    FFFF            ???                                      ; Unknown command
  0043A192    FFFF            ???                                      ; Unknown command
  
      然后在CODE段下硬件写入断点
  
  003C0000   00001000                                       Priv   RW        RW
  00400000   00001000   vb例子_V                PE header     Imag   R         RWE
  00401000   00009000   vb例子_V     .text      code          Imag   R         RWE        ;在这里双击进去后下硬件写入断点
  0040A000   00002000   vb例子_V     .data      data          Imag   R         RWE
  0040C000   00002000   vb例子_V     .rsrc      resources     Imag   R         RWE
  0040E000   0002B000   vb例子_V     VProtect                 Imag   R         RWE
  00439000   00071000   vb例子_V     VProtect   SFX,imports   Imag   R         RWE
  004B0000   00005000                                       Map    R E       R E
   
      我们在CODE段双击进去
  
  00401000   00009000   vb例子_V     .text      code          Imag   R         RWE        ;在这里双击进去后下硬件写入断点
  
      来到这里
  
  00401000    0000            ADD BYTE PTR DS:[EAX],AL   ;在这里下硬件写入断点
  00401002    0000            ADD BYTE PTR DS:[EAX],AL
  00401004    0000            ADD BYTE PTR DS:[EAX],AL
  00401006    0000            ADD BYTE PTR DS:[EAX],AL
  00401008    0000            ADD BYTE PTR DS:[EAX],AL
  0040100A    0000            ADD BYTE PTR DS:[EAX],AL
  0040100C    0000            ADD BYTE PTR DS:[EAX],AL
  
      然后F9运行,出现了NAG窗口,关掉NAG窗口后,停在了这里
  
  0043BB3A >  F3:A5           REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]        ;这里就是VP解码的地方
  0043BB3C    FF2495 54BC4300 JMP DWORD PTR DS:[EDX*4+43BC54]
  0043BB43    90              NOP
  0043BB44    8BC7            MOV EAX,EDI
  0043BB46    BA 03000000     MOV EDX,3
  
      然后F7一次,F8一次,然后在CODE段下F2或者内存访问断点,F9运行来到这里,就是FLY说的光明之巅:
  
  004014B0    68 28264000     PUSH 00402628            ;终于看到了光明之巅了,OEP
  004014B5    E8 F0FFFFFF     CALL 004014AA
  004014BA    0000            ADD BYTE PTR DS:[EAX],AL
  004014BC    0000            ADD BYTE PTR DS:[EAX],AL
  004014BE    0000            ADD BYTE PTR DS:[EAX],AL
  004014C0    3000            XOR BYTE PTR DS:[EAX],AL
  004014C2    0000            ADD BYTE PTR DS:[EAX],AL
  004014C4    3800            CMP BYTE PTR DS:[EAX],AL
  
      看下IAT吧
  
  0040148C  - E9 17D70000     JMP 0040EBA8
  00401491    90              NOP
  00401492  - E9 39D70000     JMP 0040EBD0
  00401497    90              NOP
  00401498  - E9 5BD70000     JMP 0040EBF8
  0040149D    90              NOP
  0040149E  - E9 7DD70000     JMP 0040EC20
  004014A3    90              NOP
  004014A4  - E9 9FD70000     JMP 0040EC48
  004014A9    90              NOP
  004014AA  - E9 C1D70000     JMP 0040EC70
  004014AF    90              NOP
  
      都被处理成照样了,然后JMP到壳段,具体的加密方式自己看下加密后软件吧,我们主要看下IAT的解码,主要是下面这几句:
  
  00414B20    B8 7FDE09C4     MOV EAX,C409DE7F
  00414F80    BB AD16373C     MOV EBX,3C3716AD
  0042ABD0    03C3            ADD EAX,EBX
  0041BCE0    8B00            MOV EAX,DWORD PTR DS:[EAX]
  00419430    8D0418          LEA EAX,DWORD PTR DS:[EAX+EBX]
  00413480    874424 24       XCHG DWORD PTR SS:[ESP+24],EAX
  
      上面这几句就是解密IAT的,中间穿插了很多的垃圾指令,当程序运行到过这条 LEA EAX,DWORD PTR DS:[EAX+EBX] 指令的时候,真实的IAT地址就存放在EAX中。感觉这个地方和VMP有些相似!
      本人菜鸟不会些解码,但是,既然程序运行过程中在EAX中出现了真实的IAT,那么我们可以写个脚本,在程序中查找被处理的IAT 也就是 E9???????? 这样类型的,然后判断下是不是被处理的IAT,如果不是就查找下一个,如果是的话,就单步,一直到EAX中出现真实的IAT地址,我们就把EAX的值写回到原来调用的地方,最后再后UIF处理一下就可以了。
      贴出我写的脚本吧,用以前的脚本修改的,可能有些乱,脚本也写的难看,最主要的是针对这种加密方式,这种处理方式可以说效率特别低,但是我太菜了,没有找到好的处理方式。
  
  
  var neicuncodebase            
  var neicuncodesize   
  var oep
  var ptr
  var ip1
  var addr
  var refaddr
  var temesp
  var ptr1
  var code
  var kebase1
  var kebase2
  var iataddr
  
  mov kebase1,0040e000
  mov oep,eip
  mov temesp,esp
  mov eip,kebase1
  
  start:              
                 mov esp,temesp
                 mov eip,00401000 //???????
                 mov ptr1,eip
  
  tzm3iatfind:
                 
                 mov temesp,esp
                 find  ptr1, #e9????????#   
                 je    exit                     
                 mov   ptr,$RESULT   
                 mov   ptr1,ptr
                 mov   eip,ptr
                 mov   refaddr, ptr
                 sti
                 mov ip1, eip
                 mov ip1, [ip1]
                 and ip1, 0ff
                 cmp ip1, e9
                 jnz nextfind
                 sti
                 mov ip1, eip
                 mov ip1, [ip1]
                 and ip1, 0ff
                 cmp ip1, 68
                 jnz nextfind            
                 cmp eip,kebase2
                 ja tzm3iataddrfind
                 cmp eip,kebase1
                 jb tzm3iatfind              
                 
  tzm3iataddrfind:
  
                 sti
                 mov iataddr,eax
                 gn iataddr
                 cmp   $RESULT,0
                 je tzm3iataddrfind
  tzm3iatfix:
              
                 sub eax,refaddr
                 SUB eax,5
                 mov refaddr,ptr
                 mov [refaddr],#e9#
                 add refaddr,1
                 mov [refaddr],eax,4
                 mov esp,temesp
  nextfind:
                 add ptr1,6
                 jmp tzm3iatfind
  exit:
                mov esp,temesp
                mov eip,oep
                ret
  
  
      照样脚本处理好后,用UIF修复一下,然后LP,然后IR修复就可以了!
  
  2、接下来看些中等强度和最大强度吧
  
      流程和上面是一样的,到达OEP的方法一样,但是中等强度和最大强度,对IAT的加密采取了很WS的方式,代码里面全是垃圾代码,本来我想把垃圾代码全部清除,然后再单步跟的,发现那个不是一般的费劲啊,不过还是写了个脚本来清理垃圾指令。共发现5种,脚本如下:
  
  
  
  var addr
  var yeip
  var temsep
  var long
  var addr1
  huazhiliang1:
  mov yeip,eip
  mov addr,eip
  mov addr1,eip
  mov long,460000  //这里是处理的代码长度,可以自己根据实际情况修改,下面的这个参数都一样
  add addr1,long
  
  findhua1:
  
  mov temesp,esp
  find eip,#740EEB0E????????750E740C????????74F675F4#
  cmp $RESULT,0
  je exit1
  mov eip,$RESULT
  mov [eip],#909090909090909090909090909090909090909090909090#
  mov esp,temesp
  add eip,20
  cmp eip,addr1
  jg  exit1
  jmp findhua1
  
  exit1:
  mov eip,yeip
  
  huazhiilang2:
  
  var addr
  var yeip
  var temsep
  var long
  var addr1
  
  mov yeip,eip
  mov addr,eip
  mov addr1,eip
  mov long,460000
  add addr1,long
  
  findhua2:
  
  mov temesp,esp
  find eip,#740A7508#
  cmp $RESULT,0
  je exit2
  mov eip,$RESULT
  mov [eip],#740A75089090909090909090#
  mov esp,temesp
  add eip,20
  cmp eip,addr1
  jg  exit2
  jmp findhua2
  
  exit2:
  mov eip,yeip
  
  huzhiiang3:
  
  var addr
  var yeip
  var temsep
  var long
  var addr1
  
  mov yeip,eip
  mov addr,eip
  mov addr1,eip
  mov long,460000
  add addr1,long
  
  findhua3:
  
  mov temesp,esp
  find eip,#7403#
  cmp $RESULT,0
  je exit3
  mov eip,$RESULT
  mov [eip],#7403909090#
  mov esp,temesp
  add eip,20
  cmp eip,addr1
  jg  exit3
  jmp findhua3
  
  exit3:
  mov eip,yeip
  
  
  huazhiling4:
  
  var addr
  var yeip
  var temsep
  var long
  var addr1
  
  mov yeip,eip
  mov addr,eip
  mov addr1,eip
  mov long,460000
  add addr1,long
  
  findhua4:
  
  mov temesp,esp
  find eip,#c3eb08#
  cmp $RESULT,0
  je exit4
  mov eip,$RESULT
  mov [eip],#9090909090909090909090#
  mov esp,temesp
  add eip,20
  cmp eip,addr1
  jg  exit4
  jmp findhua4
  
  exit4:
  mov eip,yeip
  
  var addr
  var yeip
  var temsep
  var long
  var addr1
  
  mov yeip,eip
  mov addr,eip
  mov addr1,eip
  mov long,460000
  add addr1,long
  
  findhua5:
  
  mov temesp,esp
  find eip,#740EEB0E????????750E740C????????????75F4????????#
  cmp $RESULT,0
  je exit5
  mov eip,$RESULT
  mov [eip],#909090909090909090909090909090909090909090909090#
  mov esp,temesp
  add eip,20
  cmp eip,addr1
  jg  exit5
  jmp findhua5
  
  exit5:
  mov eip,yeip
  ret
  
      既然清理垃圾指令的方法行不同,那我们只好换个方法吧,我的思路是,不管在VM中还是在垃圾指令里,程序总要返回IAT的真实地址的,也就是在垃圾指令或VM中运行过程中,寄存器中总会出现IAT的真实地址的,那我们就先看看在什么地方在那个寄存器里会出现真实的地址,寄存器是固定的还是随机的,写个小 脚本测试一下吧。
  
  var addr
  Find:
  sti
  mov addr,eax
  mov addr,[addr]
  gn addr
  cmp $RESULT,0
  jne zt
  mov addr,ecx
  mov addr,[addr]
  gn addr
  cmp $RESULT,0
  jne zt
  mov addr,ebx
  mov addr,[addr]
  gn addr
  cmp $RESULT,0
  jne zt
  mov addr,edx
  mov addr,[addr]
  gn addr
  cmp $RESULT,0
  je Find
  mov addr,esp
  mov addr,[addr]
  gn addr
  cmp $RESULT,0
  je Find
  
  zt:
  pause
  
      具体的代码我就补写了,全是垃圾指令而且很多很多,当寄存器中出现IAT的真实地址的时候OD就会停下来,我们就可以分析到底最关键的出现IAT的代码是那些了!在VM中跑照样的脚本,那不是一般的慢,我都不知道今天晚上电脑跑了多长的时间才跑完的! 最后经过测试中等强度的加密方式会在壳段中以下代码的时候出现真实的地址:
  
      对于中等强度:
  
  0041EE71    C3              RETN
  0041EE72    50              PUSH EAX
  0041EE73    53              PUSH EBX  ;中等强度的加密方式,在壳段中只有一处这个代码,也就是所有的IAT都要经过这里,而当程序运行到这条指令的时候,EBX中就是真实的IAT。   
  0041EE74    51              PUSH ECX
  
      对于最大强度,和中等强度一样,只是关键代码和寄存器不一样而已;
  
  0041EE71    59              POP ECX
  0041EE72    5B              POP EBX
  0041EE73    58              POP EAX
  0041EE74    8BC1            MOV EAX,ECX
  0041EE76    8B4F 24         MOV ECX,DWORD PTR DS:[EDI+24]
  0041EE79    51              PUSH ECX
  0041EE7A    9D              POPFD
  0041EE7B    03C3            ADD EAX,EBX
  0041EE7D    8B5F 44         MOV EBX,DWORD PTR DS:[EDI+44]
  0041EE80    8903            MOV DWORD PTR DS:[EBX],EAX
  0041EE82    9C              PUSHFD                              ;//最大强度的加密方式,在壳段中只有一处这个代码,也就是所有的IAT都要经过这里,而当程序运行到这条指令的时候,EAX中就是真实的IAT。
  0041EE83    58              POP EAX
  
      而且经过测试,对于加密后的VB程序,中等强度和最大强度都存在了这个特征码,而且利用的寄存器是固定的,照样也方便写脚本了。
      好了有了上面的分析就可以写个脚本来查找IAT了。没有太多的分析大家看脚本吧,最好用脚本跑一下就能明白了!
      脚本如下:
  
  
  var neicuncodebase            
  var neicuncodesize   
  var oep
  var ptr
  var ip1
  var addr
  var refaddr
  var temesp
  var ptr1
  var code
  var kebase1
  var kebase2
  var iataddr
  
  mov kebase1,0040e000   //第一个壳段
  mov kebase2,00507000   //第二个壳段
  mov oep,eip
  mov temesp,esp
  
  findkebase1tzm2:
  
                mov eip,kebase1
                find  eip, #C3505351#  //中等强度的特征码,最大强度特征码为“#595B588BC18B4F24519D03C38B5F4489039C58#”
                cmp   $RESULT,0
                je findkebase2tzm2
                add  $RESULT,2         //因为中等强度代码当运行到PUSH EBX 这条指令的时候,EBX是真实的地址所以这里加2,同理,对于最大强度这里应该加11
  /*                                   0041EE71    C3              RETN
                                       0041EE72    50              PUSH EAX
                                       0041EE73    53              PUSH EBX  ;EBX 中就是真实的IAT。   
                                       0041EE74    51              PUSH ECX
  */         
                bp $RESULT
  
  findkebase2tzm2:
  
                 mov eip,kebase2
                 find  eip, #C3505351#   //中等强度的特征码,最大强度特征码为“#595B588BC18B4F24519D03C38B5F4489039C58#”
                 cmp   $RESULT,0
                 je exit
                 add  $RESULT,2          //这里同上面,好像这段脚本就没有用,因为只是用了第一个壳段
                 bp $RESULT
                 
                 mov esp,temesp
                 mov eip,00401000 //查找的起始位置
                 mov ptr1,eip
  
  tzm2iatfind:
                 
                 mov temesp,esp
                 find  ptr1, #e9????????#    //这里查找的就是JMP  xxxx
                 je    exit                     
                 mov   ptr,$RESULT   
                 mov   ptr1,ptr
                 mov   eip,ptr
                 mov   refaddr, ptr
                 sti
                 mov ip1, eip
                 mov ip1, [ip1]
                 and ip1, 0ff
                 cmp ip1, e9
                 jnz nextfind
                 sti
                 mov ip1, eip
                 mov ip1, [ip1]
                 and ip1, 0ff
                 cmp ip1, 68
                 jnz nextfind            
                 cmp eip,kebase2
                 ja tzm2iataddrfind
                 cmp eip,kebase1
                 jb tzm2iatfind            
               
  tzm2iataddrfind:
                 esto
                 mov iataddr,ebx     ;//这里就是出现IAT真实地址的寄存器,对于中等加密是EBX,对于最大强度,这里是EAX.
                 gn iataddr
                 cmp   $RESULT,0
                 je tzm2iataddrfind
  
  tzm2iatfix:            
                 sub ebx,refaddr
                 SUB ebx,5
                 mov refaddr,ptr
                 mov [refaddr],#e9#
                 add refaddr,1
                 mov [refaddr],ebx,4
                 mov esp,temesp
  nextfind:
                 add ptr1,6
                 jmp tzm2iatfind
  exit:
                 mov esp,temesp
                 mov eip,oep
                 ret
  
      这个脚本只适用于我自己加的VB程序的壳,但是处理的原理是一样的,好了分析就这么多吧,应该说没有怎么分析IAT具体是怎么加密的,只是找到了一个解密IAT的方法,由于脚本中没有做太多的判断,所以运行脚本的时候需要自己看着脚本跑,当修复完IAT后,就自己把脚本停下来,这个时候由于寄存器的值都被破坏了这样修复的程序是不能运行的,不过我们可以打开加壳的软件跑到OEP后根据没有破坏的寄存器把修复好的寄存器的值全都修改过来,然后 再用UIF修复 LP dump  IR修复就可以了,一定要记住一点哦,dump 以前一定要取消那些断点啊,尤其是F2断点,由于我刚开始没有取消断点,结果DUMP 修复后的程序不能运行,跟踪后发现是F2断点的原因,DUMP后的程序F2断点的 地方变成了CC 也就INT3 。
      好了VP的IAT分析就到这里了,提供一下我练习的加壳后以及脱壳后的软件吧,方便像我一样的菜鸟练习。
      
  
--------------------------------------------------------------------------------
【经验总结】
  1、还是自己动手一遍比看别人的文章百遍都起作用。
  2、一直以为在VM中或者垃圾指令中的关键代码自己跟踪不到,结果用最笨的方法还是找到了!这就说明不管做什么只要去努力去试试总有成功的机会!
  3、建议苦力在下个版本中对于中等强度和最大强度加密中取消那两个特征码,或者F9运行的时候出错那样会增大修复难度,至少现在我感觉,最大速度的加密修复速度却是最慢的!修复的时候F9运行就出错,对于寄存器的使用,是否可以借鉴别的壳改为随机的那样也增加修复难度。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于wuqing1501(笨笨鼠), 转载请注明作者并保持文章的完整, 谢谢!
                                                       2010年07月18日 AM 02:31:16
样品及所有脚本
样品及所有的脚本.rar (1.27 MB, 下载次数: 159)

免费评分

参与人数 2威望 +1 热心值 +2 收起 理由
小糊涂虫 + 1 学习一下.....
wgz001 + 1 + 1 感谢发布原创作品,[吾爱破解]因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| wuqing1501 发表于 2010-7-18 15:08
回复 4# wgz001


    你用 NOOBY的 脱VMP的OD 加上SOD 最新版 加上 DBHELP.DLL 6.11或6.12 加上 最新的脚本插件  就是我用的OD没有必要提供了吧  只是插件是更新的而已
wgz001 发表于 2010-7-18 13:24
回复 1# wuqing1501


    楼主能否提供下OD,我的跑脚本出错   
cmzcn 发表于 2010-7-18 11:00
jllsl2280 发表于 2010-7-18 07:08
沙发  顶了
 楼主| wuqing1501 发表于 2010-7-18 15:22
回复 4# wgz001


    跑脚本是开始出错 还是 修复差不多了 出错啊  这个要自己看下  边调试 边修改脚本吧 这个脚本不是通用的  只适合我加壳的 VB程序  我自己跑脚本也出错的 因为 好多判断我都没有加 所以 有时候就出错了 不过可以手动控制  避免出错  你调试一下 看看 就知道了
人走茶凉。 发表于 2010-7-18 16:21
前排留名。。。支持下。
小糊涂虫 发表于 2010-7-18 16:35
完全不懂脚本。。
Hmily 发表于 2010-7-19 14:10
回复 8# 小糊涂虫


不懂就要学啊,ximo不是写过教程吗.
O_o 发表于 2010-7-19 15:38
只能膜拜。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-2 14:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表