轉載自 這裡
前言 :
我們知道每台電腦都會有所謂的 network interface, 而封包的交換便是透過那些 network interface. 底下將介紹如何使用 libpcap 來捕捉 network interface 上面的封包並將之投映於螢幕上, 在開始編碼前請先到以下位置下載 pcap 的 library :
* Download libpcap source from www.tcpdump.org
here
* Download libpcap for win32 from
www.winpcap.org
* Check out a better pcap tutorial
here
捕捉我的第一個封包 :
接著請參考下面代碼 :
- pcap_example02.c : Simple single packet capture program
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- int main(int argc, char **argv)
- {
- int i;
- char *dev;
- char errbuf[PCAP_ERRBUF_SIZE];
- pcap_t* descr;
- const u_char *packet;
- struct pcap_pkthdr hdr;
- struct ether_header *eptr;
-
- u_char *ptr;
-
-
- dev = pcap_lookupdev(errbuf);
-
- if(dev == NULL)
- {
- printf("%s\n",errbuf);
- exit(1);
- }
-
- printf("DEV: %s\n",dev);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- descr = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);
-
- if(descr == NULL)
- {
- printf("pcap_open_live(): %s\n",errbuf);
- exit(1);
- }
-
-
-
-
-
-
-
-
-
- packet = pcap_next(descr,&hdr);
-
- if(packet == NULL)
- {
- printf("Didn't grab packet\n");
- exit(1);
- }
-
-
-
-
-
-
-
-
- printf("Grabbed packet of length %d\n",hdr.len);
- printf("Recieved at ..... %s\n",ctime((const time_t*)&hdr.ts.tv_sec));
- printf("Ethernet address length is %d\n",ETHER_HDR_LEN);
-
-
- eptr = (struct ether_header *) packet;
-
-
- if (ntohs (eptr->ether_type) == ETHERTYPE_IP)
- {
- printf("Ethernet type hex:%x dec:%d is an IP packet\n",
- ntohs(eptr->ether_type),
- ntohs(eptr->ether_type));
- }else if (ntohs (eptr->ether_type) == ETHERTYPE_ARP)
- {
- printf("Ethernet type hex:%x dec:%d is an ARP packet\n",
- ntohs(eptr->ether_type),
- ntohs(eptr->ether_type));
- }else {
- printf("Ethernet type %x not IP", ntohs(eptr->ether_type));
- exit(1);
- }
-
-
- ptr = eptr->ether_dhost;
- i = ETHER_ADDR_LEN;
- printf(" Destination Address: ");
- do{
- printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);
- }while(--i>0);
- printf("\n");
-
- ptr = eptr->ether_shost;
- i = ETHER_ADDR_LEN;
- printf(" Source Address: ");
- do{
- printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);
- }while(--i>0);
- printf("\n");
-
- return 0;
- }
接著請編譯該代碼並執行 :
$ cc -g -Wall -c pcap_example02.c
pcap_example02.c: In function ‘main’:
pcap_example02.c:89:5: warning: implicit declaration of function ‘ctime’
pcap_example02.c:89:5: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
$ cc pcap_example02.o -lpcap -o test
$ sudo ./test
DEV: eth0
Grabbed packet of length 106
Recieved at ..... Fri Sep 9 09:43:36 2011
Ethernet address length is 14
Ethernet type hex:800 dec:2048 is an IP packet
Destination Address: 0:50:56:c0:0:8
Source Address: 0:c:29:e1:b3:32
這邊可以發現列印出來的 Address 並不是我們熟悉的 IP 格式而是所謂的 Hardware address (
Mac address). 而在網路通訊協定中是透過
ARP 協定 將 IP 與 實體位置做 Mapping. 而你可以透過命令
arp -n 來檢視這個 Mapping table :
在這個代碼裡, 我們將捕捉到的 packet 轉成
struct ether_header *. 而該結構定義在
net/ethernet.h :
-
- struct ether_header
- {
- u_int8_t ether_dhost[ETH_ALEN];
- u_int8_t ether_shost[ETH_ALEN];
- u_int16_t ether_type;
- } __attribute__ ((__packed__));
而在該結構的
ether_type 也可以在
net/ethernet.h 找到 :
-
- #define ETHERTYPE_PUP 0x0200
- #define ETHERTYPE_IP 0x0800
- #define ETHERTYPE_ARP 0x0806
- #define ETHERTYPE_REVARP 0x8035
事實上我們目前只使用了少部分 libpcap 的 APIs, 在實際應用上我們可能需要 filter 掉沒有興趣的 packet 與捕抓不只一個的 packet 來進行網路封包的分析與延伸應用. 而這邊所用的每一支 libpcap 的 API, 你都可以使用
man 來檢視該 API 的用法. 更多的範例與使用介紹將在後面陸續進行介紹.
沒有留言:
張貼留言