¶´Ï¤linuxϵÄNetfilter&iptables£º¿ª·¢×Ô¼ºµÄhookº¯Ê
×÷Õߣº¹ý¿Í  ·¢±íÈÕÆÚ£º2016-01-01 21:44:46  µã»÷£º634

ÏòNetfilterÖÐ×¢²á×Ô¼ºµÄhookº¯Êý

        Êý¾Ý°üÔÚЭÒéÕ»Öд«µÝʱ»á¾­¹ý²»Í¬µÄHOOKµã£¬¶øÃ¿¸öHOOKµãÉÏÓÖ±»NetfilterÔ¤ÏÈ×¢²áÁËһϵÁÐhook»Øµ÷º¯Êý£¬µ±Ã¿¸öÇå´¿µÄÊý¾Ý°üµ½´ïÕâЩµãºó»á±»ÕâЩ¿É¶ñhookº¯ÊýÂÖ·¬µ÷Ï·Ò»·¬¡£ÓÐʱºòÎÒÃǾÍÔÚÏ룬ֻÈÃϵͳ×Ô´øµÄÕâЩ¶ñ¹÷À´¿ì»î£¬ÎÒ×Ô¼ºÄܲ»ÄÜÒ²makeÒ»¸öhook³öÀ´ºÍËüÃÇͬÁ÷ºÏÎÛÄØ£¿´ð°¸Êǿ϶¨µÄ¡£

       ÎÒÃÇÀ´»Ø¹ËÒ»ÏÂĿǰϵͳÖÐÒѾ­×¢²áÁ˵Ähookº¯Êý¿É·ÖΪÒÔϼ¸Àà:

       ËüÃÇÔÚЭÒéÕ»ÖÐλÖÃÈçÏ£º

       Ê×ÏÈÎÒÃÇÐÄÀïÒª·Ç³£Çå³þµÄÖªµÀÎÒÃǽ«Òª¿ª·¢µÄÕâ¸öhookº¯ÊýλÓÚÄĸöHOOKµãµÄʲô¼¶±ð£¬ËüµÄǰºó·Ö±ðÊÇÄÄЩº¯Êý£¬ÕâÒ»µãºÜÖØÒª£¬ÒòΪÓöµ½ÎÊÌâʱÖÁÉÙÐÄÀïÓиöÆ×¡£

       ÎÒÃǽñÌì½²µÄÕâ¸öhookº¯Êý¹¦Äܼܺòµ¥£¬Ö÷ÒªÊÇÏò´ó¼Òչʾ¿ª·¢Á÷³ÌºÍ·½·¨¡£Ï¸½ÚÐԵĶ«Î÷»¹ÐèҪÿ¸öÈËÈÕ»ýÔÂÀÛµÄÐÞÁ¶²ÅÐС£

 

        Òª×¢²áÒ»¸öhookº¯ÊýÐèÒªÓõ½nf_register_hook()»òÕßnf_register_hooks()ϵͳAPIºÍÒ»¸östruct nf_hook_ops{}ÀàÐ͵ĽṹÌå¶ÔÏó¡£×î¼òµ¥µÄhookº¯ÊýÈçÏ£º

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/ip.h>

#include <linux/version.h>

#include <linux/skbuff.h>

#include <linux/netfilter.h>

#include <linux/netfilter_ipv4.h>

#include <linux/moduleparam.h>

#include <linux/netfilter_ipv4/ip_tables.h>

 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("koorey KING");

MODULE_DESCRIPTION("My hook test");

 

static int pktcnt = 0;

//ÎÒÃÇ×Ô¼º¶¨ÒåµÄhook»Øµ÷º¯Êý£¬¶ªÆúÿµÚ5¡Án(n=1,2,3,4¡­)¸öICMP±¨ÎÄ¡£

static unsigned int myhook_func(unsigned int hooknum, struct sk_buff **skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))

{

   const struct iphdr *iph = (*skb)->nh.iph;

   if(iph->protocol == 1){

      atomic_inc(&pktcnt);

      if(pktcnt%5 == 0){

           printk(KERN_INFO "%d: drop an ICMP pkt to %u.%u.%u.%u !\n", pktcnt,NIPQUAD(iph->daddr));

           return NF_DROP;

      }

   }

   return NF_ACCEPT;

}

 

static struct nf_hook_ops nfho={

        .hook           = myhook_func,  //ÎÒÃÇ×Ô¼ºµÄhook»Øµ÷´¦Àíº¯Êý

        .owner          = THIS_MODULE,

        .pf             = PF_INET,

        .hooknum        = NF_IP_LOCAL_OUT, //¹ÒÔØÔÚ±¾µØ³ö¿Ú´¦

        .priority       = NF_IP_PRI_FIRST,  //ÓÅÏȼ¶×î¸ß

};

 

static int __init myhook_init(void)

{

    return nf_register_hook(&nfho);

}

 

static void __exit myhook_fini(void)

{

    nf_unregister_hook(&nfho);

}

 

module_init(myhook_init);

module_exit(myhook_fini);

 

       ÎÒÃÇÔÚLOCAL_OUTÕâ¸öHOOKµãÉÏ£¬ÒÔ×î¸ßÓÅÏȼ¶NF_IP_PRI_FIRST×¢²áÁËÒ»¸öÃûΪmyhook_func()µÄº¯Êý¡£´Ó±¾»ú·¢³öµÄËùÓÐÊý¾Ý°ü´ÓЭÒéÕ»½øÈëNetfilter¿ò¼Üʱ£¬×îÏȶ¼»á±»¸Ãº¯ÊýËù¿´µ½£¬È»ºóÎÒÃÇÔÚÕâÀï¾Í¿ÉÒÔ¡°ºú×÷·ÇΪ¡±ÁË¡£

       Õâ¸öÄ£¿é×îºó»á±»±àÒë³ÉÃûΪmyhook.koµÄÇý¶¯Ä£¿é£¬È»ºóÓÃinsmodÀ´½«Æä¼ÓÔØ¡£¾ßÌå²Ù×÷Á÷³ÌÈçÏ£º

       ¿ÉÒÔ¿´µ½£¬ÎÒÃÇ×Ô¼ºµÄhookº¯ÊýÒѾ­³É¹¦runÆðÀ´ÁË¡£ÎÒÃÇ¿ÉÄܲ»½ö¾ÖÏÞÓÚ×öÕâô¼òµ¥Ò»¸öhook£¬Ã»Ê²Ã´ÒâÒ壬Ҳûɶ³É¾Í¸Ð¡£¿öÇÒÕâÖÖhookѹ¸ù¶ù¾ÍûÓдæÔڵļÛÖµ£¬ÒòΪÎÒÃÇÍêÈ«¿ÉÒÔͨ¹ýiptablesÀ´ÅäÖÃÏàÓ¦µÄ¹æÔò¶ø´ïµ½Í¬ÑùµÄÄ¿µÄ¡£

       OK£¬ÄÇÎÒÃǾ͸ÄÔìһϸÕдµÄÕâ¸öhook¡£ÈÃËüʵÏֵŦÄÜÊÇ£ºÃ¿ÊÕµ½5¸öICMP±¨ÎľÍÏòÖ¸¶¨µÄIPµØÖ··¢ËÍÒ»¸öUDP±¨ÎÄ¡£ÓÉÓÚÕâ¸ö¹¦ÄܵĿª·¢Ç£³¶µ½ÄÚºËЭÒéÕ»±à³Ì£¬¹ØÓÚЭÒéÕ»²¿·Ö´òËãÔÚÒÔºóµÄϵÁв©ÎÄÖÐÏêϸ²ûÊö¡£ÕâÀï½ö×ö¸ö¼òµ¥µÄÆÕ¼°ÈëÞͿÉÒÔÁË¡£

      ÎÒÃÇҪʵÏֵŦÄÜÊÇ´ÓÄÚºËÖз¢Ò»¸ö±¨ÎÄ£¬ÕâÍêÈ«²»Í¬ÓÚ֮ǰÔÚÓû§²ãͨ¹ýsocketÌ×½Ó×Ö±à³ÌµÄģʽ¡£

GodbachÐÖµÄÎÄÕÂhttp://blog.chinaunix.net/u/33048/showart_2043789.html£¬ÒÔ¼°Äں˰æµÄ¾«»ªÌû¡¶½ÌÄãÐÞ¸ÄÒÔ¼°Öع¹skb¡·¶¼ÊǷdz£¾­µäµÄ²Î¿¼ÎÄÕ¡£²»Ì«Ã÷°×µÄͯЬ¿ÉÒÔÈ¥°Ý¶Áһϣºhttp://linux.chinaunix.net/bbs/thread-1152885-1-4.html¡£

      ÔÙÖØÉêÒ»ÏÂÎÒÃǵÄÄ¿±ê£¬Ã¿ÊÕµ½5¸öICMP±¨ÎľÍÏòÖ¸¶¨IP(ÀýÈç118.6.24.132)·¢ËÍÒ»¸öUDP±¨ÎÄ¡£ÕâÀïÎÒÊÇÔÚÄÚºËÀï×Ô¼ºÈ¥DIYÒ»¸öеÄskb³öÀ´£¬¹¹ÔìÊý¾Ý°üºÍ·¢ËÍÊý¾Ý°üµÄ¹ý³ÌÈçÏ£º

#define    ETH    "eth0"  //½Ó¿ÚÃû³Æ

#define    SIP     "192.168.6.130" //½Ó¿ÚµÄIPµØÖ·

#define    DIP     "118.6.24.132" //Òª·¢ËÍUDP±¨ÎĵÄÄ¿µÄIPµØÖ·

#define    SPORT   39804   //Ô´¶Ë¿Ú

#define    DPORT   6980    //Ä¿µÄ¶Ë¿Ú

unsigned char SMAC[ETH_ALEN] = {0x00,0x0C,0x29,0x33,0x2C,0x3C}; //eth0Íø¿¨µØÖ·

unsigned char DMAC[ETH_ALEN] = {0x00,0x50,0x56,0xF4,0x8B,0xB3}; //ĬÈÏÍø¹ØµÄÍø¿¨µØÖ·

 

static int build_and_xmit_udp(char * eth, u_char * smac, u_char * dmac,

             u_char * pkt, int pkt_len,u_long sip, u_long dip,

             u_short sport, u_short dport)

{

  struct sk_buff * skb = NULL;

  struct net_device * dev = NULL;

  struct ethhdr * ethdr = NULL;

  struct iphdr * iph = NULL;

  struct udphdr * udph = NULL;

  u_char * pdata = NULL;

 

  if(NULL == smac || NULL == dmac)

      goto out;

 

  if(NULL == (dev= dev_get_by_name(eth)))

        goto out;

  //ͨ¹ýalloc_skb()À´ÎªÒ»¸öеÄskbÉêÇëÄÚ´æ½á¹¹

  skb = alloc_skb(pkt_len + sizeof(struct iphdr) + sizeof(struct udphdr) + LL_RESERVED_SPACE(dev), GFP_ATOMIC);

 

  if(NULL == skb)

      goto out;

  skb_reserve(skb, LL_RESERVED_SPACE(dev));

 

  skb->dev = dev;

  skb->pkt_type = PACKET_OTHERHOST;

  skb->protocol = __constant_htons(ETH_P_IP);

  skb->ip_summed = CHECKSUM_NONE;

  skb->priority = 0;

 

  skb->nh.iph = (struct iphdr*)skb_put(skb, sizeof(struct iphdr));

  skb->h.uh = (struct udphdr*)skb_put(skb, sizeof(struct udphdr));

 

  pdata = skb_put(skb, pkt_len); //Ô¤Áô¸øÉϲãÓÃÓÚÊý¾ÝÌî³äµÄ½Ó¿Ú

  {

     if(NULL != pkt)

        memcpy(pdata, pkt, pkt_len);

  }

 

  //¡°´ÓÉÏÍùÏ¡±Ìî³äskb½á¹¹£¬ÒÀ´ÎÊÇUDP²ã--IP²ã--MAC²ã

  udph = (struct udphdr *)skb->h.uh;

  memset(udph, 0, sizeof(struct udphdr));

  udph->source = sport;

  udph->dest = dport;

  skb->csum = 0;

  udph->len = htons(sizeof(struct udphdr)+pkt_len);

  udph->check = 0;

  //Ìî³äIP²ã

  iph = (struct iphdr*)skb->nh.iph;

  iph->version = 4;

  iph->ihl = sizeof(struct iphdr)>>2;

  iph->frag_off = 0;

  iph->protocol = IPPROTO_UDP;

  iph->tos = 0;

  iph->daddr = dip;

  iph->saddr = sip;

  iph->ttl = 0x40;

  iph->tot_len = __constant_htons(skb->len);

  iph->check = 0;

  iph->check = ip_fast_csum((unsigned char *)iph,iph->ihl);

 

  skb->csum = skb_checksum(skb, iph->ihl*4, skb->len - iph->ihl * 4, 0);

  udph->check = csum_tcpudp_magic(sip, dip, skb->len - iph->ihl * 4, IPPROTO_UDP, skb->csum);

  //Ìî³äMAC²ã

  skb->mac.raw = skb_push(skb, 14);

  ethdr = (struct ethhdr *)skb->mac.raw;

  memcpy(ethdr->h_dest, dmac, ETH_ALEN);

  memcpy(ethdr->h_source, smac, ETH_ALEN);

  ethdr->h_proto = __constant_htons(ETH_P_IP);

  //µ÷ÓÃdev_queue_xmit()·¢Ëͱ¨ÎÄ

  if(0 > dev_queue_xmit(skb))

      goto out;

 

out:

   if(NULL != skb)

   {

        dev_put (dev);

        kfree_skb (skb);

   }

   return(NF_ACCEPT);

}

       ÉÏÃæÕⲿ·Ö´úÂë¿´²»¶®Ã»¹ØÏµ£¬ÒòΪËüÐèÒª±È½ÏÊìÁ·µÄÄÚºËЭÒéÕ»±à³Ì֪ʶ£¬´ó¼Ò¿ÉÒÔ´ÓÕûÌåÉÏ¶ÔÆäÓиö¸ÐÐԵİÑÎվͿÉÒÔÁË¡£ºóÃæÈç¹ûÓÐʱ¼äÎÒ»áÔÙд¸öTCP/IPÄÚºËЭÒéÕ»·ÖÎöµÄϵÁÐÎÄÕ£¬ËäÈ»CUÉÏÓкܶà´óÅ£ÒѾ­ÔÚдÁË£¬µ«Ã¿¸öÈ˵ÄÊÕ»ñ²»Ò»Ñù£¬ºÍ´ó¼Ò·ÖÏíÒ²ÊÇѧϰµÄÁíÒ»ÖÖÐÎʽ¡£ºÃÁË£¬Ïл°²»¶à˵¡£ÎÒÃÇÕâ¸öhookµÄ×îÖÕ°æ±¾ÔÚ¡° myhook.zip ¡±ÏÂÔØ¡£

       ½ÓÏÂÀ´£¬¼¤¶¯ÈËÐĵÄʱ¿ÌÓÖµ½ÁË£¬ÎÒÃÇÀ´ÑéÖ¤Ò»ÏÂÎÒÃǵÄhookº¯ÊýÊÇ·ñ¿ÉÒÔ°´Ô¤ÆÚÒ»ÑùµØ½øÐй¤×÷¡£±àÒëºÍ¼ÓÔØÁ÷³ÌÈçÇ°ÃæËùÊö¡£ÎÒÃÇΪÉϲãÓ¦ÓòãÍùUDP±¨ÎÄÖÐÌî³äÊý¾ÝÔ¤ÁôÁ˽ӿڣ¬ËùÒÔÎÒÃÇ¿ÉÒÔÒÔÈçϵÄÐÎʽÀ´µ÷ÓÃbuild_and_xmit_udp()½Ó¿Ú£º

build_and_xmit_udp(ETH,SMAC,DMAC,¡±hello¡±,5,in_aton(SIP),in_aton(DIP),htons(SPORT),htons(DPORT));

       Í¨¹ýwireshark×¥°üÀ´ÑéÖ¤Ò»ÏÂÊDz»ÊÇÿÊÕµ½5¸öICMP±¨ÎľÍÍù118.6.24.132µØÖ··¢ËÍÒ»¸öÄÚÈݽöÓС°hello¡±×Ö·û´®µÄUDP±¨ÎÄ£º

       ¾­¹ýÕâôһ·¬¡°¸ÄÔ족£¬ÎÒÃÇ×Ô¶¨ÒåÕâ¸öhookº¯ÊýËãÊÇÓеãÌØÉ«ÁË¡£ÖÁ´ËÎÒÃǽñÌìµÄÄÚÈݾÍÈ«²¿½²ÍêÁË¡£¹À¼ÆÓÐЩÈË¿ÉÄܾõµÃ»¹ÉÙÁ˵ãʲô£¬ÓÐûÓÐÎòÐԱȽϸߵÄͯЬÌá³ö¼¸µãÖÊÒÉÀ´£¿Ã»´í£¬¾ÍÊÇÎÒÃÇÕâ¸öhookÀïÉèÖõÄIPµØÖ·Êǹ̶¨µÄ£¬°üÀ¨MACµØÖ·¡¢Ô´ºÍÄ¿µÄ¶Ë¿ÚÒÔ¼°·¢Ë͵ÄÄÚÈÝ¡£Óû§¿Õ¼äÎÒÃǸù±¾Ã»·¨¶ÔÕâЩÊôÐÔ½øÐвÙ×÷£¬ÖèÈ»¼ä£¬Õâ¸öÄ£¿éµÄ¿É²Ù×÷ÐÔºÍÒ×ÓÃÐÔ´ó´òÕÛ¿Û¡£ÄÇôÎÒÃǵ½µ×ÈçºÎ²ÅÄÜ´ÓÓû§¿Õ¼äÀ´²Ù×÷Õâ¸öÐÂ×¢²áµÄhookÄØ£¿

       Î´Í꣬´ýÐø¡­

·¢±íÆÀÂÛ£º