服务器 频道

深入Linux网络核心堆栈之六

  ------[ 6.2 给狼披上羊皮

  当收到数据包并将其送到一个packet套接字时,packet_rcv()函数被调用。这个函数可以在net/packet/af_packet.c中找到,packet_rcv()负责使数据包经过所有应用于目的套接字的套接字过滤器,并最终将其递交到用户空间。为了隐藏来自packet套接字的数据包,我们需要阻止所有特定数据包调用packet_rcv()函数。我们如何做到这一点?当然是优秀的ol式的函数劫持了。

  函数劫持的基本操作是:如果我们知道一个内核函数,甚至是那些没有被导出的函数,的入口地址,我们可以在使实际的代码运行前将这个函数重定位到其他的位置。为了达到这样的目的,我们首先要从这个函数的开始,保存其原来的指令字节,然后将它们换成跳转到我们的代码处执行的绝对跳转指令。例如以i386汇编语言实现该操作如下:

  movl  (address of our function),  %eax
  jmp   *eax

  这些指令的16进制代码如下(假设我们的函数地址为0):

  0xb8 0x00 0x00 0x00 0x00
  0xff 0xe0

  如果我们在Linux核心模块的初始化时将上例中的函数地址替换为我们的hook函数的地址,我们就能够使我们的hook函数先运行。当我们想运行原来的函数时,我们只需要在开始时恢复函数原来的指令,调用该函数并且替换我们的劫持代码。简单而有效。Silvio Cesare 不久前写过一篇文章,讲述如何实现内核函数劫持,参见参考文献[4]。

  要从packet套接字隐藏数据包,我们首先要写一个hook函数,用于检查数据包是否满足我们隐藏的标准。如果满足,那么我们的hook函数简单的向它的调用函数返回0,packet_rcv()永远不会被调用。如果packet_rcv()永远不被调用,那么这个数据包也永远都不会递交给用户空间的packet套接字。注意,只是对于"packet"套接字来说,该数据包被丢弃了。如果我们要过滤送到packet套接字的FTP数据包,那么FTP服务器的TCP套接字仍然能收到这些数据包。我们所做的一切只是使运行在本机上的嗅探软件无法看到这些数据包。FTP服务器仍然能够处理和记录连接。

  理论上就是这么多,关于原始套接字的用法同理可得。不同的是我们需要hook的是raw_rcv()函数(在net/ipv4/raw.c中可以找到)。下一节将给出并讨论一个Linux核心模块的示例代码,该代码劫持packet_rcv()函数和raw_rcv()函数,隐藏任何来自或去往我们指定的IP地址的数据包。
 

0
相关文章