浅析乱序代码的分析方法

Eddy 发布于2009-11-4 13:31:46 分类: 加密解密 已浏览loading 网友评论0条 我要评论

代码乱序的实现方式:
    代码乱序是将一系列的代码序列分散打乱分布在PE映像中,中间穿插跳转指令以及不改变环境的垃圾代码,从而扰乱正常分析流程。一般的来讲,连接指令以无条件的跳转jmp、变形的短跳转call、对称的条件跳转指令([jz、jnz];[jc、jnc]…)等实现,前提是不改变其他环境以免破坏代码正常功能。当然,也可以先保存环境,再使用破坏环境的条件跳转或通过SEH跳转等方式,然后再恢复先前保存的环境,这种先保存再恢复的实现方式必然有成对的指令模版。归根结底,连接指令是不会改变其他环境的。

代码乱序的还原方法:

    我们知道连接指令是不改变其他环境的,因此我们可以逐行分析代码,记录不改变环境的跳转,将分散乱序代码合并实现乱序的还原。代码乱序的还原方法可分为动态和静态两种,动态还原以OllyDbg为例,可利用调试器自身的反汇编引擎和脚本来实现,由于脚本和跟踪执行的效率问题,这种方式存在一定的局限性,比如动态分析时不方便比对。而静态还原首先需要一个反汇编引擎来分析指令,然后根据设定的过滤条件,将不会改变其他环境的连接跳转过滤,根据指令执行顺序,线性重排,这种方式实际上是半自动的条件反汇编。

乱序分析实例:
    下面以本人测试某反汇编引擎的中间产物InsideView为例,实现代码乱序的分析还原。在InsideView中打开example.cv.exe,程序会从入口处显示默认反汇编结果,如图:


    例子很简单,就是现实2次消息框,从InsideView可以看到,从00409149处起至000040916F止,相关代码被jmp、jne、je等乱序了,不利于分析。可以看到乱序代码中包含了无条件跳转jmp、成对的条件跳转(jne/je…)、伪装的call,这里勾选右边选项的所有过滤条件,由于指令不多,反汇编行数可以适当减少,比如填入20,避免无关代码干扰,单击Process过滤反汇编结果,可以看到过滤后的代码一目了然了:
  
对比一下(过滤前):
00409149  jmp 00409159h
0040914B  push 00h
0040914D  jne 0040915Fh
0040914F  je 0040915Fh
00409151  push dword ptr [0040A988h]
00409157  jmp 00409169h
00409159  push 00h
0040915B  js 00409151h
0040915D  jns 00409151h
0040915F  call 00405118h
00409164  call 00409171h ;maybe fake jmp
00409169  push dword ptr [0040A984h]
0040916F  jmp 0040914Bh
过滤后:
00409159  push 00h
00409151  push dword ptr [0040A988h]
00409169  push dword ptr [0040A984h]
0040914B  push 00h
0040915F  call 00405118h
可以看到,过滤后的代码地址并不连续,但实际上显示的是真实的执行顺序,在实际应用中完全可以结合OllyDbg的动态调试,根据过滤结果在关键点下断避免被猥琐掉耐心。
    单击Restore恢复初始状态,或则手动取消所有过滤器选项,以免影响下次分析,接下来我们来看看CodeVirtualizer的乱序,这个例子中Code Virtualizer虚拟过的函数为00409144  call00408600h,我们在此行上双击,进入该call的反汇编结果:
00408600  jmp 0041A1B6h
00408605  mov esp , E1A83C07h
0040860A  mov ecx , 65C31480h
0040860F  pop edx
00408610  mov dl , BFh
00408612  stosb
可以看到第一行就是一个无条件跳转去VM,双击它,来到:
0041A1B6  push 00419D13h
0041A1BB  jmp 00414EECh
0041A1C0  retf
压入数据,进入VM执行,继续双击0041A1BB  jmp 00414EECh,进入真正的处理过程:
  
粗略一看,基本上是jmp和伪装call组合的乱序,勾选右边的过滤器Filter JMP和Filter Fake CALL,代码比较多,Disassemble Lines选100好了,单击Process得到结果:
  
比较一下,一个完整的清晰的VM Handler出现在面前,要进一步分析VM也变简单了。

再来看看NoobyProtect的乱序分析,手里没Key跑不起主程序做不了实验品,只好用NoobyProtect v1.6.7.0个人版带的SEKeygen.exe来测试了。打开之后如图:
  
乍一看,完全看不懂,代码极度猥琐,没关系,一步一步来,双击进入第一行的伪装call,来到:
00776DE6  jne 00776D9Ch
00776DE8  jmp 00776D9Ch
00776DEA  std
可以看出,这里是乱序连接指令,继续双击跳转到:
00776D9C  lea esp , dword ptr [esp+04h]
00776DA0  jl 00776D5Eh
00776DA2  jnl 00776D5Eh
00776DA4  into
00776DA5  retf
00776DA6  mov dword ptr [esp] , edi
00776DA9  jne 00776E23h
00776DAB  je 00776E23h
有成对条件跳转出现,勾选右边的Filter Junk Jump后Process过滤:
  
现在的代码要明朗的多了,可以看到程序进行了大量的堆栈操作,具体干啥了请自行结合OllyDbg分析。
    补充说明一下InsideView的各项功能:
Code View内显示代码反编译结果,凡是跳转指令,可以双击或回车进入该跳转,Code View内有右键弹出菜单,
1.Disassemble from here,从选中行开始反汇编;
2.Save Result,保存反汇编结果到文本文件;
3. Copy selected lines,复制选中的内容到剪贴板。
Filter选项中Filter JMP对应过滤无条件跳转jmp,
Filter Junk Jump对应过滤对称条件跳转,
Filter Fake CALL对应过滤伪装的Call跳转,
Disassemble Lines为需要反编译的代码行数。
History中显示用户反编译的历史,双击可以回到指定地址的反汇编结果,也可以使用“-”“+”回溯或向前,与OD操作类似。
Virtual Address to disassemble可填入需要反汇编的虚拟地址,对指定地址反汇编。
Process按钮进行反汇编,
Restore按钮恢复初始化,
Save Result按钮保存反汇编结果。
    InsideView只是研究反汇编引擎的一个中间产品,功能上仍有欠缺,代码写得很乱很糟糕,就不开源献丑了。实现原理只是对反汇编代码进行分析,根据给定的条件,逐步跟随跳转指令的操作地址进行线性过滤,过滤条件的设定值目前是硬编码,不保证百分之百正确,有可能会过滤真实的代码,需要人工干预给与正确的条件组合。原理并不复杂,欢迎山寨类似分析工具,但你不能拿InsideView改个名换个外观说是你的成果。
    本文只是实现了基本的代码乱序还原方法,对代码变形和VM没有讨论,实际上,代码的变形和VM都脱离不了x86的指令集的本质,x86计算机上运行的程序无论如何变化,最终执行的依然是x86指令,如果可以动态匹配指令变形模版,则可以进一步过滤以实现变形和VM的还原分析。
    从前,为了体现技术的强大,程序员往往花费很多精力去优化精简代码,试图以最小的代码量实现最好的功能,现在,为了保护强大的技术,程序员不必再去优化代码,代码写得越臃肿越好,越乱越不容易被破解,目前软件保护工具的乱序、变形、VM等,说穿了就是一个化简为繁的过程,很显然Cracker们需要的是一个化繁为简的利器,需要一个强大的能过滤各类条件、能匹配指令模版的条件反汇编工具,而且最好还拥有比OllyDbg更完善的动态调试功能。
    期待大牛的诞生……
本文涉及的InsideView和相关文件下载:
下载文件
点击这里下载文件
Vince Hsu
2-Nov-2009

已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/decryption/63.html     欢迎订阅Eddy Blog

关于 乱序  分析  反汇编  InsideView  的相关文章

记住我的信息,下次不用再输入 欢迎给Eddy Blog留言