浅析乱序代码的分析方法
浅析乱序代码的分析方法浅析乱序代码的分析方法关键字:乱序 分析 反汇编 InsideView
本文涉及的InsideView和相关文件下载:
http://devdiy.org.ru/blog/template/neowin2/images/download.gif下载文件
点击这里下载文件
代码乱序的实现方式:
代码乱序是将一系列的代码序列分散打乱分布在PE映像中,中间穿插跳转指令以及不改变环境的垃圾代码,从而扰乱正常分析流程。一般的来讲,连接指令以无条件的跳转jmp、变形的短跳转call、对称的条件跳转指令(;…)等实现,前提是不改变其他环境以免破坏代码正常功能。当然,也可以先保存环境,再使用破坏环境的条件跳转或通过SEH跳转等方式,然后再恢复先前保存的环境,这种先保存再恢复的实现方式必然有成对的指令模版。归根结底,连接指令是不会改变其他环境的。
代码乱序的还原方法:
我们知道连接指令是不改变其他环境的,因此我们可以逐行分析代码,记录不改变环境的跳转,将分散乱序代码合并实现乱序的还原。代码乱序的还原方法可分为动态和静态两种,动态还原以OllyDbg为例,可利用调试器自身的反汇编引擎和脚本来实现,由于脚本和跟踪执行的效率问题,这种方式存在一定的局限性,比如动态分析时不方便比对。而静态还原首先需要一个反汇编引擎来分析指令,然后根据设定的过滤条件,将不会改变其他环境的连接跳转过滤,根据指令执行顺序,线性重排,这种方式实际上是半自动的条件反汇编。
乱序分析实例:
下面以本人测试某反汇编引擎的中间产物InsideView为例,实现代码乱序的分析还原。在InsideView中打开example.cv.exe,程序会从入口处显示默认反汇编结果,如图:
http://devdiy.org.ru/img/exp1.png
例子很简单,就是现实2次消息框,从InsideView可以看到,从00409149处起至000040916F止,相关代码被jmp、jne、je等乱序了,不利于分析。可以看到乱序代码中包含了无条件跳转jmp、成对的条件跳转(jne/je…)、伪装的call,这里勾选右边选项的所有过滤条件,由于指令不多,反汇编行数可以适当减少,比如填入20,避免无关代码干扰,单击Process过滤反汇编结果,可以看到过滤后的代码一目了然了:
http://devdiy.org.ru/img/exp2.png
对比一下(过滤前):
00409149jmp 00409159h
0040914Bpush 00h
0040914Djne 0040915Fh
0040914Fje 0040915Fh
00409151push dword ptr
00409157jmp 00409169h
00409159push 00h
0040915Bjs 00409151h
0040915Djns 00409151h
0040915Fcall 00405118h
00409164call 00409171h ;maybe fake jmp
00409169push dword ptr
0040916Fjmp 0040914Bh
过滤后:
00409159push 00h
00409151push dword ptr
00409169push dword ptr
0040914Bpush 00h
0040915Fcall 00405118h
可以看到,过滤后的代码地址并不连续,但实际上显示的是真实的执行顺序,在实际应用中完全可以结合OllyDbg的动态调试,根据过滤结果在关键点下断避免被猥琐掉耐心。
单击Restore恢复初始状态,或则手动取消所有过滤器选项,以免影响下次分析,接下来我们来看看CodeVirtualizer的乱序,这个例子中Code Virtualizer虚拟过的函数为00409144call00408600h,我们在此行上双击,进入该call的反汇编结果:
00408600jmp 0041A1B6h
00408605mov esp , E1A83C07h
0040860Amov ecx , 65C31480h
0040860Fpop edx
00408610mov dl , BFh
00408612stosb
可以看到第一行就是一个无条件跳转去VM,双击它,来到:
0041A1B6push 00419D13h
0041A1BBjmp 00414EECh
0041A1C0retf
压入数据,进入VM执行,继续双击0041A1BBjmp 00414EECh,进入真正的处理过程:
http://devdiy.org.ru/img/exp3.png
粗略一看,基本上是jmp和伪装call组合的乱序,勾选右边的过滤器Filter JMP和Filter Fake CALL,代码比较多,Disassemble Lines选100好了,单击Process得到结果:
http://devdiy.org.ru/img/exp4.png
比较一下,一个完整的清晰的VM Handler出现在面前,要进一步分析VM也变简单了。
再来看看NoobyProtect的乱序分析,手里没Key跑不起主程序做不了实验品,只好用NoobyProtect v1.6.7.0个人版带的SEKeygen.exe来测试了。打开之后如图:
http://devdiy.org.ru/img/exp5.png
乍一看,完全看不懂,代码极度猥琐,没关系,一步一步来,双击进入第一行的伪装call,来到:
00776DE6jne 00776D9Ch
00776DE8jmp 00776D9Ch
00776DEAstd
可以看出,这里是乱序连接指令,继续双击跳转到:
00776D9Clea esp , dword ptr
00776DA0jl 00776D5Eh
00776DA2jnl 00776D5Eh
00776DA4into
00776DA5retf
00776DA6mov dword ptr , edi
00776DA9jne 00776E23h
00776DABje 00776E23h
有成对条件跳转出现,勾选右边的Filter Junk Jump后Process过滤:
http://devdiy.org.ru/img/exp6.png
现在的代码要明朗的多了,可以看到程序进行了大量的堆栈操作,具体干啥了请自行结合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更完善的动态调试功能。
期待大牛的诞生……
Vince Hsu
2-Nov-2009
「原创文章,转载请保持完整」 這個工具已經不錯了 管理员果然强大
页:
[1]