· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Docbook Sgml/Libpcap-KLDP

Libpcap »ç¿ëÇϱâ

Libpcap »ç¿ëÇϱâ

³ë±¤¹Î

           
        

libpcapÀÇ Á¤ÀÇ¿Í »ç¿ë¹ý, ÀÀ¿ë µîÀ» Á¦½ÃÇÑ´Ù.

고친 과정
고침 0.42002-01-01고친이 Kwang-Min Noh
Text ¹®¼­¸¦ DocBookÀ¸·Î ¼öÁ¤ ¹× ÀÀ¿ë ºÎºÐ Ãß°¡

1. Libpcap(Portable Packet Capturing Library)

ÆÐŶÀ» ĸÃÄÇϱâ À§ÇÑ µµ±¸·Î´Â BPF(Berkeley Packet Filter), DLPI, NIT, SNOOP, SNIT, SOCK_PACKET, LSF(Linux Socket Filter), drainµî °¢ ¿î¿µÃ¼Á¦º°·Î ´Ù¾çÇÑ µµ±¸°¡ ÀÖ´Ù. ÇÏÁö¸¸ ¿©·¯ºÐÀÌ ¿î¿µÃ¼Á¦º°·Î ÆÐŶÀ» ĸÃÄÇϱâ À§ÇÑ À§ÇÑ Äڵ带 º°µµ·Î ±¸¼ºÇØ¾ß ÇÑ´Ù¸é ½ÃÀÛÇϱ⵵ Àü¿¡ Æ÷±âÇÒÁöµµ ¸ð¸¥´Ù. ÇÏÁö¸¸ ÀÌ ¸ðµç µµ±¸µéÀ» ¼ö¿ëÇÏ´Â PortableÇÑ API°¡ Àִµ¥ ÀÌ°ÍÀÌ ¹Ù·Î libpcapÀÌ´Ù.

¶óÀ̺귯¸® »ç¿ëÀÚ´Â ¿î¿µÃ¼Á¦ÀÇ °¢±â ´Ù¸¥ datalink·ÎÀÇ Á¢±Ù ¹æ¹ý¿¡ »ó°ü¾øÀÌ libpcapÀ» ÀÌ¿ëÇÏ¿© ¼Ò±âÀÇ ¸ñÀûÀ» ´Þ¼ºÇÒ ¼ö ÀÖ´Ù. libpcapÀ» ÀÌ¿ëÇÑ ´ëÇ¥ÀûÀÎ ÅøÀÌ ¹Ù·Î tcpdumpÀÌ´Ù.


2. ÆÐŶÀ» ĸÃÄÇϱâ À§ÇÑ libpcapÀÇ fuction

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

        if (device == NULL ) {
            if ( (device = pcap_lookupdev(ebuf) ) == NULL) {
                perror(ebuf);           
                exit(-1);
            }
        }
        
        pd = pcap_open_live(device, snaplen, PROMISCUOUS, 1000, ebuf);
        if(pd == NULL) {
            perror(ebuf);          
            exit(-1);
        }
        
        i = pcap_snapshot(pd);
        if(snaplen < i) {
            perror(ebuf);                            
            exit(-1);
        }
        
        if(pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
            perror(ebuf);
            exit(-1);
        }
        
        setuid(getuid());
        
        if(pcap_compile(pd, &fcode, filter_rule, 0, netmask) < 0) {
            perror(ebuf);
            exit(-1);
        }
        
        if(pcap_setfilter(pd, &fcode) < 0) {
            perror(ebuf);
            exit(-1);
        }
        
        fflush(stderr);
        
        printer = lookup_printer(pcap_datalink(pd));
        pcap_userdata = 0;
        
        if(pcap_loop(pd, packetcnt, printer, pcap_userdata) < 0) {
            perror("pcap_loop error");
            exit(-1);
        }
        
        pcap_close(pd);
		exit(0);
	}
    


2.1. pcap_lookupdev()

device = pcap_lookupdev(ebuf);

³×Æ®¿÷ µð¹ÙÀ̽º¸¦ °¡Á®¿À´Â ÇÔ¼öÀÔ´Ï´Ù. ÆÐŶÀ» ÀâÀ¸·Á¸é ³×Æ®¿÷ µð¹ÙÀ̽º¸¦ ÁöÁ¤ÇØ¾ß °ÚÁÒ? °¡´ÉÇÑ ´ÙºñÀ̽ºÁß °¡Àå ¹øÈ£°¡ ³·Àº µð¹ÙÀ̽º¸¦ °¡Á®¿À°Ô µË´Ï´Ù. ¸®´ª½º¶ó¸é eth0ÀÌ°ÚÁÒ... ´Ù¸¥ µð¹ÙÀ̽º¸¦ ÅëÇØ ÆÐŶÀ» ĸÃÄÇÏ·Á¸é ÀÌ ÇÔ¼ö¸¦ »ç¿ëÇÏÁö ¾Ê°í ÇÁ·Î±×·¥ÀÇ ÀÔ·ÂÀ¸·Î µð¹ÙÀ̽º¸íÀ» °¡Á®¿À¸é µË´Ï´Ù.


2.2. pcap_open_live()

pd = pcap_open_live(device, snaplen, PROMISCUOUS, 1000, ebuf);

À§ ÇÔ¼ö´Â ½ÇÁ¦ ±â±â¸¦ ¿­¾îÁÖ´Â ±â´ÉÀ» ÇÏ´Â °ÍÀ¸·Î snaplen´Â ÆÐŶ´ç ÀúÀåÇÒ ¹ÙÀ̽º ¼ö, ½ÇÁ¦ datalink°èÃþºÎÅÍ ÆÐŶÀÇ Å©±â¸¦ °è»êÇÏ¿© ¿øÇÏ´Â ºÎºÐ¸¸À» ¾ò¾î¿À¸é µÇ´Â °ÍÀÔ´Ï´Ù. Çì´õÁ¤º¸¸¸À» º¸°í½ÍÀºµ¥ ¾µµ¥¾øÀÌ µ¥ÀÌŸ±îÁö ¹ÞÀ» ÇÊ¿ä´Â ¾ø°ÚÁÒ. µ¥ÀÌÅͱîÁö º¸°í½ÍÀ¸¸é snaplen¸¦ Å©°Ô ÇÏ¸é µË´Ï´Ù. PROMISCUOUS´Â 1ÀÌ¸ç ³×Æ®¿÷ µð¹ÙÀ̽º¿¡ ¿À´Â ¸ðµç ÆÐŶÀ» ¹Þ°Ú´Ù´Â ÀǹÌÀÔ´Ï´Ù. ÀÌ ¸ðµå¸¦ ÀÚ¼¼ÇÏ°Ô ¼³¸íÇϸé EthernetÀº ¸ðµç ÆÐŶÀÌ broadcastingµÇ¸ç ÀÏ´Ü ¸ðµç ³×Æ®¿÷ µð¹ÙÀ̽º´Â µ¿ÀÏ ³×Æ®¿÷³»ÀÇ ´Ù¸¥ È£½ºÆ®ÀÇ ÆÐŶµµ ÀÏ´Ü Á¢ÇÏ°Ô µË´Ï´Ù. ±×·¯³ª, ³×Æ®¿÷ µð¹ÙÀ̽º´Â ±âº»ÀûÀ¸·Î ÀÚ½ÅÀÇ ÆÐŶ¸¸À» ¹Þ°Ô²û µÇ¾îÀÖ½À´Ï´Ù. ±×·¯¹Ç·Î ´Ù¸¥ È£½ºÆ®ÀÇ ÆÐŶÀº ¹ö¸®°Ô µÇ´Â °ÍÀÔ´Ï´Ù. ±×·¯³ª promiscuous¸ðµå·Î µð¹ÙÀ̽º ¸ðµå¸¦ ¹Ù²Ù°Ô µÇ¸é ¸ðµç ÆÐŶÀ» ¹Þ¾ÆµéÀÌ°Ô µÇ´Â °ÍÀÔ´Ï´Ù. ¸ðµç ³×Æ®¿öÅ© ¸ð´ÏÅ͸µ ÇÁ·Î±×·¥µéÀº ¸ðµÎ ÀÌ ¸ðµå¸¦ »ç¿ëÇÏ°Ô µË´Ï´Ù. ¼¼ ¹ø° ÀÎÀÚ´Â ÆÐŶÀÌ ¹öÆÛ·Î Àü´ÞµÉ ¶§ ¹Ù·Î Àü´ÞµÇ´Â °ÍÀÌ ¾Æ´Ï¶ó À§¿¡¼­ ¸í½ÃÇÑ ½Ã°£À» ³Ñ°åÀ» ¶§³ª ¹öÆÛ°¡ ´Ù ä¿öÁ³À» ¶§ ÀÀ¿ëÇÁ·Î±×·¥À¸·Î Àü´ÞµÇ´Â °ÍÀÔ´Ï´Ù.


2.3. pcap_lookupnet()

pcap_lookupnet(device, &localnet, &netmask, ebuf)

¿­·ÁÁø ÆÐŶ ĸÃÄ µð¹ÙÀ̽º¿¡ ³×Æ®¿÷ ÁÖ¼Ò¿Í ¼­ºê³Ý ¸¶½ºÅ©¸¦ ³Ñ°ÜÁÝ´Ï´Ù.


2.4. pcap_compile()

pcap_compile(pd, &fcode, filter_rule, 0, netmask)

Á¤ÇØÁø ÇÊÅÍ·ê¿¡ ÀÇÇØ ÇÊÅÍ ÇÁ·Î±×·¥À» ÄÄÆÄÀÏÇÏ°Ô µÇ´Âµ¥ ¿ì¸®°¡ ¿øÇÏ´Â ÆÐŶÀº ÇÊÅÍ·êÀ» ÁÖ¾î¾ß¸¸ ¿øÇÏ´Â ÆÐŶ¸¸À» ¾òÀ» ¼ö ÀÖ½À´Ï´Ù. ½ÇÁ¦ tcpdump¿¡¼­ »ç¿ëÇÏ´Â ÇÊÅÍ·êÀÌ ¿©±â¿¡¼­ ¾²ÀÔ´Ï´Ù. ¿¹¸¦ µé¸é "tcp port 80" ÀÔ´Ï´Ù.

ÀÚ¼¼ÇÑ ÇÊÅÍ·ê¿¡ ´ëÇÑ ¼³¸íÀº tcpdumpÀÇ ¸Þ´º¾óÀ» º¸¸é ¾Ë ¼ö ÀÖ½À´Ï´Ù.


2.5. pcap_setfilter()

pcap_setfilter(pd, &fcode)

À§´Â ¾Õ¼­ ÄÄÆÄÀÏÇÑ ÇÊÅÍ ÇÁ·Î±×·¥À» ÁöÁ¤ÇØ Áִµ¥ »ç¿ëµË´Ï´Ù. ÀÌ·¸°Ô ÇÏ¿© ¿øÇÏ´Â ÆÐŶÀ» ¾òÀ» Áغñ¸¦ ÇÏ°Ô µË´Ï´Ù.


2.6. pcap_datalink()

printer = lookup_printer(pcap_datalink(pd));

À§´Â ÆÐŶ ĸÃÄ µð¹ÙÀ̽ºÀÇ datalink°èÃþÀÇ Á¾·ù¸¦ ³Ñ°Ü ¹Þ¾Æ ÀÌ¿¡ µû¸¥ ÀûÀýÇÑ ÇÔ¼öÆ÷ÀÎÅ͸¦ ÇÒ´çÇÏ°Ô µË´Ï´Ù.


2.7. pcap_loop()

pcap_loop(pd, packetcnt, printer, pcap_userdata)

½ÇÁ¦ ÆÐŶÀ» Àâ¾Æ¼­ ½ÇÇàÇÒ ÇÔ¼ö¸¦ ÁöÁ¤ÇØ ÁÖ´Â ÇÔ¼öÀÔ´Ï´Ù. packetcntÀÇ ¼ö¸¸Å­ ÆÐŶÀ» Àâ¾Æ¼­ ÀâÀ» ¶§ ¸¶´Ù ÇØ´ç ÆÐŶÀ» printer°¡ Æ÷ÀÎÅÍÇÏ´Â ÇÔ¼ö¿¡°Ô Àü´ÞÇÏ°í ÇÔ¼ö¸¦ ¼öÇàÇÏ°Ô µË´Ï´Ù.

packetcnt¸¦ 0À¸·Î ÁöÁ¤ÇÏ¸é ¹«ÇÑ´ë·Î ÇÔ¼ö¸¦ ½ÇÇàÇÕ´Ï´Ù.


2.8. pcap_next()

ÇÔ¼öÇü Æ÷ÀÎÅ͸¦ »ç¿ëÇÏÁö ¾Ê°í ÇÔ¼ö¸¦ È£ÃâÇÒ ¶§¸¶´Ù ÆÐŶÀ» ¸®ÅÏÇØÁÖ´Â ÇÔ¼ö·Î ¾ÕÀÇ pcap_datalink()¿Í pcap_loop()¸¦ ´ëüÇÒ ¼ö ÀÖ½À´Ï´Ù.

»ç¿ë¿¹´Â ÀÀ¿ëºÎºÐ4절¿¡¼­ Âü°íÇϽʽÿÀ.


3. »ç¿ë ¿¹

½ÇÁ¦ libpcapÀ» ÀÌ¿ëÇÏ´Â ¸¹Àº ÀÀ¿ëÀÌ ÀÖ½À´Ï´Ù. À§¿¡¼­ ¾ð±ÞÇÑ tcpdump°¡ ±× ´ëÇ¥ÀûÀÎ ¿¹À̸ç, ÀÌ°Í ¿Ü¿¡ ¸¹Àº ³×Æ®¿öÅ© ¸ð´ÏÅ͸µ Åø, °ø°³ ³×Æ®¿öÅ© IDS(Intrusion Detection System) ÀÎ Snort, ÆÐŶÀ» ĸÃÄÇÏ´Â ¸¹Àº ÀÀ¿ëµéÀÌ libpcapÀ» ÀÌ¿ëÇÏ¿© ´Ù¾çÇÑ OS¿¡ Æ÷ÆõǾî ÀÖ½À´Ï´Ù. www.tcpdump.org/related.html¿¡ °¡¸é ÀÀ¿ëÀÇ ¿¹µéÀ» º¼ ¼ö ÀÖ½À´Ï´Ù.

±×·³ libpcapÀ» ÀÌ¿ëÇÑ °£´ÜÇÑ ¿¹¸¦ º¸ÀÌ°Ú½À´Ï´Ù. ¾Æ·¡ ¼Ò½º´Â ip±â¹Ý tcp, udp, icmpÀÇ ÆÐŶÀ» Àâ¾Æ¼­ °¢ ÇÁ·ÎÅäÄÝ Çʵ庰·Î ÇÁ¸°Æ®ÇØÁÖ´Â ¼Ò½ºÀÔ´Ï´Ù.

¸ÕÀú IP, TCP, UDPÀÇ °¢ HEADER FORMATÀ» ÂüÁ¶ÇϽñ⠹ٶø´Ï´Ù.

    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version|  IHL  |Type of Service|          Total Length         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Identification        |Flags|      Fragment Offset    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Time to Live |    Protocol   |         Header Checksum       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Source Address                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Destination Address                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
                     Internet Datagram Header
	<RFC791>
    

    0                   1                   2                   3   
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Source Port          |       Destination Port        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         Urgent Pointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
                            TCP Header Format
	<RFC793>
    


                  0      7 8     15 16    23 24    31  
                 +--------+--------+--------+--------+ 
                 |     Source      |   Destination   | 
                 |      Port       |      Port       | 
                 +--------+--------+--------+--------+ 
                 |                 |                 | 
                 |     Length      |    Checksum     | 
                 +--------+--------+--------+--------+ 
                 |                                     
                 |          data octets ...            
                 +---------------- ...                 
 
                      User Datagram Header Format
	<RFC768>
    

#include <sys/time.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <pcap/pcap.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>

#define  PROMISCUOUS 1

struct   iphdr    *iph;
struct   tcphdr   *tcph;
struct   udphdr   *udph;
struct   icmp     *icmph;
static   pcap_t   *pd;
int sockfd;
int pflag;
int rflag;
int eflag;
int cflag;
int chcnt;

char    *device, *filter_rule;

void packet_analysis(unsigned char *, const struct pcap_pkthdr *, 
                    const unsigned char *);

struct printer {
   pcap_handler f;
   int type;
};
   
/* datalink type¿¡ µû¸¥ ºÒ¸®¾îÁú ÇÔ¼öµéÀÇ 
   ¸ñ·ÏµéÀ» °®´Â ±¸Á¶Ã¼                       
 Data-link level type codes. 
#define DLT_NULL                0        no link-layer encapsulation 
#define DLT_EN10MB      		1        Ethernet (10Mb) 
#define DLT_EN3MB               2        Experimental Ethernet (3Mb)
#define DLT_AX25                3        Amateur Radio AX.25
#define DLT_PRONET      		4        Proteon ProNET Token Ring
#define DLT_CHAOS               5        Chaos
#define DLT_IEEE802    	 		6        IEEE 802 Networks
#define DLT_ARCNET      		7        ARCNET
#define DLT_SLIP                8        Serial Line IP
#define DLT_PPP         		9        Point-to-point Protocol
#define DLT_FDDI                10       FDDI
#define DLT_ATM_RFC1483 		11       LLC/SNAP encapsulated atm
#define DLT_RAW         		12       raw IP
#define DLT_SLIP_BSDOS  		13       BSD/OS Serial Line IP
#define DLT_PPP_BSDOS   		14       BSD/OS Point-to-point Protocol
bpf.h ¶ó´Â Çì´õÈ­ÀÏ¿¡ À§¿Í °°Àº ³»¿ëÀ¸·Î Á¤ÀǵǾî ÀÖ´Ù.         */

static struct printer printers[] = {
   { packet_analysis, DLT_IEEE802 },
   { packet_analysis, DLT_EN10MB  },
   { NULL, 0 },
};
   
/*  datalink type¿¡ µû¶ó ¼öÇàµÉ ÇÔ¼ö¸¦ °áÁ¤ÇÏ°Ô µÈ´Ù.
    ÀÌ´Â pcap_handler¶ó´Â ÇÔ¼öÇü Æ÷ÀÎÅÍÀÇ °ªÀ¸·Î ´ëÀԵȴÙ. */
static pcap_handler lookup_printer(int type) 
{
	struct printer *p;

	for(p=printers; p->f; ++p)
		if(type == p->type)
			return p->f;
			
	perror("unknown data link type");
}

/* pcap_loop()¿¡ ÀÇÇØ ÆÐŶÀ» ÀâÀ» ¶§¸¶´Ù ºÒ·ÁÁö´Â ÇÔ¼ö
   pcap_handler°¡ ÀÌ ÇÔ¼ö¸¦ Æ÷ÀÎÅÍÇÏ°í Àֱ⠶§¹®ÀÌ´Ù */
void packet_analysis(unsigned char *user, const struct pcap_pkthdr *h, 
                    const unsigned char *p)
{
	int j, temp;
	unsigned int length = h->len;
	struct ether_header *ep;
	unsigned short ether_type;
	unsigned char *tcpdata, *udpdata,*icmpdata, temp_char;
	register unsigned int i;
	
	chcnt = 0;
	
	if(rflag) {
		while(length--) {
			printf("%02x ", *(p++));
			if( (++chcnt % 16) == 0 ) printf("\n");
		}
		fprintf(stdout, "\n");
		return;
	}

	length -= sizeof(struct ether_header);
	
	// ethernet header mapping
	ep = (struct ether_header *)p;
	// ethernet header 14 bytes¸¦ °Ç³Ê ¶Ú Æ÷ÀÎÅÍ
	p += sizeof(struct ether_header);
	// datalink type
	ether_type = ntohs(ep->ether_type);
	
	printf("\n");
	// Ethernet frameÀÌ IEEE802Àΰæ¿ì ether_typeÇʵ尡 ±æÀÌÇʵ尡 µÈ´Ù.
	if(ether_type <= 1500) {
		;
		/*while(length--) {
			if(++is_llchdr <= 3) {
				fprintf(stdout,"%02x",*p++);
				continue;
			}
			if(++next_line == 16) {
				next_line = 0;      
				printf("\n");
			}
			printf("%02x",*p++);
		}*/
	}
	else 
	{    
		if(eflag) {
			printf("\n\n=================== Datalink layer ===================\n");
			for(j=0; j<ETH_ALEN; j++) {
				printf("%X", ep->ether_shost[j]);
						if(j != 5) printf(":");
			}       
			printf("  ------> ");
			for(j=0; j<ETH_ALEN; j++){ 
				printf("%X", ep->ether_dhost[j]); 
				if(j != 5) printf(":");
			}
			printf("\nether_type -> %x\n", ntohs(ep->ether_type));
		}

		iph = (struct iphdr *) p;
		i = 0;
		if (ntohs(ep->ether_type) == ETHERTYPE_IP) {        // ip ÆÐŶÀΰ¡?
			printf("\n\n===================    IP HEADER   ===================\n");
			printf("%s -----> ",   inet_ntoa(iph->saddr));
			printf("%s\n", inet_ntoa(iph->daddr));
			printf("Version:         %d\n", iph->version);
			printf("Herder Length:   %d\n", iph->ihl);
			printf("Service:         %#x\n",iph->tos);
			printf("Total Length:    %d\n", ntohs(iph->tot_len)); 
			printf("Identification : %d\n", ntohs(iph->id));
			printf("Fragment Offset: %d\n", ntohs(iph->frag_off)); 
			printf("Time to Live:    %d\n", iph->ttl);
			printf("Checksum:        %d\n", ntohs(iph->check));
	
			if(iph->protocol == IPPROTO_TCP) {
				tcph = (struct tcphdr *) (p + iph->ihl * 4);
				// tcp data´Â 
				tcpdata = (unsigned char *) (p + (iph->ihl*4) + (tcph->doff * 4));
				printf("\n\n===================   TCP HEADER   ===================\n");
				printf("Source Port:              %d\n", ntohs(tcph->source));
				printf("Destination Port:         %d\n", ntohs(tcph->dest));
				printf("Sequence Number:          %d\n", ntohl(tcph->seq));
				printf("Acknowledgement Number:   %d\n", ntohl(tcph->ack_seq));
				printf("Data Offset:              %d\n", tcph->doff);
				printf("Window:                   %d\n", ntohs(tcph->window));
				printf("URG:%d ACK:%d PSH:%d RST:%d SYN:%d FIN:%d\n", 
				tcph->urg, tcph->ack, tcph->psh, tcph->rst, 
				tcph->syn, tcph->fin, ntohs(tcph->check), 
				ntohs(tcph->urg_ptr));
				printf("\n===================   TCP DATA(HEX)  =================\n"); 
				chcnt = 0;
				for(temp = (iph->ihl * 4) + (tcph->doff * 4); temp <= ntohs(iph->tot_len) - 1; temp++) {
					printf("%02x ", *(tcpdata++));
					if( (++chcnt % 16) == 0 ) printf("\n");
				}
				if (pflag) {
				   tcpdata = (unsigned char *) (p + (iph->ihl*4) + (tcph->doff * 4));
				   printf("\n===================   TCP DATA(CHAR)  =================\n"); 
				   for(temp = (iph->ihl * 4) + (tcph->doff * 4); temp <= ntohs(iph->tot_len) - 1; temp++) {
						temp_char = *tcpdata;
						if ( (temp_char == 0x0d) && ( *(tcpdata+1) == 0x0a ) ) {
							fprintf(stdout,"\n");
							tcpdata += 2;
							temp++;
							continue;
						}
						temp_char = ( ( temp_char >= ' ' ) && ( temp_char < 0x7f ) )? temp_char : '.';
						printf("%c", temp_char);
						tcpdata++;							
				   }
				}
				printf("\n>>>>> End of Data >>>>>\n");
			}
			else if(iph->protocol == IPPROTO_UDP) {
				udph = (struct udphdr *) (p + iph->ihl * 4);
				udpdata = (unsigned char *) (p + iph->ihl*4) + 8;
				printf("\n==================== UDP HEADER =====================\n");
				printf("Source Port :      %d\n",ntohs(udph->source));
				printf("Destination Port : %d\n", ntohs(udph->dest));
				printf("Length :           %d\n", ntohs(udph->len));
				printf("Checksum :         %x\n", ntohs(udph->check));
						printf("\n===================  UDP DATA(HEX)  ================\n");   
				chcnt = 0;
				for(temp = (iph->ihl*4)+8; temp<=ntohs(iph->tot_len) -1; temp++) {
				   printf("%02x ", *(udpdata++));
				   if( (++chcnt % 16) == 0) printf("\n"); 
				}

				udpdata = (unsigned char *) (p + iph->ihl*4) + 8;
				if(pflag) {
					printf("\n===================  UDP DATA(CHAR)  ================\n");     
					for(temp = (iph->ihl*4)+8; temp<=ntohs(iph->tot_len) -1; temp++)  {
						temp_char = *udpdata;
						if ( (temp_char == 0x0d) && ( *(udpdata+1) == 0x0a ) ) {
							fprintf(stdout,"\n");
							udpdata += 2;
							temp++;
							continue;
						}
						temp_char = ( ( temp_char >= ' ' ) && ( temp_char < 0x7f ) )? temp_char : '.';
						printf("%c", temp_char);
						udpdata++;							
					}
				}
				
				printf("\n>>>>> End of Data >>>>>\n");
			}         
			else if(iph->protocol == IPPROTO_ICMP) {
				icmph = (struct icmp *) (p + iph->ihl * 4);
				icmpdata = (unsigned char *) (p + iph->ihl*4) + 8;
				printf("\n\n===================   ICMP HEADER   ===================\n");
				printf("Type :                    %d\n", icmph->icmp_type);
				printf("Code :                    %d\n", icmph->icmp_code);
				printf("Checksum :                %02x\n", icmph->icmp_cksum);
				printf("ID :                      %d\n", icmph->icmp_id);
				printf("Seq :                     %d\n", icmph->icmp_seq);
				printf("\n===================   ICMP DATA(HEX)  =================\n"); 
				chcnt = 0;
				for(temp = (iph->ihl * 4) + 8; temp <= ntohs(iph->tot_len) - 1; temp++) {
					printf("%02x ", *(icmpdata++));
					if( (++chcnt % 16) == 0 ) printf("\n");
				}
				printf("\n>>>>> End of Data >>>>>\n");
		   }
		}   
	}
}

void sig_int(int sig)
{
    printf("Bye!!\n");
    pcap_close(pd);
    close(sockfd);
    exit(0);
}

void usage(void)
{
    fprintf(stdout," Usage : noh_pa filter_rule [-pch]\n");
    fprintf(stdout,"         -p  :  µ¥ÀÌŸ¸¦ ¹®ÀÚ·Î Ãâ·ÂÇÑ´Ù.\n");
    fprintf(stdout,"         -c  :  ÁÖ¾îÁø ¼ýÀÚ¸¸Å­ÀÇ ÆÐŶ¸¸ ´ýÇÁÇÑ´Ù\n");
    fprintf(stdout,"         -e  :  datalink layer¸¦ Ãâ·ÂÇÑ´Ù.\n");
    fprintf(stdout,"         -r  :  ÀâÀº ÆÐŶÀ» »ýÀ¸·Î Âï´Â´Ù.\n");
    fprintf(stdout,"         -h  :  »ç¿ë¹ý\n");
}

int main(int argc, char *argv[])
{
	struct  bpf_program fcode;
	pcap_handler printer;
	char    ebuf[PCAP_ERRBUF_SIZE];
	int     c, i, snaplen = 1514, size, packetcnt;
	bpf_u_int32 myself, localnet, netmask;
	unsigned char   *pcap_userdata;
			
	filter_rule = argv[1];          /* example : "src host xxx.xxx.xxx.xxx and tcp port 80" */
	
	signal(SIGINT,sig_int);
	
	opterr = 0;
	
	if(argc-1 < 1) {
		usage(); 
		exit(1);
	}
	
	while( (c = getopt(argc, argv,"i:c:pher")) != -1) {
		switch(c) {
			case 'i'  :
				device = optarg;
				break;
			case 'p' :
				pflag = 1; 
				break;
			case 'c' :
				cflag = 1; 
				packetcnt = atoi(optarg);
				if(packetcnt <= 0) {
					fprintf(stderr,"invalid number %s",optarg);
					exit(1);
				}
				break;
			case 'e' :
				eflag = 1;
				break;          
			case 'r' :
				rflag = 1;
				break;          
			case 'h' :
				usage();
				exit(1);
		}
	}           
	
	if (device == NULL ) {
		if ( (device = pcap_lookupdev(ebuf) ) == NULL) {
			perror(ebuf);           
			exit(-1);
		}
	}
	fprintf(stdout, "device = %s\n", device);
	
	pd = pcap_open_live(device, snaplen, PROMISCUOUS, 1000, ebuf);
	if(pd == NULL) {
		perror(ebuf);          
		exit(-1);
	}
	
	i = pcap_snapshot(pd);
	if(snaplen < i) {
		perror(ebuf);                            
		exit(-1);
	}
	
	if(pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
		perror(ebuf);
		exit(-1);
	}
	
	setuid(getuid());
	
	if(pcap_compile(pd, &fcode, filter_rule, 0, netmask) < 0) {
		perror(ebuf);
		exit(-1);
	}
	
	if(pcap_setfilter(pd, &fcode) < 0) {
		perror(ebuf);
		exit(-1);
	}
	
	fflush(stderr);
	
	printer = lookup_printer(pcap_datalink(pd));
	pcap_userdata = 0;
	
	if(pcap_loop(pd, packetcnt, printer, pcap_userdata) < 0) {
		perror("pcap_loop error");
		exit(-1);
	}
	
	pcap_close(pd);
	exit(0);
}
	

4. ÀÀ¿ë : icmp_toy

libpcapÀ» ÀÌ¿ëÇÑ °£´ÜÇÑ ÀÀ¿ëÀÇ ¿¹¸¦ º¸À̵µ·Ï ÇÏ°Ú½À´Ï´Ù.

icmp_toy´Â ƯÁ¤ È£½ºÆ®ÀÇ ip address¸¦ ÀÔ·ÂÀ¸·Î ¹Þ¾Æ ±× È£½ºÆ®ÀÇ ¸ðµç Á¢¼ÓÀ» Â÷´ÜÇØ ¹ö¸®´Â ÇÁ·Î±×·¥À¸·Î ÇØ´ç È£½ºÆ®ÀÇ tcp, syn flag°¡ setµÈ ÆÐŶÀ» libpcapÀ» ÀÌ¿ëÇÏ¿© ĸÃÄÇÑ ÈÄ ÇØ´ç ÆÐŶ¿¡ ´ëÇÑ icmp protocol unreachable ÆÐŶÀ» ÇØ´ç È£½ºÆ®¿¡°Ô ÀçÀü¼ÛÇÏ°Ô µË´Ï´Ù.

ÀÔ·ÂÇÑ È£½ºÆ®´Â icmp_toy°¡ ±¸µ¿ÁßÀΠȣ½ºÆ®¿Í °°Àº ³×Æ®¿öÅ©¿¡ ±¸¼ºµÇ¾î ÀÖ°í, Dummy Hub ȯ°æÀÌ¿©¾ß¸¸ Á¦´ë·Î ÀÛµ¿ÇÏ°Ô µË´Ï´Ù.

icmp packetÀº ¾Æ·¡¿Í °°Àº ±¸Á¶·Î ¸¸µé¾îÁÖ°Ô µË´Ï´Ù.

	Destination Unreachable Message
 
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |     Code      |          Checksum             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             unused                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      Internet Header + 64 bits of Original Data Datagram      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    Type : 3
    Code : 2 = protocol unreachable
    <RFC792>
    

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <net/ethernet.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/time.h>
#include <pcap.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#define  PROMISCUOUS 1

static int nchild = 5;
char target_ip[16];

static pid_t *pids;
static pcap_t *pd;

unsigned short in_cksum (unsigned short *addr, int len)
{
  int nleft = len;
  int sum = 0;
  unsigned short *w = addr;
  unsigned short answer = 0;

  while (nleft > 1) {
      sum += *w++;
      nleft -= 2;
  }

  if (nleft == 1) {
      *(unsigned char *) (&answer) = *(unsigned char *) w;
      sum += answer;
  }

  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  answer = ~sum;
  return (answer);
}

void send_icmp (int sockfd, struct iphdr *iph, struct tcphdr *tcph)
{
  char buff[76];
  char data[28];

  int len;
  struct sockaddr send;
  struct icmp *icmp;
  struct sockaddr_in *willsend;

  willsend = (struct sockaddr_in *) &send;
  willsend->sin_family = AF_INET;
  willsend->sin_addr.s_addr = iph->saddr;

  fprintf (stdout, "A player\'s number is (%d) : Shot!! ---<-@ %s \n",
	   getpid (), target_ip);

  icmp = (struct icmp *) buff;
  icmp->icmp_type = ICMP_DEST_UNREACH;
  icmp->icmp_code = ICMP_PROT_UNREACH;
  icmp->icmp_id = 0;
  icmp->icmp_seq = 0;

  memcpy (data, iph, 20);
  memcpy (data + 20, tcph, 8);
  memcpy (icmp->icmp_data, data, 28);

  len = 8 + 20 + 8;

  icmp->icmp_cksum = 0;
  icmp->icmp_cksum = in_cksum ((u_short *) icmp, len);
  sendto (sockfd, buff, len, 0, &send, sizeof (send));
}

void checkip (struct iphdr *iph, struct tcphdr *tcph)
{
  int sockfd;
  char source_ip[16];

  struct in_addr in;
  in.s_addr = iph->saddr;

  strncpy (source_ip, inet_ntoa (in), sizeof (source_ip));
  sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);

  if (strncmp (target_ip, source_ip, sizeof (source_ip)) == 0)
    send_icmp (sockfd, iph, tcph);

  close (sockfd);
}

void packet_info (char *user, int len)
{
  struct iphdr *iph;
  struct tcphdr *tcph;

  iph = (struct iphdr *) user;
  tcph = (struct tcphdr *) (user + iph->ihl * 4);
  checkip (iph, tcph);
}

void sig_int (int sig)
{
  int i;

  for (i = 0; i < nchild; i++)
    kill (pids[i], SIGTERM);

  while (wait (NULL) > 0)
    ;

  fprintf (stdout, "Bye !!\n");

  pcap_close(pd);
  exit (0);
}

pid_t child_make (int i, pcap_t * pd, int datalink)
{
  pid_t pid;
  void child_main (int, pcap_t *, int);

  if ((pid = fork ()) > 0) {
      return (pid);
  }

  child_main (i, pd, datalink);
  return 0;			// ADD 
}

void child_main (int i, pcap_t * pd, int datalink)
{
  void packet_loop (pcap_t *, int);

  printf ("CHILD %ld starting\n", (long) getpid ());
  packet_loop (pd, datalink);
}

char *next_pcap (pcap_t * pd, int *len)
{
  char *ptr;
  struct pcap_pkthdr hdr;

  while ((ptr = (char *) pcap_next (pd, &hdr)) == NULL);

  *len = hdr.caplen;
  return (ptr);
}

void packet_loop (pcap_t * pd, int datalink)
{
  int len;
  char *ptr;

  for (;;) {
      ptr = next_pcap (pd, &len);
      switch (datalink) {
		case DLT_EN10MB:
	  		packet_info (ptr + 14, len - 14);
	  		break;
	  }
  }
}

void usage (void)
{
  fprintf (stdout, "SYNOPSIS : icmp_toy xxx.xxx.xxx.xxx(target ip address) \n");
}

int main (int argc, char *argv[])
{
   struct bpf_program fcode;
   char *device, *filter_rule;
   char ebuf[PCAP_ERRBUF_SIZE];
   int i, j, snaplen = 68;
   bpf_u_int32 localnet, netmask;

   signal (SIGINT, sig_int); 

   if (argc < 2) {
	   usage (); 
	   exit (1);
   }

   strncpy (target_ip, argv[1], sizeof (target_ip));
   filter_rule = "tcp and tcp[13:1] & 2 != 0";
   device = pcap_lookupdev (ebuf); 
   if (device == NULL)
   {
	   perror (ebuf); 
	   exit (1);
   }


   pd = pcap_open_live (device, snaplen, PROMISCUOUS, 1000, ebuf);

   if (pd == NULL)
   {
	   perror (ebuf); 
	   exit (1);
   }

   i = pcap_snapshot (pd); 
   
   if (snaplen < 1)
   {
	   perror (ebuf); 
	   exit (1);
   }

   if (pcap_lookupnet (device, &localnet, &netmask, ebuf) < 0)
   {
	   perror (ebuf); 
	   exit (1);
   }

   if (pcap_setfilter (pd, &fcode) < 0)
   {
	   perror (ebuf); 
	   exit (1);
   }

   fflush (stderr);

   pids = calloc (nchild, sizeof (pid_t));
   for (j = 0; j < nchild; j++)
	   pids[j] = child_make (j, pd, pcap_datalink (pd));

   for (;;) 
	   pause ();
}
   

5. °ü·Ã ¸µÅ©

  • Libpcap : ftp://ftp.ee.lbl.gov

  • WinPcap : the Free Packet Capture Architecture for Windows

  • Tcpdump : libpcapÀ» ÀÌ¿ëÇÑ ´ëÇ¥ÀûÀÎ ³×Æ®¿öÅ© ¸ð´ÏÅ͸µ Åø

  • Raw IP Networking FAQ : Raw socket, packet capturing µî¿¡ ´ëÇÑ ºó¹øÇÑ Áú¹®°ú ´ä

  • µ¿À۱׸¸(DJSTOP) : libpcap, libnet µîÀ» ÀÌ¿ëÇÑ ÀÎÅÍ³Ý Á¢¼ÓÁ¦¾î ÇÁ·Î±×·¥


6. ÀúÀÛ±Ç Á¤º¸ ¹× ±âŸ

Copyright (C) 2002 ³ë±¤¹Î

ÀÌ ¹®¼­´Â GNU Free Documentation License ¹öÀü 1.1 ȤÀº ÀÚÀ¯ ¼ÒÇÁÆ®¿þ¾î Àç´Ü¿¡¼­ ¹ßÇàÇÑ ÀÌÈÄ ÆÇÀÇ ±ÔÁ¤¿¡ µû¸£¸ç ÀúÀ۱ǿ¡ ´ëÇÑ º» »çÇ×ÀÌ ¸í½ÃµÇ´Â ÇÑ ¾î¶°ÇÑ Á¤º¸ ¸Åü¿¡ ÀÇÇÑ º»¹®ÀÇ ÀüÀ糪 ¹ßÃéµµ ¹«»óÀ¸·Î Çã¿ëµË´Ï´Ù.


6.1. Ã¥ÀÓÀÇ ÇÑ°è

º» ÀúÀÚ´Â ¹®¼­ÀÇ ³»¿ëÀÌ ¾ß±âÇÒ ¼ö ÀÖ´Â ¾î¶°ÇÑ °á°ú¿¡ ´ëÇؼ­µµ Ã¥ÀÓÀ» ÁöÁö ¾Ê½À´Ï´Ù. º» ¹®¼­¿¡¼­ ³»Æ÷ÇÏ°í ÀÖ´Â Á¤º¸µé ¹× ¿¹Á¦µéÀº ¿©·¯ºÐÀÌ ¾Ë¾Æ¼­ È°¿ëÇϽʽÿÀ. ºñ·Ï ÃÖ¼±À» ´ÙÇßÀ¸³ª ÀÌ ¹®¼­´Â Ʋ¸° Á¡À̳ª ¿À·ù°¡ ÀÖÀ» ¼öµµ ÀÖ½À´Ï´Ù. ¸¸¾à ¿©·¯ºÐÀÌ Æ²¸° Á¡À» ¹ß°ßÇß´Ù¸é ²À Àú¿¡°Ô ¾Ë·Á Áֽñ⠹ٶø´Ï´Ù.


6.2. Çǵå¹é

ÀÌ ¹®¼­¿¡ ´ëÇÑ ¹ßÀüÀûÀÎ Á¦¾ÈÀ̳ª ¼öÁ¤»çÇ×, ¹®Á¦Á¡ µî¿¡ ´ëÇÑ Çǵå¹éÀº ¾ðÁ¦µçÁö ȯ¿µÇÕ´Ï´Ù. djstop (at) orgio.net·Î ¸ÞÀÏÀ» º¸³» ÁֽʽÿÀ.


ID
Password
Join
One man tells a falsehood, a hundred repeat it as true.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2003-08-10 11:52:29
Processing time 0.0023 sec