使用WinPcap抓取各種包
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
使用WinPcap抓取各種包
使用WinPcap抓各種包
#include<stdio.h>
#include<iostream>
#define
#include"pcap.h"
#include"remote-ext.h"
#pragmacomment(lib,"Ws2_32.lib")
#pragmacomment(lib,"wpcap.lib")
usingnamespace std;
FILE*fp;
//乙太網協議格式的定義
typedefstructether_header {
u_char ether_shost[6]; // 源地址
u_short ether_type; // 乙太網型別
}ether_header;
//使用者儲存4位元組的IP地址
typedefstructip_address {
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
}ip_address;
//用於儲存IPV4的首部
typedefstructip_header{
#ifdefWORDS_BIGENDIAN
u_char ip_version : 4, header_length :4;
#else
u_char header_length : 4, ip_version : 4;
#endif
u_char ver_ihl; // 版本以及首部長度,各4位
u_char tos; // 服務質量
u_short tlen; // 總長度
u_short identification; //身份識別
u_short offset; // 分組偏移
u_char ttl; // 生命週期
u_char proto; // 協議型別
u_short checksum; // 包頭測驗碼
ip_address saddr; //源IP地址
ip_address daddr; //目的IP地址
u_int op_pad; //可選填充欄位
}ip_header;
//儲存TCP首部
typedefstructtcp_header {
u_short sport;
u_short dport;
u_int sequence; // 序列碼
u_int ack; // 回覆碼
#ifdefWORDS_BIGENDIAN
u_char offset : 4, reserved : 4; //偏移預留
#else
u_char reserved : 4, offset : 4; // 預留偏移
#endif
u_char flags; // 標誌
u_short windows; // 視窗大小
u_short checksum; // 校驗和
u_short urgent_pointer; // 緊急指標
}tcp_header;
typedefstructudp_header {
u_int32_t sport; // 源埠
u_int32_t dport; // 目標埠
u_int8_t zero; // 保留位
u_int8_t proto; // 協議標識
u_int16_t datalen; // UDP資料長度
}udp_header;
typedefstructicmp_header {
u_int8_t type; // ICMP型別
u_int8_t code; // 程式碼
u_int16_t checksum; // 校驗和
u_int16_t identification; // 標識
u_int16_t sequence; // 序列號
u_int32_t init_time; // 發起時間戳
u_int16_t recv_time; // 接受時間戳
u_int16_t send_time; // 傳輸時間戳
}icmp_header;
typedefstructarp_header {
u_int16_t arp_hardware_type;
u_int16_t arp_protocol_type;
u_int8_t arp_hardware_length;
u_int8_t arp_protocol_length;
u_int16_t arp_operation_code;
u_int8_t arp_source_ethernet_address[6];
u_int8_t arp_source_ip_address[4];
u_int8_t arp_destination_ethernet_address[6];
u_int8_t arp_destination_ip_address[4];
}arp_header;
voidtcp_protocol_packet_handle(
u_char *argument,
conststructpcap_pkthdr *packet_header,
constu_char *packet_content
) {
structtcp_header*tcp_protocol;
u_short sport;
u_short dport;
int header_length;
u_short windows;
u_short urgent_pointer;
u_int sequence;
u_int acknowledgement;
u_short checksum;
u_char flags;
printf("===========TCP Protocol===========\n");
tcp_protocol = (structtcp_header*)(packet_content + 14 + 20);
sport = ntohs(tcp_protocol->sport);
dport = ntohs(tcp_protocol->dport);
header_length = tcp_protocol->offset *4;
sequence =ntohl(tcp_protocol->sequence);
acknowledgement =ntohl(tcp_protocol->ack);
windows =ntohs(tcp_protocol->windows);
urgent_pointer =ntohs(tcp_protocol->urgent_pointer);
flags = tcp_protocol->flags;
checksum =ntohs(tcp_protocol->checksum);
fprintf(fp,"%d0%d%d%c%d", header_length, sport, dport,flags, windows);
switch(dport) {
default:
break;
}
if(flags & 0x08) printf("PSH");
if(flags & 0x10) printf("ACK");
if(flags & 0x02) printf("SYN");
if(flags & 0x20) printf("URG");
if(flags & 0x01) printf("FIN");
if(flags & 0x04) printf("RST");
printf("\n");
}
voidudp_protocol_packet_handle(
u_char *argument,
conststructpcap_pkthdr *packet_header,
constu_char *packet_content
) {
structudp_header*udp_protocol;
u_short sport;
u_short dport;
u_short datalen;
udp_protocol = (structudp_header*)(packet_content + 14 + 20);
sport = ntohs(udp_protocol->sport);
dport = ntohs(udp_protocol->dport);
datalen =ntohs(udp_protocol->datalen);
fprintf(fp,"0%d%d%d",datalen, sport, dport);
}
voidarp_protocol_packet_handle(
u_char *argument,
conststructpcap_pkthdr *packet_header,
constu_char *packet_content
) {
structarp_header*arp_protocol;
u_short protocol_type;
u_short hardware_type;
u_short operation_code;
u_char hardware_length;
u_char protocol_length;
structtm* ltime;
char timestr[16];
time_t local_tv_sec;
local_tv_sec =packet_header->ts.tv_sec;
ltime = localtime(&local_tv_sec);
strftime(timestr,sizeof(timestr),"%H:%M:%S", ltime);
printf("-------- ARP協議 --------\n");
arp_protocol = (structarp_header*)(packet_content + 14);
hardware_type =ntohs(arp_protocol->arp_hardware_type);
protocol_type =ntohs(arp_protocol->arp_protocol_type);
operation_code =ntohs(arp_protocol->arp_operation_code);
hardware_length =arp_protocol->arp_hardware_length;
protocol_length =arp_protocol->arp_protocol_length;
fprintf(fp,"%d%s", protocol_length, timestr);
switch (operation_code)
{
case 1:
printf("ARP請求協議\n");
break;
case 2:
printf("ARP應答協議\n");
break;
case 3:
printf("RARP請求協議\n");
break;
case 4:
printf("RARP應答協議\n");
break;
default:
break;
}
}
voidicmp_protocol_packet_handle(
u_char *argument,
conststructpcap_pkthdr *packet_header,
constu_char *packet_content
) {
structicmp_header*icmp_protocol;
u_short type;
u_short datalen;
u_int init_time;
u_int recv_time;
u_int send_time;
icmp_protocol = (structicmp_header*)(packet_content + 14 + 20);
datalen =sizeof(icmp_protocol);
type = icmp_protocol->type;
init_time =icmp_protocol->init_time;
recv_time =icmp_protocol->recv_time;
send_time =icmp_protocol->send_time;
fprintf(fp,"%d%c%d%d%d", datalen, type, init_time,recv_time, send_time);
// printf("===========ICMPProtocol==========\n");
switch(icmp_protocol->type) {
case 8:
//回顯請求報文
break;
case 0:
//回顯應答報文
break;
default:
break;
}
}
voidip_protocol_packet_handle(
u_char *argument,
conststructpcap_pkthdr *packet_header,
constu_char *packet_content
) {
structip_header*ip_protocol;
u_int header_length;
u_char tos;
u_short checksum;
ip_address saddr;
ip_address daddr;
u_char ttl;
u_short tlen;
u_short identification;
u_short offset;
printf("===========IP Protocol===========\n");
ip_protocol = (structip_header*)(packet_content + 14);
header_length =ip_protocol->header_length * 4;
checksum =ntohs(ip_protocol->checksum);
tos = ip_protocol->tos;
offset =ntohs(ip_protocol->offset);
saddr = ip_protocol->saddr;
daddr = ip_protocol->daddr;
ttl = ip_protocol->ttl;
identification =ip_protocol->identification;
tlen = ip_protocol->tlen;
offset = ip_protocol->offset;
fprintf(fp,"%d%d%c%d%d%d", saddr, daddr, ttl,identification, tlen, offset);
switch(ip_protocol->proto) {
case 6:
tcp_protocol_packet_handle(argument,packet_header,packet_content);
break;
case 17:
udp_protocol_packet_handle(argument,packet_header,packet_content);
break;
case 1:
icmp_protocol_packet_handle(argument,packet_header,packet_content);
break;
default:
break;
}
}
voidethernet_protocol_packet_handle (
u_char *argument,
conststructpcap_pkthdr *packet_header,
constu_char *packet_content
) {
u_short ethernet_type; // 乙太網型別
structether_header*ethernet_protocol; // 乙太網協議變數
u_char *mac_string; // 乙太網地址
ethernet_protocol = (structether_header*)packet_content; //獲取乙太網資料內容
printf("Ethernet type is : \n");
ethernet_type =ntohs(ethernet_protocol->ether_type); //獲取乙太網型別
printf(" %04x\n", ethernet_type);
switch(ethernet_type) {
case 0x0800:
printf("The network layer is IP protocol\n");
break;
case 0x0806:
printf("The network layer is ARP protocol\n");
break;
default:
break;
}
// 獲取乙太網源地址
// printf("MAC Source Address is :\n");
mac_string =ethernet_protocol->ether_shost;
fprintf(fp,"%02x:%02x:%02x:%02x:%02x:%02x",
*mac_string,
*(mac_string + 1),
*(mac_string + 2),
*(mac_string + 3),
*(mac_string + 4),
*(mac_string + 5)
);
// 獲取乙太網目的地址
// printf("MAC Target Address is :\n");
mac_string = ethernet_protocol->ether_dhost;
fprintf(fp,"%02x:%02x:%02x:%02x:%02x:%02x",
*mac_string,
*(mac_string + 1),
*(mac_string + 2),
*(mac_string + 3),
*(mac_string + 4),
*(mac_string + 5)
);
fprintf(fp,"%d",sizeof(packet_content));
switch(ethernet_type) {
case 0x0800:
ip_protocol_packet_handle(argument,packet_header,packet_content);
break;
default:
break;
}
}
intmain() {
pcap_if_t *alldevs;
pcap_if_t *d;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
int inum;
int i = 0;
u_int netmask;
char packet_filter[] ="ip and tcp";
structbpf_programfcode;
int res;
structpcap_pkthdr*header;
structtm *ltime;
constu_char *pkt_data;
time_t local_tv_sec;
char timestr[16];
ip_header *ih;
// 獲得裝置列表pcap_findalldevs_ex()
if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL, &alldevs, errbuf)== -1) {
fprintf(stderr,"Errorin pcap_findalldevs: %s\n", errbuf);
exit(1);
}
for(d = alldevs; d; d = d->next) {
printf("%d. %s", ++i, d->name);
if(d->description) {
printf("(%s)\n", d->description);
}
else {
printf("No description available\n");
}
}
if(0 == i) {
printf("\nNo interface found!Make sure WinPcap is installed\n");
return -1;
}
printf("Enter the interface number(1-%d):",i);
scanf_s("%d", &inum);
if(inum < 1 || inum > i) {
printf("\nInterface number out of range.\n");
pcap_freealldevs(alldevs);
return -1;
}
for(d = alldevs, i = 0; i < inum-1; d=d->next, i++);
// 跳轉到該裝置,開啟介面卡
// 裝置名,要捕捉的資料包的部分(65536保證能捕獲到不同資料鏈路層上的每個資料包的全部內容),混雜模式,讀取超時時間,錯誤緩衝池
if((adhandle = pcap_open_live(d->name, 65536, 1, 1000, errbuf)) ==NULL) {
fprintf(stderr,"\nUnableto open the adapter.%s is not supported by WinPcap\n", errbuf);
pcap_freealldevs(alldevs);
return -1;
}
// 檢查資料鏈路層(只考慮了乙太網)
if(pcap_datalink(adhandle) !=DLT_EN10MB) {
fprintf(stderr,"\nThisprogram works only on Ethernet networks.\n");
pcap_freealldevs(alldevs);
return -1;
}
if(d->addresses !=NULL){
//獲得介面的第一個地址的掩碼
netmask = ((structsockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
}
else {
netmask = 0xffffff;
}
/*
//編譯過濾器
if(pcap_compile(adhandle, &fcode,packet_filter, 1, netmask) < 0) {
fprintf(stderr, "\nUnable tocompile the packet filter.Check the syntax\n");
pcap_freealldevs(alldevs);
return -1;
}
//設定過濾器
if(pcap_setfilter(adhandle, &fcode)< 0) {
fprintf(stderr, "\nError settingthe filter.\n");
pcap_freealldevs(alldevs);
return -1;
}
printf("\nlistenting on %s...\n",d->description);
*/
fp = freopen("in.txt","w",stdin);
while((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0){
//請求超時
if(0 == res) {
continue;
}
//分析資料包
ethernet_protocol_packet_handle(NULL, header, pkt_data);
//將時間戳轉換成可識別的格式
local_tv_sec =header->ts.tv_sec;
ltime =localtime(&local_tv_sec);
strftime(timestr,sizeof(timestr),"%H:%M:%S", ltime);
ih = (ip_header *)(pkt_data + 14);//乙太網頭部長度
//輸出時間和IP資訊
printf("%s.%.6d len:%d ", timestr, header->ts.tv_usec,header->len);
printf("%d.%d.%d.%d -> %d.%d.%d.%d\n",
ih->saddr.byte1,
ih->saddr.byte2,
ih->saddr.byte3,
ih->saddr.byte4,
ih->daddr.byte1,
ih->daddr.byte2,
ih->daddr.byte3,
ih->daddr.byte4);
}
if(-1 == res) {
printf("Error reading the packet:%s\n",pcap_geterr(adhandle));
return -1;
}
pcap_freealldevs(alldevs);
fclose(fp);
fclose(stdin);
return 0;
}