Libpcap »ç¿ëÇϱ⠱¤¹Î ³ë
dalgu2 (at) kldp.org
0.4 2002-01-01 Kwang-Min Noh Text ¹®¼­¸¦ DocBookÀ¸·Î ¼öÁ¤ ¹× ÀÀ¿ë ºÎºÐ Ãß°¡ libpcapÀÇ Á¤ÀÇ¿Í »ç¿ë¹ý, ÀÀ¿ë µîÀ» Á¦½ÃÇÑ´Ù.
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ÀÌ´Ù. ÆÐŶÀ» ĸÃÄÇϱâ À§ÇÑ 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); } pcap_lookupdev() device = pcap_lookupdev(ebuf); ³×Æ®¿÷ µð¹ÙÀ̽º¸¦ °¡Á®¿À´Â ÇÔ¼öÀÔ´Ï´Ù. ÆÐŶÀ» ÀâÀ¸·Á¸é ³×Æ®¿÷ µð¹ÙÀ̽º¸¦ ÁöÁ¤ÇØ¾ß °ÚÁÒ? °¡´ÉÇÑ ´ÙºñÀ̽ºÁß °¡Àå ¹øÈ£°¡ ³·Àº µð¹ÙÀ̽º¸¦ °¡Á®¿À°Ô µË´Ï´Ù. ¸®´ª½º¶ó¸é eth0ÀÌ°ÚÁÒ... ´Ù¸¥ µð¹ÙÀ̽º¸¦ ÅëÇØ ÆÐŶÀ» ĸÃÄÇÏ·Á¸é ÀÌ ÇÔ¼ö¸¦ »ç¿ëÇÏÁö ¾Ê°í ÇÁ·Î±×·¥ÀÇ ÀÔ·ÂÀ¸·Î µð¹ÙÀ̽º¸íÀ» °¡Á®¿À¸é µË´Ï´Ù. pcap_open_live() pd = pcap_open_live(device, snaplen, PROMISCUOUS, 1000, ebuf); À§ ÇÔ¼ö´Â ½ÇÁ¦ ±â±â¸¦ ¿­¾îÁÖ´Â ±â´ÉÀ» ÇÏ´Â °ÍÀ¸·Î snaplen´Â ÆÐŶ´ç ÀúÀåÇÒ ¹ÙÀ̽º ¼ö, ½ÇÁ¦ datalink°èÃþºÎÅÍ ÆÐŶÀÇ Å©±â¸¦ °è»êÇÏ¿© ¿øÇÏ´Â ºÎºÐ¸¸À» ¾ò¾î¿À¸é µÇ´Â °ÍÀÔ´Ï´Ù. Çì´õÁ¤º¸¸¸À» º¸°í½ÍÀºµ¥ ¾µµ¥¾øÀÌ µ¥ÀÌŸ±îÁö ¹ÞÀ» ÇÊ¿ä´Â ¾ø°ÚÁÒ. µ¥ÀÌÅͱîÁö º¸°í½ÍÀ¸¸é snaplen¸¦ Å©°Ô ÇÏ¸é µË´Ï´Ù. PROMISCUOUS´Â 1ÀÌ¸ç ³×Æ®¿÷ µð¹ÙÀ̽º¿¡ ¿À´Â ¸ðµç ÆÐŶÀ» ¹Þ°Ú´Ù´Â ÀǹÌÀÔ´Ï´Ù. ÀÌ ¸ðµå¸¦ ÀÚ¼¼ÇÏ°Ô ¼³¸íÇϸé EthernetÀº ¸ðµç ÆÐŶÀÌ broadcastingµÇ¸ç ÀÏ´Ü ¸ðµç ³×Æ®¿÷ µð¹ÙÀ̽º´Â µ¿ÀÏ ³×Æ®¿÷³»ÀÇ ´Ù¸¥ È£½ºÆ®ÀÇ ÆÐŶµµ ÀÏ´Ü Á¢ÇÏ°Ô µË´Ï´Ù. ±×·¯³ª, ³×Æ®¿÷ µð¹ÙÀ̽º´Â ±âº»ÀûÀ¸·Î ÀÚ½ÅÀÇ ÆÐŶ¸¸À» ¹Þ°Ô²û µÇ¾îÀÖ½À´Ï´Ù. ±×·¯¹Ç·Î ´Ù¸¥ È£½ºÆ®ÀÇ ÆÐŶÀº ¹ö¸®°Ô µÇ´Â °ÍÀÔ´Ï´Ù. ±×·¯³ª promiscuous¸ðµå·Î µð¹ÙÀ̽º ¸ðµå¸¦ ¹Ù²Ù°Ô µÇ¸é ¸ðµç ÆÐŶÀ» ¹Þ¾ÆµéÀÌ°Ô µÇ´Â °ÍÀÔ´Ï´Ù. ¸ðµç ³×Æ®¿öÅ© ¸ð´ÏÅ͸µ ÇÁ·Î±×·¥µéÀº ¸ðµÎ ÀÌ ¸ðµå¸¦ »ç¿ëÇÏ°Ô µË´Ï´Ù. ¼¼ ¹ø° ÀÎÀÚ´Â ÆÐŶÀÌ ¹öÆÛ·Î Àü´ÞµÉ ¶§ ¹Ù·Î Àü´ÞµÇ´Â °ÍÀÌ ¾Æ´Ï¶ó À§¿¡¼­ ¸í½ÃÇÑ ½Ã°£À» ³Ñ°åÀ» ¶§³ª ¹öÆÛ°¡ ´Ù ä¿öÁ³À» ¶§ ÀÀ¿ëÇÁ·Î±×·¥À¸·Î Àü´ÞµÇ´Â °ÍÀÔ´Ï´Ù. pcap_lookupnet() pcap_lookupnet(device, &localnet, &netmask, ebuf) ¿­·ÁÁø ÆÐŶ ĸÃÄ µð¹ÙÀ̽º¿¡ ³×Æ®¿÷ ÁÖ¼Ò¿Í ¼­ºê³Ý ¸¶½ºÅ©¸¦ ³Ñ°ÜÁÝ´Ï´Ù. pcap_compile() pcap_compile(pd, &fcode, filter_rule, 0, netmask) Á¤ÇØÁø ÇÊÅÍ·ê¿¡ ÀÇÇØ ÇÊÅÍ ÇÁ·Î±×·¥À» ÄÄÆÄÀÏÇÏ°Ô µÇ´Âµ¥ ¿ì¸®°¡ ¿øÇÏ´Â ÆÐŶÀº ÇÊÅÍ·êÀ» ÁÖ¾î¾ß¸¸ ¿øÇÏ´Â ÆÐŶ¸¸À» ¾òÀ» ¼ö ÀÖ½À´Ï´Ù. ½ÇÁ¦ tcpdump¿¡¼­ »ç¿ëÇÏ´Â ÇÊÅÍ·êÀÌ ¿©±â¿¡¼­ ¾²ÀÔ´Ï´Ù. ¿¹¸¦ µé¸é "tcp port 80" ÀÔ´Ï´Ù. ÀÚ¼¼ÇÑ ÇÊÅÍ·ê¿¡ ´ëÇÑ ¼³¸íÀº tcpdumpÀÇ ¸Þ´º¾óÀ» º¸¸é ¾Ë ¼ö ÀÖ½À´Ï´Ù. pcap_setfilter() pcap_setfilter(pd, &fcode) À§´Â ¾Õ¼­ ÄÄÆÄÀÏÇÑ ÇÊÅÍ ÇÁ·Î±×·¥À» ÁöÁ¤ÇØ Áִµ¥ »ç¿ëµË´Ï´Ù. ÀÌ·¸°Ô ÇÏ¿© ¿øÇÏ´Â ÆÐŶÀ» ¾òÀ» Áغñ¸¦ ÇÏ°Ô µË´Ï´Ù. pcap_datalink() printer = lookup_printer(pcap_datalink(pd)); À§´Â ÆÐŶ ĸÃÄ µð¹ÙÀ̽ºÀÇ datalink°èÃþÀÇ Á¾·ù¸¦ ³Ñ°Ü ¹Þ¾Æ ÀÌ¿¡ µû¸¥ ÀûÀýÇÑ ÇÔ¼öÆ÷ÀÎÅ͸¦ ÇÒ´çÇÏ°Ô µË´Ï´Ù. pcap_loop() pcap_loop(pd, packetcnt, printer, pcap_userdata) ½ÇÁ¦ ÆÐŶÀ» Àâ¾Æ¼­ ½ÇÇàÇÒ ÇÔ¼ö¸¦ ÁöÁ¤ÇØ ÁÖ´Â ÇÔ¼öÀÔ´Ï´Ù. packetcntÀÇ ¼ö¸¸Å­ ÆÐŶÀ» Àâ¾Æ¼­ ÀâÀ» ¶§ ¸¶´Ù ÇØ´ç ÆÐŶÀ» printer°¡ Æ÷ÀÎÅÍÇÏ´Â ÇÔ¼ö¿¡°Ô Àü´ÞÇÏ°í ÇÔ¼ö¸¦ ¼öÇàÇÏ°Ô µË´Ï´Ù. packetcnt¸¦ 0À¸·Î ÁöÁ¤ÇÏ¸é ¹«ÇÑ´ë·Î ÇÔ¼ö¸¦ ½ÇÇàÇÕ´Ï´Ù. pcap_next() ÇÔ¼öÇü Æ÷ÀÎÅ͸¦ »ç¿ëÇÏÁö ¾Ê°í ÇÔ¼ö¸¦ È£ÃâÇÒ ¶§¸¶´Ù ÆÐŶÀ» ¸®ÅÏÇØÁÖ´Â ÇÔ¼ö·Î ¾ÕÀÇ pcap_datalink()¿Í pcap_loop()¸¦ ´ëüÇÒ ¼ö ÀÖ½À´Ï´Ù. »ç¿ë¿¹´Â ÀÀ¿ëºÎºÐ¿¡¼­ Âü°íÇϽʽÿÀ. »ç¿ë ¿¹ ½ÇÁ¦ 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); } ÀÀ¿ë : 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 (); } °ü·Ã ¸µÅ© 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 µîÀ» ÀÌ¿ëÇÑ ÀÎÅÍ³Ý Á¢¼ÓÁ¦¾î ÇÁ·Î±×·¥ ÀúÀÛ±Ç Á¤º¸ ¹× ±âŸ Copyright (C) 2002 ³ë±¤¹Î ÀÌ ¹®¼­´Â GNU Free Documentation License ¹öÀü 1.1 ȤÀº ÀÚÀ¯ ¼ÒÇÁÆ®¿þ¾î Àç´Ü¿¡¼­ ¹ßÇàÇÑ ÀÌÈÄ ÆÇÀÇ ±ÔÁ¤¿¡ µû¸£¸ç ÀúÀ۱ǿ¡ ´ëÇÑ º» »çÇ×ÀÌ ¸í½ÃµÇ´Â ÇÑ ¾î¶°ÇÑ Á¤º¸ ¸Åü¿¡ ÀÇÇÑ º»¹®ÀÇ ÀüÀ糪 ¹ßÃéµµ ¹«»óÀ¸·Î Çã¿ëµË´Ï´Ù. Ã¥ÀÓÀÇ ÇÑ°è º» ÀúÀÚ´Â ¹®¼­ÀÇ ³»¿ëÀÌ ¾ß±âÇÒ ¼ö ÀÖ´Â ¾î¶°ÇÑ °á°ú¿¡ ´ëÇؼ­µµ Ã¥ÀÓÀ» ÁöÁö ¾Ê½À´Ï´Ù. º» ¹®¼­¿¡¼­ ³»Æ÷ÇÏ°í ÀÖ´Â Á¤º¸µé ¹× ¿¹Á¦µéÀº ¿©·¯ºÐÀÌ ¾Ë¾Æ¼­ È°¿ëÇϽʽÿÀ. ºñ·Ï ÃÖ¼±À» ´ÙÇßÀ¸³ª ÀÌ ¹®¼­´Â Ʋ¸° Á¡À̳ª ¿À·ù°¡ ÀÖÀ» ¼öµµ ÀÖ½À´Ï´Ù. ¸¸¾à ¿©·¯ºÐÀÌ Æ²¸° Á¡À» ¹ß°ßÇß´Ù¸é ²À Àú¿¡°Ô ¾Ë·Á Áֽñ⠹ٶø´Ï´Ù. Çǵå¹é ÀÌ ¹®¼­¿¡ ´ëÇÑ ¹ßÀüÀûÀÎ Á¦¾ÈÀ̳ª ¼öÁ¤»çÇ×, ¹®Á¦Á¡ µî¿¡ ´ëÇÑ Çǵå¹éÀº ¾ðÁ¦µçÁö ȯ¿µÇÕ´Ï´Ù. djstop (at) orgio.net·Î ¸ÞÀÏÀ» º¸³» ÁֽʽÿÀ.