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

You are not allowed to 'info'


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
Of all forms of caution, caution in love is the most fatal.


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.0017 sec