脱壳经验谈

admin 2021年4月25日08:45:48评论46 views字数 4892阅读16分18秒阅读模式

破解时间也不长了,也学了一些脱壳的技术,过程中感触颇深。这里给大家分享一下,也算是给脱壳新手的一个指导。
  

  菜鸟心得,高手飘过~ 当然你要看,我也不反对~~
  
  关于工具
   
  关于OD
  所谓工欲善其事,必先利其器。要想学习脱壳的话,有几种不同的OD是很重要。因为有时在调试一些强壳的时候,有些改造过的OD可以躲过壳的深层检查,再配合一些OD插件就可以完全让壳检测不到调试器的存在了。这里推荐几款比较好的OD:
  1,fly改造的OD。可以调试大多数壳,但是由于不能使用phanom 1.3版的插件,导致在调试某些强壳(如Aspr 2.x)的时候会被检测到。
  2,ImmunityDebugger.这款OD可以比较顺利的调试Aspr等其他强壳。国内也有了汉化版。只是界面背景是黑色的,我实在不习惯这种界面,喜欢的人可以试试。
  关于其他的工具
  1,LordPE。推荐大家在Dump程序的时候使用这个工具。或许大家在脱简单的压缩壳时习惯使用OD的脱壳插件来抓取内存镜像,但是如果大家有调试穿山甲等强壳的经验就会知道,如果用OD插件抓取内存镜像就会出现OD被卡死的状态,这或许是OD插件的Bug,也可能是壳的反Dump方式,反正会影响到我们正常的脱壳。所以这里推荐使用LordPE来抓取镜像文件。而且在需要补区段的时候,用LordPE可以很方便的进行区域抓取。此外,作为一款PE编辑器,LordPE也是很优秀的。相比之下,PEtools就有点儿差了,对于PE文件有些操作会导致文件损坏,不知道为什么。大家还是用LordPE吧。
  2,ImportReconstruction。这是一款专业级的输入表重建工具。由于它支持插件扩展,可以大大提高对于加密壳的脱壳成功率。但是请大家不要过于依赖这款软件,学会手动修复输入表是很必要的。在ImportREC不能修复的时候,我们只能靠手动修复。手动修复一方面可以练习调试技术,另一方面可以让我们更加深入的去了解PE文件的工作方式。
  
  关于脱壳方法
  相信大家都像我一样看过一些脱文,在里面告诉我们下这个API断点,然后走多少步,再怎么样怎么样就可以到OEP了。反正具体为什么这么操作,作者都只字不提。当我看到这些脱文的时候,基本上是一头雾水。加上我这个人比较倔强,对于我不懂的方法是不会接受的,所以那段时间,脱壳的水平基本上止步不前。实践是最好的老师,自己亲手调试了些壳以后就明白为什么了。当时我有个这样的顾虑,就是“我真的能调试这些壳,那可是前辈们干的事儿啊”,但是真正调试后才发现其实并没有那么难的。当我第一次手脱了一个Aspr 1.23RC1的时候,真的好兴奋,那种感觉就像一个初出茅庐的小贼利用自己学过的书本上的技能到**局偷出了一根**局长的头发,虽然没有值得炫耀的,但是对于自信心却是很大的鼓励。所以加密壳没有好怕的,你只要想办法躲过壳的所有检验,然后乖乖的走到OEP就可以了!至于如何躲过这些检验,那就要你在调试中不断积累经验,以及借助别人的经验了。
  所谓授之以鱼,不如授之以渔。学习脱壳还是理解方法,才能真正学会。
  所以我对于那些脱文的态度是这样的:
  1,对于所谓的方法先置之不理,自己手动调试一遍,了解壳的流程(一般来说,当你调试到OEP的时候,这个壳你应该调试了10遍以上了)。
  2,当遇到实在过不去的检验的时候再看脱文,了解它是怎么过去的。这样印象深刻一些。并在下次遇到这样状况的时候能自己解决。
  3,当自己完全脱掉这个壳后,再看下脱文,这个时候你应该就可以明白为什么下那些API断点了。下次就可以不用这样手脱了,照着脱文给的快捷方法脱壳就可以了。这个时候对于出现和脱文上不同的情况,我想你应该也会处理了。
  再说说如何调试壳呢。
  1,首先要选择并配置好OD,尤其对于强壳一定要这么做。配置OD包括异常设置,删除int3断点(因为有些壳会检测Int3断点的),OD的标题隐藏等。当这些都设置好,要在OD中运行一次,确保你要脱壳的程序能在当前的OD中顺利的运行(对于有些带驱动的壳可以不这么做,因为必须在没有驱动的条件下才能调试。),这样可以在调试时省去不少躲避调试器检查的时间。(当然有些壳还是要在调试中躲避检查的。)
  2,个人认为,基本的调试方法有:单步法,最后一次异常法。这两种方法在逻辑上都是比较好理解的。在调试的过程中要配合内存断点,硬件断点,Int3断点以及F4来简化调试过程。如可以用F4来跳出循环;硬件断点可以用来记录调试进度,当程序不小心跑飞的时候,可以在相应的位置下硬件执行断点,重新来过后就可以直接到达跑飞的位置了;灵活运用内存断点可以使得调试变得很容易,也是提高调试技巧的一种方法。
  当你可以熟练的运用这些方法的时候,任何的壳都可以搞定了,任何一个加壳的程序就像躺在床上的**,等着你脱了~ ^-^


  关于OEP的到达
  我们脱壳的目的就是为了到达OEP,但是如果判断是不是到达了OEP了呢?前辈们告诉我们一个方法,注意跨段跳转或转移。这确实是唯一判断标准。但是很多的教程中都把这句话误解为了:“注意大的跳转”,使得很多新手都被搞的云里雾里的,看到大跳转就兴奋。
  首先澄清一个误解,什么叫做“跨段转移或跳转”?这里面所谓的段指的是一个区段,是指被分割成一段段的内存。跨段跳转顾名思义,是指EIP指针从一个区段跳到了另一个区段。而不是所谓的大的跳转。如果EIP所在的区段很大,段内跳转也可以很大,这里所谓大的跳转本身就是一个很模糊的概念。
  其次,并不是出现跨段跳跃就是要到OEP了。一般加密壳在解码的时候会在内存中申请空间,并在那里实行解码。一般来说是壳会申请很多段这样的空间,然后在解码的时候从这个段跳到那个段。这些段就是我们在调试的时候在目标程序区段后面的那些没有名字的区段部分。所以说在这些段里面的跳跃一般不会到OEP的。
  再次,那么你会说了,那到底怎么判断呢?大多数壳把程序解码后会跳到目标程序的code段的进行执行。那么方法就出现了,在调试的时候可以先看下code段的地址范围,如果在调试过程中出现了跳跃到这个地址范围内存的跳转或转移的话,那么十有**就是要去OEP了!
  此外,对于OEP的判断可以通过不同语言编译的程序入口点特征来判断,当然这完全就是经验的问题,需要大家不断的积累。就像天草说的,记住入口特征这句话我都说了八百遍了。
  不过,这里有个小技巧,就是通过查看资源类型来大致判断。因为壳很少资源列表进行处理,所以如果查看资源,发现存在RCData的话,就可以认为程序应该Delphi或者BC++的;如果资源中有对话框,菜单等资源,而且资源名称都比较规则的话(这主要是为了区分VB以及E语言),就可以判断是MS VC++的了;如果在程序安装目录中发现*.fnr等类型的文件话,基本可以认定是E语言的了(现在E语言的程序越来越多了);如果在程序的末尾发现附加数据的很多的话(一般要大小的数量级在KB以上),那应该也是E语言的(这个时候大家应该明白为什么E语言程序查壳的时候为什么显示的时候Microsoft VC++[OVERLAY]了吧)。


  关于学习方法
  这应该是老生常谈了。学习方法因人而异,没有必要强调某种方法,方法的目的只有一个,就是掌握你学到的东西东西并与以前的知识融汇贯通。论语中的那句话“温故而知新”,确实很有道理。当你学到一些东西后,回过头来看以前学的东西,你会发很多新的东西,可以加深对某些知识点的理解。这点是没有任何方法可以替代的。这里推荐两种方法:
  1,录像。把你的脱壳学习过程录像,当你忘记的时候,回忆起来也会很快的。
  2,做好笔记。OD有个很好的插件Godup可以在调试的过程中做好记录。从某种程度上讲,记录是你调试过这个壳唯一证据。
  
  关于到OEP的一些特征代码
  现在的壳变聪明了,很少再使用Jump **X这样的方式来到OEP了。下面介绍几种流行的方法。
   1,push 寄存器或者地址
      retn 
   这种方法是利用retn来实现远跳转的,原理同call子程序的后返回的
原理一样,即通过push一个值到堆栈顶,然后用retn指令即可返回到堆栈顶指向的地址。
   2,mov dword ptr[**],**X  
      jnz  **XX
      retn
      push 0  这个地址是上面的mov指令动态填写的
      retn   
     这样的条转在ASPac和ASprotect中使用过。
   3,mov 寄存器,**X
      call 寄存器
    这个在穿山甲的壳中可以看到。
   4,还有使用Leave指令进行跳转的,大家也可以注意下。
   5,使用SEH。后面会提到。


   关于SEH
   SEH,Structure Exceptions Handle,结构化异常处理,是加密壳程序经常使用的桥段。主要用这种方法来实现非正常跳转(可能还有其他作用,我现在只理解到这里)。对于SEH的具体技术细节我也搞不明白,也不用管它,OD给了我们一个很好用的功能,就是在堆栈会显示SE句柄。这是什么意思呢?你只要知道当出现异常后,系统处理完异常就会跳到这里来继续执行。 那么我们可以通过在这个地方下好断点,然后Shift+F9,就可以继续调试了!
  
   关于自校检
   现在带有脱壳自检验的程序还是很多的。自校验类型大致分为以下几个类型。
   1,CreateFile型。这种自检验一般都会调用CreatFileA(W)函数来对于自身。然后
   通过GetFileSize获取文件大小,因为一般脱壳后文件大小会变,通过比较文件的大小来检测是否被脱壳。
   通过SetFilePointer来设置文件指针,然后通过ReadFile读取文件中的一些数据,来判断是否被脱壳(一般来说读取的时候附加数据)
   2,内存型。这种自检一般是对程序在内存中镜像进行CRC,MD5等检验,如果不相等则认为已脱壳或被修改。
   3,脚本语言型。脚本编程语言指的是像autoit,autohotkey等语言。这种语言编译出来的程序一般都是天生带壳的,而且自校验是对附加数据进行多次细致的检查,如果不弄清楚检验过程,即使更改跳转也不能让程序正常运行。有机会大家可以试试。
   4,壳校检型。这种校验是在主程序中插入一些跳到壳地址中的代码,并返回一些无关紧要的数据或做无关紧要的操作。如果程序被脱壳了,这些代码执行的时候就会出现异常。
   还有一些其他类型,但是现在还有总结出比较好的说法,以后再补充。 
   相应的处理方法。
   1,直接对API下断,基本就可以到达解密点。
   2,用PEID插件可以查看算法的所在位置,就可以到达解密点了。
   3,没有别的方法,运用API断点耐心调试吧
   4,在OD运行程序,出现异常后,在堆栈中找到返回的位置,nop掉相应的指令即可。
   
   关于脱壳脚本
   脚本应该是前辈没有留给我们最好的财富了,有了这些东西,我们可以在不了解任何脱壳细节的情况下脱掉壳。但是如果想学脱壳技术的话,那么请把它当作你的老师。因为脚本中包含着你遇到问题的所有答案~ 而且当你了解了以后,还可以自己改进脚本的功能。借用达朗贝尔的一句话:多读读高斯,他是我们每个人的老师~ 
   
   关于花指令
   可能有些新手看到壳那些乱七八糟的指令会发怵的,这些都是壳为了阻止调试者所设的花指令,或许你不知道这些指令怎么执行,但是壳是是知道的,它不可能去执行一坨不能执行的指令的,有些指令是动态解码的,有些是花指令。你在调试的时候只要看着当前指令F8(7)就可以了,不用管别的。再借用达朗贝尔的一句话(怎么又是他?):前进吧,你会有信心的!
    
   关于心态
   调试壳是需要很大耐心的,就像破解一样! 所以如果你已经下好决心的话,那么请同时做好心里准备!
   
   最后送大家一句话,关键是要对技术有爱~ 只有真正对这个东西感兴趣,你才能真正学到东西!
   

本文始发于微信公众号(飓风网络安全):脱壳经验谈

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年4月25日08:45:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   脱壳经验谈https://cn-sec.com/archives/359425.html

发表评论

匿名网友 填写信息