分享

OD学习

 zhuxrgf 2015-12-04

                                        手动脱壳有效手段

 

   不可否认,壳的确是个好东西,很多时候它可以帮你拦截大多数软件分析者的跟踪。

   同样,病毒的作者也有同样的感想。因此,为了避免自己辛苦写出来的病毒程序被安全工程师或者同行跟出来,他们可算是想尽了一切办法完善,加强壳的能力。

   不过话又说回来,你壳再强大,再复杂,再变态,程序总会在某一时刻到达OEP,也就是真正的入口点。因此,只要你有足够的耐心和了解一些基本的注意点,那么跟到OEP还是不难的。

    需要说明的,在我看来判定一个壳难不难脱的标准在于PEID能不能识别。当然,这个标准仅仅是我自己定义的,一般来说这还是符合客观事实。

    PEID能够识别的壳,相对都比较的好脱。一般来说简单的壳可以通过ESP定律,F4定律轻松搞定。难的壳大都需要LoadLibrary定律来辅助。如果实在不会百度下就基本有了思路。

    就杀毒软件公司的病毒样本分析人员而言,他们很少关注PEID无法探测的壳,也没有太大的把握能够把这些壳脱下来。因此,病毒如果加上这些强壳,那么至少会让安全人士郁闷一些。同时他们也不能把你的病毒细细的跟出来。这点很重要,毕竟知识产权对自己而言是至少无上的!!

    很多脱壳的朋友经常会遇到这样一个问题,不停的F8或者F4之后,OD就会显示异常,之后就跳到了NTDLL领空,之后程序就退出了。关于这一点,我并没有深入研究。不过呢,据我的观察:壳作者会故意插入引起异常的代码  比如: mov eax ,0

          mov [eax],888

并且在上面代码前插入SEH异常处理函数。很明显,这是故意添加的,其目的就是故意产生异常,按道理讲,这个异常的出现会导致异常处理函数的调用。如果你使用OD调试的话,此类异常会首先被OD捕获。当然,你可以忽略异常,但是问题来了,如果壳的作者在异常处理函数里添加些有用的代码(比如解压代码),那么的话你OD即使忽略了异常也再也跟不下去了。这关键的关键就是千万别忽略异常,当作为调试器的OD无法处理的异常,系统会继续交给程序来处理。正如我们所知道的,壳的作者已经定义好了异常处理函数。所以,按道理讲,你完全可以F8或者F7跟下去。但是这样做太乱了,太令人心碎了。这也就是为什么很多菜鸟只能放弃这些壳了。

    因此有人想出了LoadLibrary定律。为什么会有这个定律呢?

    作为壳而言,它肯定会做的事情就是要具有还原节区的功能。那么肯定就必须调用API函数,这些函数必须动态获得,因此LoadLibrary函数肯定就会被调用。对于壳而言,故意添加异常的代码大都出现的刚开始的地方,获得相关API之后才会开始还原节区的动作。还原好了之后才会跳到OEP。一旦程序运行到LoadLibrary,那么至少可以保证跳过了最开始的令人心碎的部分。

    现在重点开始研究LoadLibrary定律该如何的使用。首先,我们必须知道,LoadLibrary函数可以直接被调用也会被间接调用。而在壳代码中,它肯定会被直接调用!!说白了,你下完此函数断点后按F9的时候务必关注堆栈窗口的函数返回地址!!并且在第一次调试的时候还要数清楚你按了几次F9后,堆栈窗口的返回地址不再是程序领空内部地址了(在系统领空)。为什么呢?正如我上面所说,壳的代码会直接调用LoadLibrary函数,因此返回地址肯定还是壳的领空(也就是程序领空)。如果说在某个时刻按F9,堆栈中的返回地址变成了系统领空,至少可以判定这次的LoadLibrary调用肯定和壳的正常行为无关,或许这个时候已经走过了OEP了。所以以上我所说的只有一个目的:准确定位到“万事俱备”这一时刻,接下来就开始等着开始还原节区了。

    当壳获得了自己所需要的API之后,那么它就可以做还原节区的工作了。你可以按F8走。但是中途有些地方必须要注意。特别是遇到像这样的指令:

            Call  eax       (此时eax指向一个系统领空地址)

如果说你不注意,死命的按F8的话,那么你就不知不觉进入了系统领空,像这样的情况,能走出来还算好的,走不出来就郁闷死你。这也就是为什么很多人放弃继续跟的另外一个原因。因此你遇到这些变态壳的时候,一步一步的走,如果遇到诸如上面的指令,那么按F7进去,之后再把堆栈中的返回地址记录下来并在反汇编窗口中下断。这样直接按F9就跳出来了。这样就避免了你在系统领空跳来跳去影响心情。

    当然啦,这些壳还有个比较显著的特征就是CALL语句跳转的地方就在附近,因此在壳中遇到CALL语句千万记得养成先按“回车键”的习惯,如果是近跳(程序嵌套现象)经务必F7。如果你F8了,那么后果是严重的。如果是普通的跳,那么F8就行。总之一切要小心。

    在壳中,Loopd指令也会经常的出现,记得必要的时候下条件断点 “ecx==1”,这样避免你按的手指发酸。

 *************************

    另外补充下,壳还有一个重要的特征:当它要还原节区的时候,首先必须先要修改内存属性,毕竟还原节区这个举动是要操作内存的,从而必须要修改相应内存属性为可写,可读。因此,我们可以在virtualprotect函数上下断点。上面我们已经说过,壳的作者会故意插入异常,进而执行异常处理函数内的实用代码,不排除人家会在调用LoadLibrary后面继续插入这样令人恶心的东西。因此下断virtualprotect可以更加多的越过异常。

    当然,下断VirtualFree也是很好的方式,因为壳在还原节区的时候总是会申请一段内存作为交换区域。还原操作完成之后,就会用这个函数释放所申请的区域。因此在这个函数下断更加的和谐。

*******************************

    读者可以用 PECompact 2.x壳做实验。这个壳很好的表现出以上几乎所有的特征。并且有些版本还会稍微加上一些反调试的功能,比如说调用IsDebugerPersent函数。像这样的情况很容易处理,要么NOP掉这个函数调用,要么就修改跳转。关于这个函数,还请读者熟知其代码细节:

              IsDebugerPersent()

               {

                 _asm

                  {

                     mov     eax, dword ptr fs:[18]

                     mov     eax, dword ptr [eax+30]
                     movzx   eax, byte ptr [eax+2]
                     retn

                  }

               }

    如果读者非得细细跟带有“故意插入异常的壳”的话,你会很容易发现注册异常处理函数的代码,之后找到异常处理函数的入口点。下断吧!  之后慢慢跟下去。

    

    其实网上有很多脱壳的教程,有图有步骤,但是本着知其然知其所以然的精神,笔者还是决定写出这篇文章让读者知道为什么要下这些断点,为什么要有那些操作。当然,笔者在这方面也是菜鸟,有些地方出现错误或者说理解有问题也是难免,还请高手们赐教。谢谢~~~

 

***********************

反调试:

1,rdtsc指令。

2,

     

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多