一、原理
Intel x86系列微机支持256种中断,为了使处理器比较容易地识别每种中断源,把它们从0~256编号,即赋予一个中断类型码n,Intel把它称作中断向量。
而Linux中的系统调用使用的是128号,即0x80号中断,所有的系统调用都是通过唯一的入口system_call()来进入内核,当用户动态进程执行一条int 0x80汇编指令时,CPU就切换到内核态,并开始执行system_call()函数,system_call()函数再通过系统调用表 sys_call_table来取得相应系统调用的地址进行执行。
系统调用表sys_call_table中存放所有系统调用函数的地址,每个地址可以用系统调用号来进行索引,例如sys_call_table[NR_fork]索引到的就是系统调用sys_fork()的地址。(arch/i386/kernel/syscall_table.S)
Linux用中断描述符(8字节)来表示每个中断的相关信息,其格式如下:
31…1615…0
偏移量
|
一些标志、类型码及保留位
|
段选择符
|
偏移量
|
所有的中断描述符存放在一片连续的地址空间中,这个连续的地址空间称作中断描述符表(IDT),在保护模式下,中断描述附表可能位于物理内存的任何地方。处理器有一个特殊的寄存器 IDTR,用来存储中断描述附表的起始地址与大小。这个IDTR的格式为:
47…1615…0
当产生一个中断时,处理器会将中断号乘以8然后加到中断描述符表的基址上。然后验证产生的结果地址位于中断描述附表内部(利用表的起始地址与长度)。如果产生的地址没有位于中断描述符表的内部,将产生一个异常。如果产生的地址正确,存储在描述附表中的 8-byte 的描述符会被 CPU 加载并执行。
通过上面的说明可以得出通过IDTR寄存器来找到system_call()函数地址的方法:根据IDTR寄存器找到中断描述符表,中断描述符表的第0x80项即是system_call()函数的地址。
在这里我们已经知道怎么获得了system_call()的方法,那如何获得sys_call_table的地址呢?
我们看看system_call()的源代码:
我们找到了sys_call_table的在代码的位置,因此通过下面指令,找出sys_call_table的指令码
$cd /usr/src/<linux-version>
$gdb -q vmlinux
$disass sys_call_table
$ x/xw syscall_call+0
下面就是通过查找0x408514ff这个指令来得到*sys_call_table 的值,以上我们便可以找到sys_call_table。
Linux 系统中用来查询文件信息的系统调用是sys_getdents64,这一点可以通过strace来观察到,例如strace ps 将列出命令ps用到的系统调用,从中可以发现ps是通过sys_getedents64来执行操作的。当查询文件或者目录的相关信息时,Linux系统用 sys_getedents64来执行相应的查询操作,并把得到的信息传递给用户空间运行的程序,所以如果修改该系统调用,去掉结果中与某些特定文件的相关信息,那么所有利用该系统调用的程序将看不见该文件,从而达到了隐藏的目的。首先介绍一下原来的系统调用,其原型为:
int sys_getdents64(unsigned int fd, struct linux_dirent64
*dirp,unsigned int count)
|
其中fd为指向目录文件的文件描述符,该函数根据fd所指向的目录文件读取相应dirent结构,并放入dirp中,其中count为dirp中返回的数据量,正确时该函数返回值为填充到dirp的字节数。
因此,只需要把上述的sys_getdents64替换成自己写的hacked_getdents函数,对隐藏的进程进行过滤,从而实现进程的隐藏。
在hacked_getdents函数中,怎么对隐藏的进程进行过滤呢?
由于在Linux中不存在直接查询进程信息的系统调用,类似于ps这样查询进程信息的命令是通过查询proc文件系统来实现的,由于proc文件系统它是应用文件系统的接口实现,因此同样可以用隐藏文件的方法来隐藏proc文件系统中的文件,只需要在上面的hacked_getdents中加入对于proc文件系统的判断即可。
由于proc是特殊的文件系统,只存在于内存之中,不存在于任何实际设备之上,所以Linux内核分配给它一个特定的主设备号0以及一个特定的次设备号3, 除此之外,由于在外存上没有与之对应的i节点,所以系统也分配给它一个特殊的节点号PROC_ROOT_INO(值为1),而设备上的1号索引节点是保留 不用的。
通过上面的分析,可以得出判断一个文件是否属于proc文件系统的方法:
1)得到该文件对应的fstat结构fbuf;
2)if
(fbuf->ino == PROC_ROOT_INO && !MAJOR(fbuf->dev) &&
MINOR(fbuf->idev) == 3)
{该文件属于proc文件系统}
通过上面的分析,给出隐藏特定进程的伪代码表示:
以上便是通过劫持系统调用而实现隐藏进程的原理!
二 、实现
本人比较懒,懒得再重新设置进程的hide变量,于是在之前的一篇文章《linux 隐藏进程-crux实现》基础上进行修改(url:http://blog.csdn.net/billpig/archive/2010/11/26/6038330.aspx),使得内核能够同时支持本文的方法及前篇文章的方法。为了区分开两种方法,在include/linux/文件夹下添加hide.h头文件。
在hide.h选择隐藏文件的方式后,在linux内核文件目录下,执行make bzImage,然后把得到的内核加入grub目录。分别设置不同的隐藏方式即可得到不同方法所得到的内核。
2.1 修改前一篇文章 /proc
修改前一篇文件/proc的代码,使得不会影响本文代码的实现(因为前篇文章已经实现进程隐藏了,再次隐藏无意义),于是修改fs/proc/base.c的proc_pid_readdir()的代码如下:
2.2 本文方法的实现
2.2.1 hook.c
在2.1中去除掉了修改后的/proc代码对本文的影响,接下来便实现在第一部分内容原理的代码。
于是,在kernel目录下创建hook.c文件,具体内容如下:
然后在修改kernel/Makefile,把hook.o添加入编译选项,使得hook.c代码编译入内核
2.2.2 添加系统调用
接着,就如和前篇文章一样,添加系统调用的头部及相关信息
在include/asm-i386/unistd.h添加系统调用号及系统的调用总数
arch/i386/kernel/syscall_table.S在系统调用表中添加相应项,在最后一行添加
在include/linux/syscalls.h添加函数声明
至此,添加系统调用完成,重新编译内核
三、测试
我们编写了一个测试函数,用来我们修改的内核是否成功,代码hook.c(注意跟内核的hook.c区分开来)如下:
gcc hook.c -o hook后,执行 ./hook ,查看结果如图
4、结束语
这只是实现隐藏的另一种方式,网上实现的拦截系统调用只是简单的拦截而已,没有更深一层的应用,本文也是对隐藏进程的另一种补充。由于只是演示而已,个人觉得采用模块的方式会比较好,因为内核的系统调用代码一般是不会修改的。
参考资料:
[1] Linux2.6内核中劫持系统调用隐藏进程:http://linux.chinaitlab.com/kernel/810229_3.html
[2] 高手过招谈Linux环境下的高级隐藏技术:http://blog.csdn.net/ldong2007/archive/2008/09/03/2874082.aspx
[3] 2.6内恶化里劫持系统调用:http://blog.csdn.net/ldong2007/archive/2008/09/03/2872144.aspx
[4] 2.6版本Linux上替换系统调用函数实现隐藏文件学习:http://blog.csdn.net/ldong2007/archive/2008/09/03/2872077.aspx
版权所有,转载请出明出处!
分享到:
相关推荐
Linux 2.6调度系统的分析与改进.pdf
在linux2.6内核下添加系统调用的过程.pdf欢迎大家下载。。
修改linux2.6.32.2内核源码,编写一个新的系统调用。
Linux2.6系统调用钩子的原理分析和实现应用.pdf
由浅到深分析linux2.6内核的启动,方便对Linux各内核版本的启动分析学习。
讲述在linux内核2.6下具体的裁剪过程
《Linux2.6内核标准教程》适合Linux内核爱好者、Linux驱动开发人员、Linux系统工程师参考使用,也可以作为计算机及相关专业学生深入学 习操作系统的参考书。 引用: 目录 第1章 Linux内核学习基础 1 1.1 为什么...
Linux 2.6内核分析——对进程调度机制的分析.pdf
linux2.4.16内核升级到2.6.18
linux 2.6 启动流程分析 linux 2.6 启动流程分析
Linux2.6进程调度机制的剖析.pdf
LINUX 2.6内核标准教程(华清远见,河秦)(高清PDF共218M)10/10
linux2.6内核编译方法详述 linux2.6内核编译方法详述
《Linux2.6内核标准教程》适合Linux内核爱好者、Linux驱动开发人员、Linux系统工程师参考使用,也可以作为计算机及相关专业学生深入学 习操作系统的参考书。 引用: 目录 第1章 Linux内核学习基础 1 1.1 为什么...
本文分析了在 Linux 2.6 中引入的对 Intel CPU 快速系统调用指令 SYSENTER/SYSEXIT 支持的实现。Linux 驱动及内核开发者通过了解快速系统调用指令的机制,可以在自己的代码中通过利用这一机制,提高系统性能,并避开...
Linux 2.6 调度系统分析
Linux2.6内核的定制
第2部分第6次课linux2.6内核之系统调用及定时器详解.ppt
linux 2.6源码,最广为人知的