抒写Linux 2.6.x下内核级后门程序

Author:;wzt
EMail:;wzt@xsec.org
Site:;http://www.xsec.org;&;hhtp://hi.baidu.com/wzt85
Date:;2008-8-29

一.;内核后门简介
二.;内核中系统调用
三.;使用kernel;mode;socket函数
四.;如何扩展后门
五.;参考资料
六.;相关源代码

一.;内核后门简介

所谓内核后门 , ;当然指的是在内核空间中给hacker提供的可远程控制的shell模块喽 , ;性质跟ring3下的后门一样 , 只是所有功能都在内核空间实现了而已 。其实它跟rootkit的定义基本已经混淆了 。有的内核后门不能提供隐藏行为的功;能 , 有的rookit没有提供远程shell的功能 。只有两者互补才能组合成一个功能强的’root-kit’.
本文只介绍2种实现内核后门的基本方法 , 如果您有更好的方法 , 还请多多指教 。

二.;内核中系统调用

Unix世界中一切皆文件的思想将socket通信变的简单的多 , ;通常我们直接可以用read , write等api函数作为socket通信的方法 , 这些api函数最终都会调用kernel提供的sys_XXX系列函;数 。平时用到的read等函数早以在c库中封装好了 。其实我们可以自己直接向系统发送软中断int;0x80来执行sys_read函数 , 如:

int;my_read(int;fd,;char;*;buf,;off_t;count)
{
long;__res;

__asm__;volatile;("push;%離;;int;$0x80;;pop;%離"

:;"=a";(__res)
:;"0";(__NR_read),;"ri";((long)(fd),;;;;;"c"((long)(buf),
"d";((long)(count));:"memory");

return;(int)(__res);
}

这里用到了at&t的内嵌汇编程序来实现,;其实就是向eax寄存器中存入具体的系统调用号 , ebx , ecx , edx依次存入read函数的参数 。最后执行一个int;$0x80陷入内核去执行sys_read.要想在内核空间中实现后门的功能 , ;就必须调用某些函数来进行socket通信 。;本节介绍直接在内核中使用系统调用的方式来和远程用户进行通讯,下一节则介绍直接使用内核socket函数进行通讯 。

通过上面的例子 , 我们明白了如何在用户空间下来使用系统调用 。那么上述方法也可以用在内核空间中 , 这样在内核空间执行系统调用感觉效率会很低 , 但是对我们来说 , 编写程序将会非常的方便 。著名的sk;rookti就是用这种方式来进行通讯的 。

linux内核提供了很多个不同的系统调用 , 我们需要编写几个宏来方便的使用这些系统调用 。比如下面这几个宏:

#define;my__syscall_return(type,;res);/
do;{;/
if;((unsigned;long)(res);>=;(unsigned;long)(-(128; ;1)));{;/
errno;=;-(res);;/
res;=;-1;;/
};/
return;(type);(res);;/
};while;(0)

#define;my_syscall3(type,name,type1,arg1,type2,arg2,type3,arg3);/
type;name(type1;arg1,type2;arg2,type3;arg3);/
{;/
long;__res;;/
__asm__;volatile;("push;%離;;;int;$0x80;;;pop;%離";/
:;"=a";(__res);/
:;"0";(__NR_##name),"ri";((long)(arg1)),"c";((long)(arg2)),;/
"d";((long)(arg3));:;"memory");;/
my__syscall_return(type,__res);;/
}

my_syscall3代表这个系统调用有3个参数 , 以read系统调用为例 , 我们可以在内核空间中这样使用它:
static;inline;my_syscall3(int,;read,;int,;fd,;char;*,;buf,;off_t,;count);

编译的时候就会被展开成:

int;read(int;fd,;char;*;buf,;off_t;count);;;;/
{;;;;/
long;__res;;;;;;;/

__asm__;volatile;("push;%離;;int;$0x80;;pop;%離"/

:;"=a";(__res);/
:;"0";(__NR_read),;"ri";((long)(fd),;"c"((long)(buf),;/
"d";((long)(count));:"memory");;/

return;(int)(__res);/
}

本文后面将会给出比较全面的宏 , 通过这些宏 , 可以在内核中随意的使用系统调用 。

好了 , 现在可以使用read,;write,;select等系统调用在内核空间收发信息了 。;但是怎么在内核中使用平时在用户空间下用到的那些socket函数呢?其实这些socket函数都是通过执行sys_socketall系统调用来实现的:

推荐阅读