Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1648
  • 博文数量: 1
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 20
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-26 19:41
文章分类
文章存档

2014年(1)

我的朋友
最近访客

分类: 其他平台

2014-06-06 17:03:54

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





   以下代码均在linux i86 2.0.x的内核下面测试通过。它兴许能够在之前的版本通过,但并不被测试过。因为从2.1.x内核版本就引入了相称大的转变,明显地内存治理上的差异,但这些不是我们当初要探讨的内容。  用户空间与内核空间  linux是一个存在掩护模式的操作系统。它始终工作在i386 cpu的维护模式之下。  内存被分为两个单元:内核区域和用户区域。内核区域存放并运行着核心代码,当然,顾名思义,用户区域也寄存并运行用户程序。当然,作为用户过程来讲它是不能访问内核区域内存空间以及其他用户进程的地址空间的。  核心进程也有同样的情形。核心代码也同样不能访问用户区地地址空间。那么,这样做到底有什么意思呢·我们假设当一个硬件驱动试图去写数据到一个用户内存空间的程序里的时候,它是不可以直接去完成的,但是它可以利用一些特别的核心函数来间接完成。同样,当参数需要传递地址到核心函数中时,核心函数也不能直接的来读取该参数。同样的,它可以利用一些特殊的核心函数来传递参数。  这里有一些比拟有用的核心函数用来作为内核区与用户区彼此传递参数用。





#include asm/segment.h
get_user(ptr)  从用户内存获取给定的字节,字,或者长整形。这只是一个宏在核心代码里面有此宏的具体定义,并且它根据参数类型来断定传输数目。所以你必需奇妙天时用它。   put_user(ptr)跟get_user()十分类似,然而,它不是从用户内存读取数据,而是想用户内存写数据。





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函数库的调用都依附于系统调用,就是一些使用户程序可以调用的简略核心包装函数。这些系统调用运行在内核自身或者在可加载内核模块中,就是一些可动态的加载卸载的核心代码。   就象MSDOS和其余很多系同一样,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,并且返回一个出错信息。否则,系统调用存在并在表里相应的进口为系统调用代码的内存地址。这儿是一个有问题的系统调用例程:





.rootplaguez kernel.# cat no1.c
#include linux/errno.h
#include sys/syscall.h
#include errno.h

extern void .sys_call_table..;

sc()
{ // 165这个体系调用,是不存在的。
__asm__(
"movl $165,eax
int $0x80");
}

main()
{
errno sc();
perror("test of invalid syscall");
}
.rootplaguez kernel.
# gcc no1.c
.rootplaguez kernel.
# ./a.out
test of invalid syscall:
Function not implemented
.rootplaguez kernel.
# exit

  系统把持权就会转向真正的系统调用, 用来实现你的恳求并返回。 而后_system_call()调用_ret_from_sys_call()来检讨不同的返回值, 并且最后返回到用户内存。   . libc   这int $0x80 并不是直接被用作系统调用; 更确实地是,libc函数,常常用来包装0x80中止,这样应用的。   libc通常应用_syscallX()宏来描写系统调用,X是系统调用的总参数个数。   举个例子吧, libc中的write(2)就是利用_syscall3这个系统调用宏来实现的,由于实际的write(2)原型须要3个参数。在调用0x80中断之前,这个_syscallX宏假设系统调用的堆栈构造和请求的参数列表,最后,当 _system_call()(通过int 0x80来引发)返回的时候,_syscallX()宏将会查犯错误的返回值在eax并且为其设置errno。



.1. .2. 下一页


阅读(569) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~