Aspects of Network Sniffing

 [ a u t h o r ] kay

                    Copyright 1999 kay <kay@phreedom.org>
         Please contact the author and or Phreedom Magazine prior to
                           publication of any kind.

 0. Abstract

 Tazi  statiq  ima  za  cel  da pokave i dwete strani na mrevowite snifferi -
 kakwo sa za sistemnite administratori: kak da gi otkriem, kak da gi sprem; i
 kakwo  za  programista.  Wkljucheni sa primeri za Linux-specifichni funkcii,
 kakto i za PCAP bibliotekata.

 Sydyrvanie:

   1. Network basics
     1.1. Network design, hardware and software
     1.2. Devices and interfaces
     1.3. Preventing and detecting sniffers
   2. Introduction to packet sniffing
     2.1. Example of Linux SOCK_PACKET usage
     2.2. Libpcap example
     2.3. BPF Packet filter programs
     2.4. Loadable kernel modules
   3. Bibliography and additional files


 1. Network basics

 Nqkoi hora biha osporili, che snifferite sa neshto dosta iztyrkano: da, taka
 e. Sled kato razpolagame s asimetrichno kodirashti algoritmi, se predpolaga,
 che  tezi  problemi  sa  resheni.  Wsyshtnost,  wseki  den  hilqdi accounti,
 kreditni karti i druga wavna informaciq "iztichat". Syshto taka sniferite sa
 winagi  polezen  instrument  za otkriwane na problemi w mrevowite protokoli,
 kakto i za sledene na sigurnostta (IDS, Intrusion Detection Systems).


 1.1. Network design, hardware and software

 Nqkoi  osobenosti  na  ustrojstwoto i dizajna na lokalnite kompjutyrni mrevi
 pozwolqwat  da  se  "podslushwa"  komunikaciqta  mevdu  2  stancii  ot treti
 kompjutri, koito sa swyrzani w syshtiq segment. Towa se dylvi na osobenost w
 standarta  IEEE  802.3 CSMA/CD (Carrier Sense Multiple Access with Collision
 Detection)  i  po-specialno  w algorityma za izprashtane, izpolzwan ot NIC's
 (Network  Interface Cards) za izbqgwane na kolizii. Koliziq nastypwa, kogato
 2  stancii  se  opitat  da  predadat ednowremenno danni po mrevata. Tyj kato
 wsichki  izpolzwat  edna  i  syshta  chestotna  lenta, towa wodi do wremenno
 spirane  na  wsichki  komunikacii.  Imenno tozi algoritym w adapterite sledi
 trafika  po  mrevata  i  izchakwa naj-udobniq moment "da se wkljuchi". Nqkoi
 po-stari modeli mrevowi ustrojstwa syshto taka "podslushwat" wsichki paketi,
 minawashti prez mrevata, za da reagirat na Broadcast syobshteniq.

 Towa  wse oshte ne e dostatychno za da move da se podsluswat wsichki wryzki:
 Operacionnata  sistema  na  wsqka  stanciq  wzima  samo  paketite,  koito sa
 prednaznacheni  za  neq i propuska ostanalite. Izkljuchenie prawqt Broadcast
 paketite,  chieto syshtestwuwane e wyzmovno samo w edin segment na lokalnite
 mrevi  (rqdko i w drugi sluchai) poradi imenno tezi osobenosti. Broadcast se
 izprashta kym opredelen adres na mrevata, na kojto reagirat wsichki stancii.
 Towa  se  izpolzwa  za  opredelqne  na  DHCP, BOOTP serveri, i drugi podobni
 uslugi (Smurf ...).


 1.2. Devices and interfaces

 W Unix otdelnite fizicheski i logicheski mrevowi ustrojstwa sa predstaweni s
 taka narechenite interfejsi. Mogat da se razgledat s komandata 'ifconfig' (w
 nowite Linux sistemi i s 'ip'):


 $ /sbin/ifconfig -a
 lo        Link encap:Local Loopback
           inet addr:127.0.0.1  Mask:255.0.0.0
           UP LOOPBACK RUNNING  MTU:3924  Metric:1
           RX packets:249 errors:0 dropped:0 overruns:0 frame:0
           TX packets:249 errors:0 dropped:0 overruns:0 carrier:0
           Collisions:0

 eth0      Link encap:Ethernet  HWaddr 00:AC:3B:71:1D:D0
           inet addr:192.168.0.1  Mask:255.255.255.0
           MULTICAST PROMISC  MTU:1500  Metric:1
           RX packets:5357 errors:0 dropped:0 overruns:0 frame:0
           TX packets:2397 errors:0 dropped:0 overruns:0 carrier:0
           Collisions:0
           Interrupt:12 Base address:0x420

 ppp0      Link encap:Point-to-Point Protocol
           inet addr:192.168.0.100  P-t-P:192.168.1.1  Mask:255.255.255.255
           POINTOPOINT NOARP MULTICAST  MTU:1500  Metric:1
           RX packets:913 errors:1 dropped:0 overruns:0 frame:1
           TX packets:920 errors:0 dropped:0 overruns:0 carrier:0
           Collisions:0

 W  sluchaq  -  Linux sistema s loopback, edin Ethernet i edin PPP interfejs.
 Wivda  se, che eth0 interfejsyt e w promiscuous mode, t.e. poluchawa wsichki
 paketi  ot  mrevata,  dori  i  tezi,  koito ne sa konkretno za dadeniq host.
 Po-dolu shte widite kak move da si naprawite sobstwena takawa programa.


 1.3. Kak da predotwratim snifferi w lokalnata mreva

 Syshtestwuwat harduerni i sofruerni resheniq, koito prawqt po-sigurna cqlata
 mreva. Prawilniqt dizajn i izgravdane na mrevowata topologiq sa predpostawka
 za  izoliranost  na  otdelnite mrevowi segmenti. Izpolzwaneto na Switch-owe,
 kriptirashti Hub-owe i router-i, VPN namalqwat do golqma stepen shansa da se
 podslushwat "sigurni" wryzki.

 L0pth  Heavy  Industries  obqwi  softueren produkt za otkriwane na sniferi w
 lokalna  mreva  (ili  izobshto mrevowi adapteri w promiscuous revim) za NT i
 Unix,  kojto  raboti na bazata na pasiwni priznaci i prowokira snifera da se
 izdade  chrez  spoofnati  paketi.  W BugTraq ima interesna diskusiq po powod
 efektiwnosta  na  AntiSniff, kakto i GPL AntiAntiSniff Sniffer. Velatelno e,
 kogato  si  prowerqwate lokalnata sistema za promiscuous mode interfejsi, da
 polzwate  otdelna  programa,  a  ne  ifconfig,  zashtoto  tq  move  da  byde
 troqnizirana da ne go pokazwa. Wivte lspromisc.c po-nadolu.

 Eto edin primer za zle izgradena lokalna mreva:

           [Server]
              |
  [Bridge]--[Hub]---[Border router]------------  - - - Internet
              |
              |
         [Another Hub]
         / | | | | | /
        .  . . . . .  .

 Po  tozi  nachin  wsichki  stancii  shte  mogat da podslushwat trafika mevdu
 nashiq  i  sysedniq  server, ili pyk e-mail parolata na Joe na drug server w
 Internet.  Trqbwa  da  se  izpolzwat  switch-owe wmesto koncentratori, da se
 razdelqt  mashinite  na  grupi i po wyzmovnost da se obosobqt w VLAN mrevi i
 t.n.  i  t.n.  Pomnete che naj-sigurnite kompjutri sa izkljuchenite. No neka
 ostawim towa za sega, tyj kato tazi statiq ima druga osnowna tema.


 2. Introduction to Libpcap

 Wsqka  operacionna  sistema  predstawq  swoj  sobstwen  metod  za  dostyp do
 naj-niskoto  niwo na mrevata: Berkley Packet Filter pri BSD, Char device pri
 Solaris, specialen tip socket pri Linux i t.n. Towa prawi trudno syzdawaneto
 na  portable  programi,  koito  izpolzwat  tezi  funkcii i se kompilirat bez
 promqna  na  razlichni  tipowe Unix. Bibliotekata PCAP (ot Packet Capture) e
 wsyshtnost  obsht  interfejs  kym syotwetnite funkcii ot nisko niwo za nqkoq
 operacionna  sistema,  predostawqjki  na  programista  mnogo  dopylnitelni i
 polezni  wyzmovnosti,  kato  dump na paketikte wyw fajl, prochitane ot fajl,
 BPF filtri i prawila za poluchawane samo na opredeleni paketi, informaciq za
 mrevata/hosta.  Zatowa,  ako  poglednete  nqkoj arhiw s publichni eksploiti,
 shte  namerite  nqkolko  razlichni  sniferi,  raboteshti  samo na opredelena
 operacionna sistema.

 Nqkolko  dumi  za  izgravdaneto  na  samiq  sniffer. Nemislimo e da se pishe
 paketen snifer, bez da se poznawat dostatychno dobre protokolite i paketite,
 na  koito move da se natyknem. Tyj kato osnownata cel na powecheto sniferi e
 podlushwane na TCP wryzki w lokalna mreva, trqbwa da se zapochne ot Ethernet
 ramkata,  prez IPv4 (ili v6, no za sega towa ne e chak tolkowa neobhodimo) i
 samiq  TCP hedyr. Tyj kato ne poluchawame dannite kato potok, a razdeleni na
 otdelni  paketi,  trqbwa  da  si sglobim neshto kato mini-TCP/IP-stek, za da
 movem  da  prosledim otdelnite logicheski TCP sesii (w qdroto tazi rabota se
 wyrshi ot TCP multiplexer).

  struct ethhdr eth;
  struct iphdr ip;
  struct tcphdr tcp;
  [... data ...]

 Razbira  se,  movem  da  podlsushwame ICMP, IGMP, UDP i wsichko drugo, koeto
 move  da  se  prekara  wyrhu  IPv4,  stiga  da  movem korektrno da razoznaem
 protokola.

 #define MAC_LEN 6

 struct ethhdr {
         u_char dst_addr[MAC_LEN];
         u_char src_addr[MAC_LEN];
         u_short protocol;
 };

 struct iphdr {
         u_char ver_ihl;
         u_char tos;
         u_short total_len;
         u_short id;
         u_short frag_offset;
         u_char ttl;
         u_char protocol;
         u_short checksum;
         u_long src_addr;
         u_long dst_addr;
 };

 struct tcphdr {
         u_short src_port;
         u_short dst_port;
         u_long sequence;
         u_long acq_seq;
         u_short flags;
         u_short window;
         u_short checksum;
         u_short urg_ptr;
 };


 Towa  e  priblizitelnata shema na dejswie (algoritym) na snifyra w psewdokod
 (mrazq blokowi shemi):

 while (we_want_to_sniff) {
         packet = read_raw_packet();

         if (starts_new_connection(packet) && port_is_interesting(packet))
                 add_to_stack(connection(packet));

         if (packet_is_part_of_tracked_connection(packet)) {
                 log(packet);

                 if (we_have_logged_enough(connection(packet)) ||
                     packet_closes_connection(packet)))
                         remove_from_stack(connection(packet));
         }
 }


 2.1. Example of Linux SOCK_PACKET usage

 Za  dostyp do link layer-a na opredelen interfejs Linux predostawq specialen
 tip  socket  -  SOCK_PACKET,  pri kojto movem da poluchim/izpratim ne prosto
 IPv4  +  ramka,  a  da  izgradim  paketa zapochwajki Ethernet, PPP, SLIP ili
 kakywto  drug  protokol  polzwame za wryzka po syotwetniq interfejs (t.e. ot
 Link Layer).

 Za da poluchim wsichki interesuwashti ni paketi (wkljuchitelno i tezi, koito
 ne  sa za nas), trqbwa syotwetniqt interfejs da e s wdignat flag promiscuous
 (IFF_PROMISC). W Linux towa stawa chrez strukturata ifreq:

 struct ifreq
 {
 #define IFNAMSIZ        16
         union
         {
                 char    ifrn_name[IFNAMSIZ];
         } ifr_ifrn;

         union {
                 struct  sockaddr ifru_addr;
                 struct  sockaddr ifru_dstaddr;
                 struct  sockaddr ifru_broadaddr;
                 struct  sockaddr ifru_netmask;
                 struct  sockaddr ifru_hwaddr;
                 short   ifru_flags;
                 int     ifru_ivalue;
                 int     ifru_mtu;
                 struct  ifmap ifru_map;
                 char    ifru_slave[IFNAMSIZ];
                 char    ifru_newname[IFNAMSIZ];
                 char *  ifru_data;
         } ifr_ifru;
 };

 #define  ifr_name       ifr_ifrn.ifrn_name      /* interface name       */
 #define  ifr_hwaddr     ifr_ifru.ifru_hwaddr    /* MAC address          */
 #define  ifr_addr       ifr_ifru.ifru_addr      /* address              */
 #define  ifr_dstaddr    ifr_ifru.ifru_dstaddr   /* other end of p-p lnk */
 #define  ifr_broadaddr  ifr_ifru.ifru_broadaddr /* broadcast address    */
 #define  ifr_netmask    ifr_ifru.ifru_netmask   /* interface net mask   */
 #define  ifr_flags      ifr_ifru.ifru_flags     /* flags                */
 #define  ifr_metric     ifr_ifru.ifru_ivalue    /* metric               */
 #define  ifr_mtu        ifr_ifru.ifru_mtu       /* mtu                  */
 #define  ifr_map        ifr_ifru.ifru_map       /* device map           */
 #define  ifr_slave      ifr_ifru.ifru_slave     /* slave device         */
 #define  ifr_data       ifr_ifru.ifru_data      /* for use by interface */
 #define  ifr_ifindex    ifr_ifru.ifru_ivalue    /* interface index      */
 #define  ifr_bandwidth  ifr_ifru.ifru_ivalue    /* link bandwidth       */
 #define  ifr_qlen       ifr_ifru.ifru_ivalue    /* Queue length         */
 #define  ifr_newname    ifr_ifru.ifru_newname   /* New name             */


 i chrez SIOCGIFFLAGS (Socket I/O Control Get Interface Flags) i SIOCSIFFLAGS
 (Socket  I/O  Control  Set Interface Flags) ioctl() izwikwaniq. Edinstweniqt
 obsht  parametyr  za  wsichki izwikwaniq e ifr_name, ostanalite se izpolzwat
 spored   syotwetnata  operaciq.  Informaciq  za  konfiguraciqta  na  wsichki
 nalichni  interfejsi  move  da  se wzeme chrez SIOCGIFCONF, kato se izpolzwa
 strukturata ifconf:

 struct ifconf
 {
         int     ifc_len;
         union
         {
                 char *                  ifcu_buf;
                 struct  ifreq           *ifcu_req;
         } ifc_ifcu;
 };

 #define ifc_buf ifc_ifcu.ifcu_buf
 #define ifc_req ifc_ifcu.ifcu_req


 W  ifc_len  se  podawa  razmer  na bufera ifcu_buf, kojto shte poluchi ifreq
 strukturite  za  wsichki  interfejsi.  Pri nedostatychno golqm bufer kernela
 wryshta informaciq samo kolkoto buferyt move da prieme, bez da dawa greshka.
 Stojnostta  na  ifc_len  se  promenq  na  syotwetniq  broj.  Wsichko  towa e
 neobhodimo,  za  da  movem  da  wzemem  spisyka  s podhodqshti interfejsi za
 podslushwane,  w  sluchaj,  che nikoj ot standartnite ne syshtestwuwa, oshte
 poweche  che  ne  e  zadylvitelno  wseki  ot  tqh  da  otgowqrq na harduerno
 ustrojstwo  -  kernel  modul move da syzdade specialen interfejs za VPN, pri
 koeto movem da podslushwame dannite predi oshte da sa kodirani. Za powecheto
 interfejsi  obache,  wkljuchitelno  i pri podslushwane prez libpcap, move da
 ima  dopylnitelni  danni  kym ramkata na paketa, chesto razlichni za ednakwi
 interfejsi w razlichni operacionni sistemi.


 Kogato  iskame  da  podslushwame  opredelen  interfejs  se  izpolzwa  bind()
 funkciqta, po syshtiq nachin, kakto i pri normalnite soketi.

 struct sockaddr {
         unsigned short sa_family;
         char sa_data[14];
 };

 w sa_data se zadawa kato null-terminated string imeto na interfejsa.


 -<sockpacket.c>---------------------------------------------------------
 /* Copyright (C) 1999 kay@phreedom.org; All rights reserved */

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
 #include <netinet/ip.h>
 #include <netinet/if_ether.h>
 #include <linux/if.h>

 #include "pdump.h"


 int
 main(int argc, char **argv)
 {
    struct ifreq ifr;          /* Linux interface request control structure */
    short ifr_flags_orig;                     /* Initial flags if interface */
    int sockfd;                                        /* Socket descriptor */
    u_char sp[2000];
    int err;

    printf("Example of non-portable packet sniffer for Linux/n");

    /* We want only Ethernet frames containing IP data */
    sockfd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_IP));
    if (sockfd < 0) {
       perror("socket");
       exit(1);
    }

    /* Make the interface promiscuous */
    strcpy(ifr.ifr_name, INTERFACE);
    err = ioctl(sockfd, SIOCGIFFLAGS, &ifr);
    if (err < 0) {
       perror("SIOCGIFFLAGS");
       exit(1);
    }
    ifr_flags_orig = ifr.ifr_flags;
    ifr.ifr_flags |= IFF_PROMISC;
    err = ioctl(sockfd, SIOCSIFFLAGS, &ifr);
    if (err < 0) {
       perror("SIOCSIFFLAGS");
       exit(1);
    }

    /* Read one packet */
    err = read(sockfd, &sp, sizeof(sp));
    if (err < 0) {
       perror("read");
       exit(0);
    }

    /* Dump what we cought */
    printf("Dumping %i bytes:/n", err);
    dump_eth((struct ethhdr *) &sp);
    dump_ip((struct iphdr *) &sp+14L);
    dump_hex((void *) &sp, err, 2, 16);
    dump_ascii((void *) &sp, err, 16);
    printf("/n/n");

    /* Restore original interface flags */
    ifr.ifr_flags = ifr_flags_orig;
    if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
       perror("SIOCSIFFLAGS");
       exit(1);
    }
    close(sockfd);

    return EXIT_SUCCESS;
 }

 /* eof */
 -</sockpacket.c>--------------------------------------------------------

 -<getifconf.c>----------------------------------------------------------
 /* Copyright 1999 Kay <kay@phreedom.org>. All rights Reserved */

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>

 int main()
 {
         struct ifconf ifc;
         struct ifreq ifr_x[20];
         int sockfd, err;

         sockfd = socket(PF_PACKET, SOCK_PACKET, 0);
         if (sockfd < 0) {
                 perror("socket");
                 exit(1);
         }

         ifc.ifc_len = 20 * sizeof(struct ifreq);
         ifc.ifc_req = ifr_x;
         err = ioctl(sockfd, SIOCGIFCONF, &ifc);
         perror("ioctl");
         printf("retrieved info for %i interface(s)/n",
                         ifc.ifc_len / sizeof(struct ifreq));
         for (err = 0; err < ifc.ifc_len / sizeof(struct ifreq); err++)
                 printf("%s/n", ifr_x[err].ifr_name);
         return EXIT_SUCCESS;
 }

 /* eof */
 -</getifconf.c>---------------------------------------------------------

 

 2.2. Libpcap primer

 Slednata  programa  wyrshi  absolutno  syshtite funkcii kato sockpacket.c, i
 wsichko e poweche ot ochewidno kak raboti.


 -<libpcap.c>------------------------------------------------------------
 /* Portable packet sniffer example - needs libpcap in order to compile
  * Copyright (c) 1999 kay@phreedom.org; All rights reserved */

 #include <stdio.h>
 #include <stdlib.h>
 #include <pcap.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
 #include <netinet/ether.h>

 #include "pdump.h"


 int main(int argc, char **argv)
 {
    pcap_t *pcap;                /* PCAP descriptor */
    u_char *packet;              /* Our newly captured packet */
    struct pcap_pkthdr pkthdr;   /* PCAP packet information structure */

    printf("Example of portable packet sniffer using Libpcap/n");

    /* Obtain a descriptor for interface, capture no more than
     * 8192 octets, set interface to promiscuous mode, 1000 miliseconds
     * read timeout, No buffer for error messages */
    pcap = pcap_open_live(INTERFACE, 8192, 1, 1000, NULL);
    if (pcap == NULL) {
       perror("pcap_open_live");
       exit(EXIT_FAILURE);
    }

    /* Get the next packet from the queue */
    packet = (u_char *) pcap_next(pcap, &pkthdr);

    if (packet != NULL) {
       packet += OFFSET;
       /* Dump the packet in various forms */
       printf("Dumping %i bytes:/n", pkthdr.caplen);
       dump_eth((struct ethhdr *) packet);
       dump_ip((struct iphdr *) packet);
       dump_hex((void *) packet, pkthdr.caplen, 2, 16);
       dump_ascii((void *) packet, pkthdr.caplen, 16);
       printf("/n/n");
    } else {
       pcap_perror(pcap, "pcap_next returned NULL");
    }

    /* Enough for now ... */
    pcap_close(pcap);

    return EXIT_SUCCESS;
 }

 /* eof */
 -</libpcap.c>-----------------------------------------------------------

 const u_char *pcap_next(pcap_t *, struct pcap_pkthdr *);

 Ochewidno osnownata rabota se wyrshi ot funkciqta pcap_next(), koqto wryshta
 ukazatel  kym  sledwashtiq  paket  ot  opashkata.  Sled  towa  dejstwieto na
 sniffera  e  napylno  analogichno  na  predishniq  primer.  Razbira se, tezi
 primeri  w nikakyw sluchaj ne sa izpolzwaemi w tozi si wid, no sa edna dobra
 osnowa.


 2.3. BPF Packet filter programs

 Chrez  Berkeley  Packet Filter move da se zadade programa, koqto da filtrira
 whodqshtite  paketi  po  opredeleni  priznaci.  Takawa programa se systoi ot
 masiw  BPF  instrukcii "izpylnqwani" na wirtualna mashina. Intrukciite dosta
 napomnqt  asembleren  ezik.  Towa  e  izkljuchitelno  moshten  mehanizym, no
 syzdawaneto  na  tezi programi chesto e prekaleno slovno, za da si struwa da
 gi  pishem.  Sledniq  primer  ot man-stranicata pokazwa programa, izbirashta
 samo IP paketi mevdu 128.3.112.15 i 128.3.112.35:

 struct bpf_insn insns[] = {
         BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K,
         ETHERTYPE_IP, 0, 8), BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 26),
         BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x8003700f, 0, 2),
         BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 30), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K,
         0x80037023, 3, 4), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x80037023, 0, 3),
         BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 30), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K,
         0x8003700f, 0, 1), BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
         BPF_STMT(BPF_RET+BPF_K, 0),
 };

 Za  towa  (kakto  i  pri  normalnite ezici), w LBL e syzdaden ezik ot wisoko
 niwo, kojto se "kompilira" do BPF-instrukcii. Pylnata dokumentaciq se namira
 w man-stranicata na tcpdump(8). Neka poglednem sledniq primer:

 -<pfilter.c>------------------------------------------------------------
 /* Packet filter example
  * Copyright (c) 1999 kay@phreedom.org; All rights reserved */

 #include <stdio.h>
 #include <stdlib.h>
 #include <pcap.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
 #include <netinet/ether.h>

 #include "pdump.h"


 int main(int argc, char **argv)
 {
    pcap_t *pcap;                /* PCAP descriptor */
    u_char *packet;              /* Our newly captured packet */
    struct pcap_pkthdr pkthdr;   /* PCAP packet information structure */
    struct bpf_program fp;       /* Structure to hold the compiled prog */
    char pfprogram[] = "ip host 128.3.112.15 and 128.3.112.35";

    printf("Example of portable packet sniffer using Libpcap/n");

    /* Obtain a descriptor for interface, capture no more than
     * 8192 octets, set interface to promiscuous mode, 1000 miliseconds
     * read timeout, No buffer for error messages */
    pcap = pcap_open_live(INTERFACE, 8192, 1, 1000, NULL);
    if (pcap == NULL) {
       perror("pcap_open_live");
       exit(EXIT_FAILURE);
    }

    /* Compile and set the filter program */
    if (pcap_compile(pcap, &fp, pfprogram, 1, 0x0) == -1) {
       pcap_perror(pcap, "pcap_compile");
       exit(EXIT_FAILURE);
    }
    if (pcap_setfilter(pcap, &fp) == -1) {
       pcap_perror(pcap, "pcap_setfilter");
       exit(EXIT_FAILURE);
    }

    /* Get the next packet from the queue */
    packet = (u_char *) pcap_next(pcap, &pkthdr);

    if (packet) {
       /* Dump the packet in various forms */
       printf("Dumping %u bytes:/n", pkthdr.caplen);
       packet += OFFSET;
       dump_eth((struct ethhdr *) packet);
       dump_ip((struct iphdr *) packet);
       dump_hex((void *) packet, pkthdr.caplen, 2, 16);
       dump_ascii((void *) packet, pkthdr.caplen, 16);
       printf("/n/n");
    } else {
       printf("Packet not captured because of filter/n");
    }

    /* Enough for now ... */
    pcap_close(pcap);

    return EXIT_SUCCESS;
 }

 /* eof */
 -</pfilter.c>-----------------------------------------------------------

 Izrazyt  "ip  host 128.3.112.15 and 128.3.112.35" se prewevda w BPF programa
 ot   pcap_compile()  i  togawa  se  prikachwa  kym  PCAP  descriptora  chrez
 pcap_setfilter(). Dosta po-lesno ot predniq primer, nali?

 Linux  Socket  Filter (ili LSF) e Linux-wersiqta na BPF, s nqkoi dopylneniq.
 Imenno:  toj  pozwolqwa  na  potrebitelski  programi da prikachat filtri kym
 tehnite  soketi i po tozi nachin da filtrirat wryzkite si; syshto taka toj e
 po-lesen  za  polzwane  po otnoshenie na "prikachwaneto" si. Samite filtyrni
 programi sa napylno identichni.


 2.4. Loadable kernel modules

 Loadable  kernel  modules  (LKM)  sa  bili  syzdadeni,  za  da se predostawi
 mehanizym  za  dinamichno dobawqne na nowi funkcii w qdroto na operacionnata
 sistema, bez da e nuven reboot ili drug wid prekyswane na normalnata rabota.
 LKM,  koito  rabotqt  w ring 0 pri powecheto OS, estestweno imat prawa wyrhu
 cqlata  pamet i mogat da promenqt wytreshni strukturi na kernel-a kakto i da
 se  skriqt ot ochite na administratora izpolzwajki razlichni tehniki. Towa e
 dosta dobyr nachin za trojanizirane na crack-nati sistemi. Kokretno za Linux
 kernel  interfejsite i pisaneto na moduli sa mnogo dobre opisani - za obshto
 wywedenie  poglednete  "The Linux Kernel" i "Linux Kernel Hacker's Guide" ot
 Linux Documentation Project. Temata za LKM e podrobno opisana wyw Phrack 55.


 3. Bibliography and additional files

 Man pages: pcap(3), setsockopt(2), bpf(7)
 RFC's: 791, 792, 793, 894
 IEEE 802 (esp. 802.3)
 UTSL: Linux kernel 2.2.12, libpcap 0.4
 Libpcap: ftp://ftp.ee.lbl.gov
 Linux Documentation Project: http://metalab.unc.edu/LDP
 Phrack Magazine: http://www.phrack.com


 W  primerite  za  SOCK_PACKET  i  PCAP  sa  izpolzwani funkcii ot pdump.c za
 pokazwane    na    HEX/ASCII/IP/Ethernet    danni/strukturi   na   terminal.
 Linux-specifichnite  primeri  za  izprobwani na Debian GNU/Linux 2.1 (kernel
 2.0.36  glibc  2.0.7),  Debian  GNU/Linux  2.2  (kernel 2.2.12 glibc 2.1.2).
 PCAP-primerite sa izprobwani na Debian GNU/Linux 2.2 + libpcap 0.4 i OpenBSD
 2.4 GENERIC, libpcap 0.4.


 -<pdump.h>--------------------------------------------------------------
 /* Packet dumping routines, Copyright (c) 1999 Kay <kay@PHREEDOM.ORG> */

 void dump_eth(struct ethhdr *);
 void dump_ip(struct iphdr *);
 void dump_hex(void *, u_long, u_long, u_long);
 void dump_ascii(void *, u_long, u_long);
 -</pdump.h>-------------------------------------------------------------

 -<pdump.c>--------------------------------------------------------------
 /* Packet dumping routines, Copyright (c) 1999 Kay <kay@PHREEDOM.ORG> */

 #include <stdio.h>
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
 #include <netinet/ether.h>

 void dump_eth(struct ethhdr *eth)
 {
         int cnt;

         printf("/th_dest   =");
         for (cnt = 0; cnt < ETH_ALEN; cnt++)
                 printf(" %X", eth->h_dest[cnt]);
         printf(";/n/th_source =");
         for (cnt = 0; cnt < ETH_ALEN; cnt++)
                 printf(" %X", eth->h_source[cnt]);
         printf(";/n/th_proto  = %X;/n", eth->h_proto);
         fflush(stdout);
 }

 void dump_ip(struct iphdr *ip)
 {
         struct protoent *pp;
         struct in_addr ia;

         printf("/tihl      = %X;/n", ip->ihl);
         printf("/tversion  = %X;/n", ip->version);
         printf("/ttos      = %X;/n", ip->tos);
         printf("/ttot_len  = %X;/n", ip->tot_len);
         printf("/tid       = %X;/n", ip->id);
         printf("/tfrag_off = %X;/n", ip->frag_off);
         printf("/tttl      = %X;/n", ip->ttl);

         printf("/tprotocol = %X;", ip->protocol);
         pp = getprotobynumber(ip->protocol);
         if (pp == NULL) printf("/n"), perror(NULL);
         else printf("/t(%s)/n", pp->p_name);

         printf("/tcheck    = %X;/n", ip->check);
         ia.s_addr = ip->saddr;
         printf("/tsaddr    = %X;/t(%s)/n", ip->saddr, inet_ntoa(ia));
         ia.s_addr = ip->daddr;
         printf("/tdaddr    = %X;/t(%s)/n", ip->daddr, inet_ntoa(ia));
         fflush(stdout);
 }


 /* Its obvious: *data, how many octets, interval of spaces,
    interval of '/n'-s */
 void dump_hex(void *bare, u_long octets, u_long int_sp, u_long int_nl)
 {
         u_long s;
         u_long spc=0, nlc=0;
         char *buf = (char *) bare;

         for (s=0; s<octets; s++) {
                 if ((u_char)buf[s]<0x10) printf("0");
                 printf("%X", (u_char)buf[s]);
                 if (++spc==int_sp) printf(" "), spc=0;
                 if (++nlc==int_nl) printf("/n"), nlc=0;
                 fflush(stdout);
         }
 }

 int is_printable(char c)
 {
         if ((c >= '1')&&(c <= '0')) return 1;
         if ((c >= 'A')&&(c <= 'Z')) return 1;
         if ((c >= 'a')&&(c <= 'z')) return 1;
         return 0;
 }

 void dump_ascii(void *bare, u_long octets, u_long int_nl)
 {
         u_long s;
         u_long nlc=0;
         char *buf = (char *) bare;

         for(s=0; s<octets; s++) {
                 printf("%c", is_printable(buf[s])?buf[s]:'.');
                 if (++nlc==int_nl) printf("/n"), nlc=0;
                 fflush(stdout);
         }
 }

 /* eof */
 -</pdump.c>-------------------------------------------------------------

 -<Makefile>-------------------------------------------------------------
 # Makefile for examples (c) 1999 kay <kay@phreedom.org>
 # Edit to suit your system.
 # In case of problems when compiling on Linux 2.0 systems, try
 # replacing AF_PACKET with AF_INET.

 # Set interface to sniff. Some common offsets:
 # Ethernet (eth0, le0)        offset 0
 # Loopback (lo, lo0, ...)     offset 4
 # PPP link (ppp0, ppp1, ...)  offset 0
 DEFS=-DINTERFACE=/"lo/" -DOFFSET=4

 CC=cc
 RM=rm -f
 CFLAGS=-O2 -Wall -pipe $(DEFS)
 LIBPCAP=-lpcap

 default:
         @echo "Type one of:"
         @echo "        make pcap    -- build only PCAP examples"
         @echo "        make all     -- build PCAP and Linux-specific examples"

 all:    libpcap pfilter sockpacket lspromisc getifconf

 pcap:   libpcap pfilter

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

 sockpacket:     pdump.o sockpacket.o
         $(CC) $(CFLAGS) -o sockpacket sockpacket.o pdump.o

 pfilter:        pdump.o pfilter.o
         $(CC) $(CFLAGS) -o pfilter pdump.o pfilter.o $(LIBPCAP)

 libpcap:        libpcap.o pdump.o
         $(CC) $(CFLAGS) -o libpcap libpcap.o pdump.o $(LIBPCAP)

 getifconf:      getifconf.c
         $(CC) $(CFLAGS) -o getifconf getifconf.c

 lspromisc:      lspromisc.c
         $(CC) $(CFLAGS) -o lspromisc lspromisc.c

 clean:
         $(RM) pdump.o sockpacket.o sockpacket libpcap.o /
         libpcap getifconf lspromisc pfilter pfilter.o
 -</Makefile>------------------------------------------------------------

 -<lspromisc.c>----------------------------------------------------------
 /* Copyright 1999 kay@phreedom.org. All rights Reserved */

 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <linux/if.h>

 int main()
 {
         struct ifconf ifc;
         struct ifreq ifr_x[50];
         int sockfd, err, i;

         sockfd = socket(PF_PACKET, SOCK_PACKET, 0);
         if (sockfd < 0) {
                 perror("socket");
                 exit(1);
         }

         ifc.ifc_len = 50 * sizeof(struct ifreq);
         ifc.ifc_req = ifr_x;
         err = ioctl(sockfd, SIOCGIFCONF, &ifc);
         if (err == -1) return EXIT_FAILURE;
         for (i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++) {
                 err = ioctl(sockfd, SIOCGIFFLAGS, &ifr_x[i]);
                 if (err == -1) perror("SIOCGIFFLAGS: ");
                 else if(ifr_x[i].ifr_flags & IFF_PROMISC)
                         printf("Interface %s is promiscuous/n",
                                ifr_x[i].ifr_name);
         }
         return EXIT_SUCCESS;
 }

 /* eof */
 -</lspromisc.c>---------------------------------------------------------

 >> EOA <<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值