加入我的最爱 设为首页 风格修改
首页 首尾
 手机版   订阅   地图  繁体 
您是第 2697 个阅读者
 
发表文章 发表投票 回覆文章
  可列印版   加为IE收藏   收藏主题   上一主题 | 下一主题   

头像
个人文章 个人相簿 个人日记 个人地图
路人甲
级别: *
推文 x 鲜花 x
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片
推文 x0
[资讯教学] 内核级Rootkit技术入门


献花 x0 回到顶端 [楼 主] | Posted:2007-06-26 03:05 |
upside 手机 葫芦墩家族
个人头像
个人文章 个人相簿 个人日记 个人地图
特殊贡献奖 社区建设奖 优秀管理员勋章
头衔:反病毒 反诈骗 反虐犬   反病毒 反诈骗 反虐犬  
版主
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

三、将代码导入内核的方法

所有应用程序都是运行在用户模式下的,而操作系统是运行在内核模式下的,所以应用程序根本没有机会来修改内核程序。要想颠覆内核,前提是设法让我们的代码也运行在内核模式下,即将我们的代码导入内核。

设想一下当我们的代码通过驱动程序进入内核后的情形:我们的代码一旦在内核运行,就能访问内核的所有特权内存空间和系统进程——有了这样的内核级访问特权,我们就能任意修改系统中的任何代码和数据了!

将代码导入内核的方法很多,但我们要介绍的是利用设备驱动程序将代码导入内核的方式。内核驱动程序有多种叫法,有时候又称为内核驱动程序,或者可加载模块。我们之所以利用设备驱动程序将代码导入到内核,主要考虑到两点:

1.简单性。能够让我们的代码运行在内核模式之的方法有多种,例如把我们的代码做成设备驱动程序、设法修改正在内存运行的内核、覆盖硬盘中的内核映像等等。其中,利用设备驱动程序是最为简单的一种。

2.适用性。现在,绝大多数的操作系统都允许第三方的硬件厂商加载为其硬件产品制作的内核扩展,从而使得操作系统能够支持它们的硬件产品。这的确是一个双赢之举,只有这样,操作系统开发商才能不断巩固和扩大其用户群。因此,各个操作系统开发商不仅提供该系统下的开发设备驱动程序的详尽帮助文档,而且还提供了相应的开发工具包。

虽然我们已经找到将我们的代码导入到内核模式的路径,但还有一个问题需要回答:除了与硬件打交道的代码外,其它代码是否也能写进设备驱动程序?答案是肯定的。尽管这里的“设备”一词容易误导我们,实际上任何代码都可以写成设备驱动程序。

迄今为止,我们已经回答了利用设备驱动程序来打造内核级别的Rootkit可行性问题,也就是说,内核级Rootkit大门已经打开了一扇,为了打开另一扇,我们要解决的是“how to”的问题。并且,我们第一个必须解决的“how to”问题就是如何编写Windows设备驱动程序。

四、Windows设备驱动程序

下面我们介绍如何在Windows XP平台上开发一个简单的设备驱动程序。在此过程中,我们要用到设备驱动程序开发包DDK。需要注意的是,微软为不同的Windows版本提供了不同的DDK。就目前来说,我们可以使用Windows 2003 DDK,因为该版本能够支持Windows 2000、Windows XP和Windows 2003等三个平台下的设备驱动程序的开发。

1. 驱动程序源文件

首先在C盘根目录下新建一个目录,本例为C:\myrootkit,此后向相应文件都存放在该目录之下。然后可以在VC++下建立一个C源文件,让其内容如下所示:



//一个简单的驱动程序实例

#include "ntddk.h"

NTSTATUS DriverEntry ( IN PDRIVER_OBJECT theDriverObject,

IN PUNICODE_STRING theRegistryPath )

{

DbgPrint("I am a driver!");

return STATUS_SUCCESS;

}

之后,将其保存在我们的C:\myrootkit目录下,并且该文件命名为mydriver.c。下面对上面的代码作简要的解释:

DriverEntry是该驱动程序的入口点,即当该驱动程序启动时,操作系统会首先调用该函数。它相当于一般C/C++程序中的main或Winmain函数。另外,我们看到DriverEntry的两个参数中都含有一个关键词IN,说明这两个参数只能用于输入。第一个参数指向应被初始化的当前驱动程序的驱动对象;第二个参数是设备服务键的键名。

该驱动程序实在太简单了,它只是在内核运行时,利用调试语句给出一则消息:“I am a driver!”。不过,和一般程序不同,该消息不会显示在标准输出设备上,也就是说,我们在屏幕上看不到这则消失,关于调试输出的处理我们会在后文中加以详细介绍。

有一点需要指出,那就是上面的驱动程序没有设置卸载例程。尽管卸载例程不是必需的,但有时它却非常有用:启动驱动程序时,系统会将参数theDriverObject传递给该驱动程序的主函数,这个参数指向的数据结构含有许多函数指针,其中一个指针称为“unload routine”。如果我们设置该指针,就能从内存中卸载驱动程序;如果不设置该指针的话,除非重新启动机器,否则无法将载入内存的驱动程序卸载掉。同时,驱动程序在开发过程中,会不断添加或改变功能,所以要经常装载以及卸载它们。为了避免每次测试新版本的驱动程序时都必须重启系统,我们应当设置“unload routine”指针。事实上,设置该指针并不是什么难事:先建立一个卸载例程,就可以设置该卸载指针了。

现在以前面的驱动程序为例,介绍如何为其添加卸载例程:

//一个简单的驱动程序实例

#include "ntddk.h"

// 这里是我们的卸载函数

VOID MyUnload( IN PDRIVER_OBJECT DriverObject )

{

DbgPrint("MyUnload called\n");

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,

IN PUNICODE_STRING theRegistryPath)

{

DbgPrint("I am a driver and I loaded!");

// 初始化DriverObject对象中指向卸载函数的指针

theDriverObject->DriverUnload = MyUnload;

return STATUS_SUCCESS;

}

这样一来,我们用重启系统就能方便地装载和卸载驱动程序了。


爸爸 你一路好走
献花 x0 回到顶端 [1 楼] From:台湾和信超媒体宽带网 | Posted:2007-06-26 03:06 |
upside 手机 葫芦墩家族
个人头像
个人文章 个人相簿 个人日记 个人地图
特殊贡献奖 社区建设奖 优秀管理员勋章
头衔:反病毒 反诈骗 反虐犬   反病毒 反诈骗 反虐犬  
版主
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

2. SOURCES文件

要想构建设备驱动程序,仅有驱动程序源文件还是不够的,我们还需另外两个文件:SOURCES和MAKEFILE文件。

我们先来介绍SOURCES文件,此文件的名称必须使用大写字母,并且不带任何扩展名,它的内容应当包含:

TARGETNAME=MYDRIVER

TARGETPATH=OBJ

TARGETTYPE=DRIVER

SOURCES=mydriver.c




其中,第一个变量TARGETNAME的作用是为我们的驱动程序命名。在本例中,我们的设备驱动程序在编译后被命名为MYDRIVER。需要注意的是,变量TARGETNAME指定的名称会被嵌入到二进制代码之中,所以在写Rootkit时,千万不要用该变量为其指定容易被人猜中的名称。即使把二进制文件本身改名,但其内部的名字是无法改变的。最好用一些迷惑性较强的名称来为这些Rootkit命名,方法是根据系统中已有的驱动程序名,在此基础上少做手脚,一个上佳的Rootkit名便诞生了。

第二个变量TARGETPATH的作用是指定驱动程序编译后的存放位置,该变量通常设为OBJ。一般来说,驱动程序文件被放在目录objchk_xxx/i386下面,例如本文驱动程序,作者在Windows XP下构建后的文件将位于C:\myrootkit\objchk_wxp_x86\i386。

第三个变量TARGETTYPE用来指定要编译的文件类型。对于设备驱动程序,该变量设为DRIVER。

第四个变量SOURCES用来指定源文件。该变量可以指定多个源文件,这时每行一个文件,并且除最后一行外,在每行末尾都要放上一个反斜杠,如下例所示:

SOURCES= myfile1.c \

myfile2.c \

myfile3.c   /*注意,最后一行没有反斜杠*/


除了上面几个必选的变量外,还有一些可选变量。变量INCLUDES便是可选变量之一,它用以规定寻找包含文件的目录。现举例说明: NCLUDES = c:\my_includes \

..\..\inc \

c:\other_includes


如果需要链接库的话,我们还需要变量TARGETLIBS。例如,有时我们要用到NDIS库,这时在SOURCES文件就应当包含如下一行: TARGETLIBS=$(BASEDIR)\lib\w2k\i386\ndis.lib
或者: TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib
当然,ndis.lib在你自己系统上的位置可能有所不同,你可以根据实际情况将上面的路径加以调整。其中,变量$(BASEDIR)规定DDK的安装目录$(DDK_LIB_PATH);变量$(DDK_LIB_PATH)则规定了库文件的默认安装位置。


爸爸 你一路好走
献花 x0 回到顶端 [2 楼] From:台湾和信超媒体宽带网 | Posted:2007-06-26 03:06 |
upside 手机 葫芦墩家族
个人头像
个人文章 个人相簿 个人日记 个人地图
特殊贡献奖 社区建设奖 优秀管理员勋章
头衔:反病毒 反诈骗 反虐犬   反病毒 反诈骗 反虐犬  
版主
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

3. MAKEFILE文件

和SOURCES文件一样,MAKEFILE文件的名称也必须使用大写字母,同时也不能带任何扩展名,它的内容一般为:

!INCLUDE $(NTMAKEENV)\makefile.def
注意的是,要在Windows中建立不带扩展名的文件,可以利用dos命令行下的EDIT命令或copy con命令。此外,SOURCES和MAKEFILE文件必须与驱动程序的源代码位于同一个目录下。

4. 构建过程

准备好SOURCES、MAKEFILE以及C源代码文件后,我们就可以构建驱动程序了。在此之前,我们先说明一下DDK的两种构建环境:checked和free构建环境。其中前者一般在开发过程中使用,为了便于调试,它会在生成的驱动程序中添加一些调试信息,这会使得驱动程序体积较大。开发测试完成后,当我们需要发布产品级的驱动程序时,就可以利用free构建环境来生成驱动程序。

从DDK中单击checked-build environment,打开命令窗口;

然后,利用cd命令将工作目录切换到C:\myrootkit目录下面:

cd C:\myrootkit

接着在命令提示符下输入命令build开始构建;

如果没有收到任何错误消息,而是类似下图所示的提示,则说明我们的第一个设备驱动程序已经大功告成了!


五、小结

到目前为止,本文介绍了Windows下的内核级Rootkit的最基础性的东西,以及利用驱动程序将代码导入到内核的方法。虽然我们还没有涉及到真正的Rootkit,但这些内容是我们掌握Rootkit的必经之路,就像我们要建一座6层的楼房,却不能撇开基础和低层而直接盖第六层一样!更多的内容,会在后续的文章中陆续介绍。


爸爸 你一路好走
献花 x0 回到顶端 [3 楼] From:台湾和信超媒体宽带网 | Posted:2007-06-26 03:07 |
jack1984yw
数位造型
个人文章 个人相簿 个人日记 个人地图
初露锋芒
级别: 初露锋芒 该用户目前不上站
推文 x95 鲜花 x150
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

谢谢大大提供知识


献花 x0 回到顶端 [4 楼] From:台湾 | Posted:2007-12-24 17:45 |
yuan2626
个人文章 个人相簿 个人日记 个人地图
小人物
级别: 小人物 该用户目前不上站
推文 x0 鲜花 x18
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

感谢
收到
知识是无价的


献花 x0 回到顶端 [5 楼] From:台湾 | Posted:2007-12-25 00:20 |

首页  发表文章 发表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 0.065739 second(s),query:16 Gzip disabled
本站由 瀛睿律师事务所 担任常年法律顾问 | 免责声明 | 本网站已依台湾网站内容分级规定处理 | 连络我们 | 访客留言