后门技术和Linux LKM Rootkit详解

ZDNet软件频道 时间:2008-07-01 作者:大鹰 | 赛迪网 我要评论()
本文关键词:命令行 Linux 技巧
在这篇文章里, 我们将看到各种不同的后门技术,特别是Linux的可装载内核模块(LKM)。我们将会发现LKM后门比传统的后门程序更加复杂,更加强大,更不易于被发现。

我们同时处理TCP和UDP的原因是假如那里有一些防火墙的话,UDP可能不能穿过。因此,我们只需要发一个源地址被伪造的数据包到目的机子。此外,对于TCP的数据包,它也不需要使用SYN位。事实上,现在我们的客户程序使用的是ACK的包。

第二个想法更使人感兴趣。 如果一台目标的机子上有个WEB的服务并且安了一个只允许WEB通信的防火墙,那么我们如何来穿过它呢? 我们能否得到一个交互的shell呢?答案是肯定的。方法如下:

____________ _________________________ 
| 攻击者    | | web server            | 
|          | | 80 <=======> 53333 | 
|__________| |_______________________| 
|                                    | 
|                                    | 
|____________________________________| 
1025 ==> 80 or 1025 <== 80

假设我们在web服务器上已经绑定了一个bind shell后门并且监听53333端口(可以利用第一个方法来完成) 现在我们需要把攻击者到web服务器上的流量从80端口重定向到53333端口, 从53333端口到攻击者的流量必须被改成80端口。

实现部分。改变接收的包是很容易的, 我们可以借用第一个LKM的思路- 无论何时我们都检查到来的tcp包如果必要我们修改它的目的端口。为了改变发出的包, 这就有点困难了。因为TCP/IP协议栈的实现涉及到Linux内核的一些底层的静态函数。它不太容易被置换(但是是可能的, 细节参见附录)。我们利用的是大部分发布时就被编译进内核中的防火墙。每个到来的包,转发的包, 或发出的包必须通过防火墙。并且防火墙函数是可以被动态地加载到内核里的!我们利用系统导出函数register_firewall() 在系统防火墙规则之前插入我们自己的规则。假如我们发现一些来自于53333端口的包, 我们可以自动改变它到80。

关于此实现的另外的细节是无论何时我们改变数据包, 我们必须去重新计算校验和。 更有趣的事情是我们可以在web服务器和其他一些机器上监听网络流量,我们可以看到他们的不同之处。在其他机器上的sniffer看起来象普通的web流量, 但是在web服务器上的sniffer是一些无用的流量纪录。具体细节参见附录。

现在我们谈一下如何来截获系统调用。为了隐藏入侵者的足迹, 文件, 进程,网络连接必须隐藏起来。 因为这些信息都是可以从特殊的系统调用里面获得的, 我们可以接获一些感兴趣的系统调用。

1. 隐藏文件。象这些命令如"ls", "du" 使用sys_getdents() 来获得目录信息。 所以LKM程序必须过滤这些输出来达到隐藏文件的目的。

2. 隐藏进程。在Linux的实现中,进程的信息被映射到/proc文件系统去了。我们的工作仍旧是捕获sys_getdents()调用在进程链表中标记为不可见。通常的手法是设置任务的信号标志位为一些未用的信号量,比如31就是一个例子。

3. 隐藏网络连接。 和隐藏进程相似, 在这个例子中我们是这去隐藏一些包括/proc/net/tcp和/proc/net/udp的文件。所以我们改变sys_read()。 无论何时读包含匹配字符串的这两个文件的时候, 系统调用将不会声明在使用它。

4. 重定向可执行文件。 有时候, 入侵者可能会需要替换系统的二进制文件, 象"login", 但不想改变原文件。他可以截获sys_execve()。因此, 无论何时系统尝试去执行"login"程序的时候, 它都会被重定向到入侵者给定的其他程序。

5. 隐藏sniffer。这儿我们指隐藏网络接口的杂拨模式。在这里我们要替换的是sys_ioctl()。

6. 和LKM通信。 黑客已经很好的安装了他的LKM。现在他需要告诉内核来隐藏其他文件。他该怎么做呢?我们知道从用户态切换到和心态通常是通过系统调用来进行的, 所以我们必须修改一些系统调用。

例如, 我们将截获sys_settimeofday()。当一个指定的参数被传递, 我们的系统调用将会为我们做一些适当的事情。

7. 隐藏LKM本身。一个优秀的LKM程序必须很好地隐藏它自己。系统里的LKM是用单向链表连接起来的, 为了隐藏LKM本身我们必须把它从链表中移走以至于lsmod这样的命令不能把它显示出来。

8. 隐藏符号表。通常的LKM中的函数将会被导出以至于其他模块可以使用它。因为我们是入侵者, 所以隐藏这些符号是必须的。幸运的是, 有一个宏可以供我们使用:"EXPORT_NO_SYMBOLS"。 把这个宏放在LKM的最后可以防止任何符号的输出。

经验和结论

做个LKM程序是一个非常有趣而又非常危险的事情。有趣的是你可以在系统内核中作你想做的事情。 但这也是非常危险的, 它可以使你的服务陷入混乱, 破坏你的数据, 并且可以在你的系统里做任何怪异的事情。 我们的经验有: 在安装了LKM程序几天后我们的网络层不工作了, 只工作五分钟就要重起一次; 无论何时发送数据包, 象这些应用程序 telnet, netscape, pine都将会产生core dump; 在安装LKM程序后立马重起。所以, 就象标题所说的那样,后果自负!

值得一提的是写一个LKM程序你可以更好地了解到系统是如何工作的。例如, /proc文件系统有很好的特性。因为LKM程序工作在内核空间, 调试LKM程序就变得比一般程序要困难。使用"printk"函数可以解决一些问题。但这不是最好的解决方法。通过注册在/proc文件系统里的我们的文件和目录的数据结构, 我们可以访问到任何时间的内核空间的信息。我们甚至可以通过写这个文件来修改内存, 尽管一般不建议这样做。

从经验来看, 很明显的LKM程序可以在Linux上安装,一旦系统被攻破并且被安装了LKM的Rootkit程序, 这就变的很难被发现了。因为甚至操作系统都不能信任了。如果机器不允许关机,唯一的发现入侵者的方法是通过分析在网络其他机器上的sniffer结果。或者, 利用其他的操作系统来监测硬盘。所有这两个方法都很难去做, 因为你不知道你要找什么。 所以,所以最好的安全措施就是防止被攻击者入侵系统。


百度大联盟认证黄金会员Copyright© 1997- CNET Networks 版权所有。 ZDNet 是CNET Networks公司注册服务商标。
中华人民共和国电信与信息服务业务经营许可证编号:京ICP证010391号 京ICP备09041801号-159
京公网安备:1101082134