(转载请注目博客地址:http://blog.csdn.net/hitetoshi)
写这一系列文章的目的有两个:一是告诉大家绝影还在。二是尝试向大家介绍一种新的技术,我把他叫做“动态感染”,也许这样命名不规范,但我至今仍未找到对这一技术的比较科学合理的命名方式。所以姑且把它叫做“动态感染”吧。
所谓的“感染”大家应该比较熟悉,它的原理是在一个PE文件中新添加一个节(或者从已有的节中寻找一块足够大的可用空间),将感染代码写入,再修改原PE文件的EntryPoint的代码,改为Jmp XXXXXXXX(XXXXXXXX为感染代码的起始位置),当感染代码执行完毕后,再使用一条Jmp OldEntryPoint代码跳回PE程序的原入口点。这样当PE文件运行时就会先执行我们写入的感染代码。对PE文件的分析和更改技术都比较成熟,唯一的难点是所有感染代码都要使用自定位代码,或者修改PE文件的导入表等,加入对感染代码所使用的DLL函数的支持。这一感染过程是静态的,必须在PE文件没有运行的情况下进行;同时这一方法也是很不妥的,毕竟修改了原始的PE文件,恢复起来相当困难,几乎对其进行了不可逆的破坏。
以下要讲的“动态感染”,都是在内核态下,所以我们要做的,也就是一个内核模块(有些人叫做“驱动”,但我觉得这样并不严格)。当一个PE文件开始执行时,内核中先要进行很多工作:分配内存、创建线程、加载导入表中的DLL等,这里就不详细阐述了。我们想要做的,是在执行到EntryPoint之前,用ZwAllocateVirtualMemory向目标进程中分配内存,写入感染代码,将原始的EntryPoint修改为感染代码的起始,然后我们的感染代码执行一系列操作,最后Jmp OldEntryPoint,将控制权交回原来的代码。整个过程不修改原始PE文件,可随时卸载我们的内核模块。
这一技术的意义在于我们要动态地保护指定的应用程序不被其他DLL入侵(防止木马等)。我们知道DLL入侵是比较普遍的入侵方式,可以用钩子,也可以用远程线程。钩子的方法相信大家都比较熟悉,远程线程的方法除了可以用LoadLibrary作为线程函数加载一个入侵DLL,还有一种改进的办法,就是直接用纯自定位代码注入目标进程。这类方法在没有杀毒软件的情况防范还是有一定的困难,况且现在很多病毒还能关闭杀毒软件,或者欺骗杀毒软件。如果我们在目标进程已经运行起来的情况下再来保护,可能已经来不及了,有些DLL的注入是非常快的。而我们现在要讨论的技术,是在整个进程还没有完全启动的情况下(尚没有一个线程被创建)来进行,我们的代码进入目标进程的时间相当早,有足够的时间来完成防护准备。如果你使用OllyDbg来调试我们的被保护程序,你会发现,当OD中断在程序的入口点时,我们的代码已经完成了运行。
这系列文章我会分为几个部分来写:使用汇编语言编写内核态程序;获取内核基址、SSDT基址;Hook SSDT监视进程创建;在进程的第一个线程执行前向目标进程分配内存并注入代码;编写自定位的感染代码(代码简单,因为你如果已经学到这里了,你自己就可以写复杂的代码,也可以使用LoadLibrary载入DLL来实现复杂的功能)。
为什么要用汇编语言来写内核态程序呢?一是因为我已经习惯了;二是SSDT钩子函数的简便;三是由于要写自定位的代码,对高级语言来说还是相当困难(至少我还没找到简单有效的方法,例如要计算注入的代码的长度,除非你事先反汇编);四是你顺便可以学习用汇编语言来编写程序。当你学完了这个系列的文章,你会发现,在我们写的这个小程序中,大部分是内核态下的代码,同时又有用户态下的代码(注入到目标进程中的感染代码),这是个非常有意思的小东西。
要学习这系列的文章,你首先要准备以下工具:
一、Mirosfot Visual Studio 2003(用这个只是编辑器,也可以用更高或更低版本的Visual Studio,但某些汇编、连接的设置可能会有变化;如果你会用makefile而且你是编程牛人直接用记事本编写代码那就忽略)。
二、MASM32V10开发包(其实V9,V8是一样的)。
三、KmdKit(汇编语言用的驱动程序开发包)。
四、KmdManager.exe(加载并测试我们编写的内核程序,在KmdKit中有)。
五、OllyDbg(可以测试或者观察我们的代码)。
六、VMWare之类的虚拟机(可选,测试用,免得你的机器频繁蓝屏,当然,如果你对内核开发很有信心可忽略)。
你需要掌握的技术知识有以下几点:
一、汇编语言基础知识(如果你会使用MASM32开发包,已经用汇编语言写过小应用程序那就OK,否则你还是去看下《Windows环境下汇编语言程序设计吧)。
二、用汇编语言编写内核程序的基础知识(会用KmdKit就OK,不过不会也没关系,我会尽力跟大家讲解明白)。
三、对内核程序的认识和理解(请不要再停留在Cxxxx类的使用或某个Windows API的调用上,否则你根本就不会知道我在讲什么)。
四、会使用OllyDbg(会使用而已,不是说会破解)。
通过这一系列的文章,你可以学习到以下的知识:
一、使用汇编语言开发内核程序的知识(包括使用Visual Studio编写、汇编、连接汇编语言代码的知识,makefile我就不讲了,我自己也马不实在的)。
二、对内核有所认识和了解(至少知道什么是内核,什么是内核程序、内核基址等概念)。
三、对SSDT有所了解(你现在也可以去baidu上搜索一下什么是SSDT,做好准备)。
四、在内核上Hook SSDT(也可以直接Inline hook某些内核函数,但还是先一步一步来,SSDT稳当些)。
五、通过Hook内核的某些函数监视进程的创建,在内核态上向用户态应用程序分配内存并拷贝数据(或代码)进去。
六、编写自定位代码(包括在用户态上寻找Kernel32.dll基址等)。
本文所使用的环境是Windows XP SP3。因为XP比较熟悉了,而且买电脑的时候送的XP是正版,而且KmdKit又没有Windows 7的版本,而且我是个比较传统怀旧的人,而且......总之就是Windows XP SP3了!
好了,今天就讲这么多。如果你对今天所讲的东西感兴趣,那么就准备好上面的工具和知识吧。当然,你永远不要奢望就这么一个知识或技术就能让你成为牛人,因为没有任何一种技术能让你马上成为牛人的!