随锐旗下互动传媒:

Linux内核级后门的原理及简单实战应用

http://www.weaseek.com  2005-08-10 00:00:00  来源:e800开发者频道

以下代码均在linux i86 2.0.x的内核下面测试通过。

以下代码均在linux i86 2.0.x的内核下面测试通过。它也许可以在之前的版本通过,但并没有被测试过。因为从2.1.x内核版本就引入了相当大的改变,显著地内存管理上的差别,但这些不是我们现在要讨论的内容。

用户空间与内核空间

linux是一个具有保护模式的操作系统。它一直工作在i386 cpu的保护模式之下。

内存被分为两个单元:内核区域和用户区域。内核区域存放并运行着核心代码,当然,顾名思义,用户区域也存放并运行用户程序。当然,作为用户进程来讲它是不能访问内核区域内存空间以及其他用户进程的地址空间的。

核心进程也有同样的情况。核心代码也同样不能访问用户区地地址空间。那么,这样做到底有什么意义呢?我们假设当一个硬件驱动试图去写数据到一个用户内存空间的程序里的时候,它是不可以直接去完成的,但是它可以利用一些特殊的核心函数来间接完成。同样,当参数需要传递地址到核心函数中时,核心函数也不能直接的来读取该参数。同样的,它可以利用一些特殊的核心函数来传递参数。

这里有一些比较有用的核心函数用来作为内核区与用户区相互传递参数用。

memcpy_fromfs(void *to,const void *from,unsigned long n)      从用户内存中的*from拷贝n个字节到指向核心内存的指针*to。        
memcpy_tofs(void *to,const *from,unsigned long n)      从核心内存中的*from拷贝n个字节数据到用户内存中的*to。系统调用大部分的c函数库的调用都依赖于系统调用,就是一些使用户程序可以调用的简单核心包装函数。这些系统调用运行在内核本身或者在可加载内核模块中,就是一些可动态的加载卸载的核心代码。就象MS-DOS和其他许多系统一样,linux中的系统调用依赖一个给定的中断来调用多个系统调用。linux系统中,这个中断就是int 0x80。当调用  int 0x80  中断的时候,控制权就转交给了内核(或者,我们确切点地说, 交给_system_call()这个函数), 并且实际上是一个正在进行的单处理过程。* _system_call()是如何工作的?首先,所有的寄存器被保存并且%eax寄存器全面检查系统调用表,这张表列举了所有的系统调用和他们的地址信息。它可以通过extern void *sys_call_table[]来被访问到。该表中的每个定义的数值和内存地址都对应每个系统调用。大家可以在/usr/include/sys/syscall.h这个头中找到系统调用的标示数。他们对应相应的SYS_systemcall名。假如一个系统调用不存在,那么它在sys_call_table中相应的标示就为0,并且返回一个出错信息。否则,系统调用存在并在表里相应的入口为系统调用代码的内存地址。这儿是一个有问题的系统调用例程:        
[root@plaguez kernel]# cat no1.c[root@plaguez kernel]# cat no2.c#define MODULE#define __KERNEL__#define __KERNE_SYSCALLS__#defines (#define MODULE, #define __KERNEL__)和
                    
[责任编辑:]热门关键词:

相关文章