自修改代码浅析

来源:互联网 发布:商品分类数据库设计 编辑:程序博客网 时间:2024/05/01 05:47

  自修改代码浅析 收藏
相信大家都在程序调试或者分析中碰到过自修改代码的情况吧。所谓自修改代码,就是程序自我保护的一种机制。它使我们的反汇编调试器看起来相当地无助。因为我们看到的所谓的反汇编代码并非执行过程中的代码,它表面上看起来不合逻辑甚至一塌糊涂,但是运行起来却井井有条。因此,这项技术被广泛用在那些反破解的商业软件中,在试图bypass杀毒软件的黑客 软件中也颇有涉及。在另一方面,cracker初学者们对这类程序大伤脑筋,他们一边诅咒反汇编调试器一边对着一大堆非法指令符莫名其妙。他们必须不停地设置断点,慢慢地让程序在运行过程中将真正的代码暴露出来。

没错,这就是很多壳的基本运行原理。然而我并不打算在这里教大家怎么脱壳,大部分程序员都已经为我们做好了现成的脱壳程序,剩下的都是一些繁杂的充斥着各种 SEH等保护机制的超级壳,也许强大到作者也没有办法写出脱壳脚本。我写这篇文章的目的就是对代码自修改技术做一点点分析而已。

为了更好地诠释代码自修改,我引用下面段代码。

FE 0D   xxxxxx            DEC byte ptr DS:[The_fake_jmp]        ;将装有The_fake_jmp入口地址的DS进行修改,即将The_fake_jmp的第一个字节内容减一。

......                          ;其他的代码

B8 01 000000          MOV eax,1

The_fake_jmp:

75 xx                          JNZ another_place                                 ;eax非零则跳转

......

如果没有看到前面的代码,也许很多程序员会想当然地认为一定会跳转到another_place,其实程序运行时已经将the_fake_jmp改成了74 xx,即改成了jz。这样程序运行的结果将与程序员所预料的完全相反。

通过这个例子大家也许会发现,存在自修改代码的程序调试起来确实要小心.难道我们必须要一步一步单步调试才能发现隐藏的陷阱吗?当然不是.前面已经提到了,不吝惜自己的断点可以很方便地识破这些小小的破绽。

下面我将通过调试著名木马Bifrost 1.2.1的脱壳服务端(该木马可以在chasenet.org下载到)来观察它的一些自修改代码片断。

传说中Bifrost的原始服务端是加壳的。有人已经做出了所谓的脱壳版本。实际上,我发现两者的区别不是很大。oep都没有经过修改。这里选用的调试器是网络上比较流行的应用层调试器Ollydbg。

载入服务端后我们可以看到OD的提示。说明该服务端存在大量自修改程序。我们随便就能找到一些调试器无法识别的指令。这里我选用00406111处.这里的代码如下:(这些代码也许在其他版本的服务端上是不同的)

00406111    F4              hlt
00406112    A4              movs    byte ptr es:[edi], byte ptr [esi>
00406113    64:9A 325427F8 >call    far D779:F8275432
0040611B    9B              wait
0040611C    F1              int1
0040611D    65:338D 355EF3B>xor     ecx, dword ptr gs:[ebp+BFF35E35]
00406124    DEBF D977A7B3   fidivr  word ptr [edi+B3A777D9]
0040612A    A8 62           test    al, 62
0040612C    9B              wait
0040612D    002A            add     byte ptr [edx], ch

不仅仅是这些代码,它的一大段上下文都让人莫名其妙。到这里我们假定它是自修改代码的一部分。我们在00406111点右键-断点-内存写入,然后F9运行,我们会到达尝试对这段代码进行修改的程序段。仔细看看,呵呵,不错,我们似乎到达了对代码进行修改的函数里。其附近代码如下,我在这里对它们加了一点简短的注释。

004073C0    55                  push    ebp
004073C1    8BEC            mov     ebp, esp
004073C3    56                  push    esi
004073C4    33F6              xor     esi, esi                                        ;清空esi
004073C6    3975 0C        cmp     dword ptr [ebp+C], esi          ;esi在这里做计数器
004073C9    7E 1B             jle     short 004073E6                        ;若解密完毕则跳转
004073CB    8B45 08        mov     eax, dword ptr [ebp+8]
004073CE    33D2              xor     edx, edx
004073D0    8D0C06         lea     ecx, dword ptr [esi+eax]         ;解密段指针
004073D3    8BC6              mov     eax, esi
004073D5    F775 14         div     dword ptr [ebp+14]
004073D8    8B45 10         mov     eax, dword ptr [ebp+10]
004073DB    8A0402          mov     al, byte ptr [edx+eax]             ;我们的密钥
004073DE    3001               xor     byte ptr [ecx],

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhengtingt108/archive/2009/09/15/4555277.aspx

原创粉丝点击