日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

在Ubuntu 14.04 64位上使用libpcap进行抓包和解包

發布時間:2023/11/27 生活经验 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Ubuntu 14.04 64位上使用libpcap进行抓包和解包 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
為了開發需要,我決定使用最新libpcap源碼包安裝。在Unix環境下安裝libpcap庫,需要
c編譯器,flex,bison等,安裝Ubuntu系統時,沒有這些包。安裝flex需要m4編譯環境,否則會提示“GNU M4 is required”錯誤。


1.安裝系統依賴包
sudo apt-get install gcc libc6-dev
sudo apt-get install m4?
sudo apt-get install flex bison


2.下載libpcap源碼并安裝
從官網http://www.tcpdump.org/下載最新的libpcap版本
cd /usr/local/src
wget http://www.tcpdump.org/release/libpcap-1.5.3.tar.gz
tar zxvf libpcap-1.5.3.tar.gz
cd libpcap-1.5.3
./configure
make
sudo make install


3.安裝開發需要用到的依賴庫
sudo apt-get install libpcap-dev


4.測試libpcap的小程序,命名為pcap_demo.c,以檢驗環境是否配置正確
#include <pcap.h>
#include <stdio.h>


int main(int argc, char *argv[])
{
pcap_t *handle; /* Session handle */
char *dev; /* The device to sniff on */
char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */
struct bpf_program fp; /* The compiled filter */
char filter_exp[] = "port 80"; /* The filter expression */
bpf_u_int32 mask; /* Our netmask */
bpf_u_int32 net; /* Our IP */
struct pcap_pkthdr header; /* The header that pcap gives us */
const u_char *packet; /* The actual packet */


/* Define the device */
dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
return(2);
}
/* Find the properties for the device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);
net = 0;
mask = 0;
}
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
return(2);
}
/* Compile and apply the filter */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
return(2);
}
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
return(2);
}
/* Grab a packet */
packet = pcap_next(handle, &header);
/* Print its length */
printf("Jacked a packet with length of [%d]\n", header.len);
/* And close the session */
pcap_close(handle);
return(0);
}
開始編譯:
? ? gcc -g pcap_demo.c -o pcap_demo -lpcap ?
開始執行
? ? ./pcap_demo


5.注意的問題
5.1.注意使用root用戶來執行,或者對普通用戶使用sudo來提升權限
? ? sudo pcap_demo
5.2.對一些PCAP API函數要有全面地理解,并時刻更新文檔,比如pcap_loop這個函數,下面是官網的man page地址
http://www.tcpdump.org/manpages/pcap.3pcap.html
5.3,對一些函數的理解:
? ? pcap_loop和pcap_dispatch的區別,前者不會超時返回,而是會盡量去讀取更多的包,直至發生一個錯誤才返回。正常返回的值是0,否則就是負值。我目前需要連續不斷地抓包,所以應該使用pcap_loop。pcap_dispatch內部會調用pcap_loop。pcap_loop中的第四個參數在某些應用中很有用,但是在通常情況下被設為NULL。這種定義很有用,比如假如你想給pcap_loop的回調函數再額外傳遞一些參數,你可以使用u_char類型的指針(字符串),傳人到回調函數中再做具體地處理。pcap_dispatch只會處理它收到的第一批包。
從pcap_loop返回后,我們應該顯式調用pcap_close來關閉pcap以便釋放資源。為了表示連續不間斷的抓包,在pcap_loop中要盡量使用-1而不是0.關于其中回調函數的說明,里面有3個參數。第一個參數user是pcap_loop中最后一個參數,它表示某個不太重要的信息,可以忽略,第二個參數是包頭信息,含有包的時間戳和長度,第三個參數是包的數據,從鏈路層頭開始,它在該回調函數中并不會被釋放,但是當該回調返回時不包裝這些數據再合法,所以要再次使用它們,請事先復制出來。

下面再深入研究一下pcap_loop這個回調函數的定義:
首先注意函數的返回值是void類型,這完全符合邏輯,因為pcap_loop根本不知道如何處理回調函數的返回值,就是給他傳出返回值也沒有意義。然后就是回調函數的第一個參數對應pcap_loop中的最后一個參數,不管你給pcap_loop的最后一個參數傳遞什么值,當回調函數被調用時,它都會作為第一個參數傳遞給回調函數,第二個參數是pcap頭,它包含一些信息:抓包時間,包多大,等等,這個結構在pcap.h中定義,如下
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};

抓包方式有兩種,一種是每次抓一個包,另一種是循環抓包,分為循環抓有限個數的包,或者是無限循環抓包。其中每次抓一個包使用pcap_next函數。pcap_next()表示只抓取一個數據包,它的第一個參數是session handle,第二個參數是包頭,返回值是包數據。函數原型如下
u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
另一種循環抓包的方法,就是使用pcap_loop和回調函數,代碼樣例參見我整理出的兩個例子。


5.4.網卡設備的設置有兩種方法,第一種方法是用戶直接指定網卡名稱(必須要真實可用),從命令行參數傳遞進去,比如
#include <stdio.h>
#include <pcap.h>


int main(int argc, char *argv[])
{
char *dev = argv[1];


printf("Device: %s\n", dev);
return(0);
}
另一種方法,是讓pcap自己去探測網卡設備,如果出錯,會給出出錯信息,但是這種方法很多情況下不靠譜,對此的改進是,讓pcap探測出所有的網卡設備,讓用戶區選擇使用那個網絡設備抓包,參見下面的代碼
#include <stdio.h>
#include <pcap.h>


int main(int argc, char *argv[])
{
char *dev, errbuf[PCAP_ERRBUF_SIZE];


dev = pcap_lookupdev(errbuf);
if (dev == NULL) {
fprintf(stderr, "Couldn't find default device: %s\n", errbuf);
return(2);
}
printf("Device: %s\n", dev);
return(0);
}


5.5.對我們抓到的數據包,它的結構,大體分為Ethernet header,IP header,TCP header等等,分別對應14,20,20個字節,IP header至少20個字節,TCP頭也至少20個字節。
data=recv_data[42:]這樣做的原因是,recv_data 抓到的都是raw packet, tcp/ip是分了5層,一個udp包,會帶有 14Bytes的Ethenet_II Frame的頭,然后是20個字節的ip包頭,而udp包頭有8個字節,所以偏移量42之后的才是udp的實際內容
tcp包的包頭大小為20Bytes,所以其實際內容在偏移量54之后


5.6.對數據包的解包和組包,需要用到Ethernet header,IP header,TCP header,UDP header等常用數據結構的定義,我們并不需要重新定義這些頭,直接引用相關的頭文件定義就可以了。
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>?

5.6.對我們目前的程序,通常需要從命令行傳人如下參數信息:
? wlan0 ? ? ? ?待抓包的網卡名稱
? tcp port 80 ?過濾表達式
? 10000 or -1 ?抓包模式,是抓指定個數的包(這里是10000個包),還是無限抓包下去
當然,對這些參數,你也可以寫死在程序里。

參考文獻
[1].http://www.tcpdump.org/pcap.html

總結

以上是生活随笔為你收集整理的在Ubuntu 14.04 64位上使用libpcap进行抓包和解包的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。