使用winPcap(libpcap)實現的簡單抓包程式
阿新 • • 發佈:2019-01-05
這兩天做了一個抓包程式,因為現在區域網內都是交換機組網,想在本地監聽區域網內其他機器的資訊是不可能的,而工作中需要監聽一臺機器的一個程式和外界的互動資訊,解決辦法是:在目標機器上執行一個抓包程式,監聽的資訊,再發給另外一臺機器。 其中抓包的主幹程式來自網上,經過自己的整理,比網上的demo程式功能更多一些,因此拿出來跟朋友們共享。
#define PA_ICMP 1 //控制資訊協議
#define PA_TCP 6 //傳輸控制協議
#define PA_EGP 8 //外部閘道器協議
#define PA_IGP 9 //內部閘道器協議
#define PA_UDP 17 //使用者資料報協議 typedef struct ethhdr {
unsigned char eh_dest[6]; /* destination eth addr */
unsigned char eh_source[6]; /* source ether addr */
unsigned short eh_proto; /* packet type ID field */
}ETH_HDR;
typedef struct ip_hdr //IP頭
{
unsigned char h_lenver; //4位首部長度+4位IP版本號
unsigned char tos; //8位服務型別TOS
unsigned short total_len; //16位總長度(位元組)
unsigned short ident; //16位標識
unsigned short frag_and_flags; //3位標誌位+13報片偏移
unsigned char ttl; //8位生存時間 TTL
unsigned char proto; //8位協議 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校驗和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HDR; typedef struct udp_hdr
{
unsigned short uh_sport;
unsigned short uh_dport;
unsigned short uh_length;
unsigned short uh_checksum;
}UDP_HDR; typedef struct tcp_hdr //TCP頭
{
unsigned short th_sport; //16位源埠
unsigned short th_dport; //16位目的埠
unsigned int th_seq; //32位序列號
unsigned int th_ack; //32位確認號
unsigned char th_lenres; //4位首部長度/6位保留字
unsigned char th_flag; //6位標誌位
unsigned short th_win; //16位視窗大小
unsigned short th_sum; //16位校驗和
unsigned short th_urp; //16位緊急資料偏移量
}TCP_HDR;
#include <pcap.h>
//#include "remote-ext.h"
#include <string.h>
#include <stdlib.h>
#include <time.h> #ifndef WIN32
#include <netinet/in.h>
#include <unistd.h>
//#include <sys/socket.h>
//#include <sys/types.h>
#else
//#include
#pragma comment(lib, "wpcap.lib")
#pragma comment(lib, "ws2_32.lib")
#endif //by rainfish
//from rainfish.cublog.cn
/* 資料包處理函式宣告 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); /* 來自 tcptracert, 把數字IP地址轉換為點格式 */
#define IPTOSBUFFERS 12
char* iptos(u_long in)
{
static char output[IPTOSBUFFERS][3*4+3+1];
static short which;
u_char *p;
p = (u_char *)∈
which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output[which];
}
/* Print all the available information on the given interface */
void ifprint(pcap_if_t *d)
{
pcap_addr_t *a;
/* 名稱 */
printf("%s\n",d->name);
/* 描述 */
if (d->description)
printf("\tDescription: %s\n",d->description);
/* 迴環地址 */
printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
/* IP 地址 */
for(a=d->addresses;a;a=a->next) {
printf("\tAddress Family: #%d\n",a->addr->sa_family);
switch(a->addr->sa_family)
{
case AF_INET:
printf("\tAddress Family Name: AF_INET\n");
if (a->addr)
/* Y- IP 地址 */
printf("\tAddress: %s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
if (a->netmask)
/* Y- 掩碼 */
printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
if (a->broadaddr)
/* Y- 廣播地址 */
printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
if (a->dstaddr)
/* Y - 目標地址 */
printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
break;
default:
/* 未知 */
printf("\tAddress Family Name: Unknown\n");
break;
}
}
printf("\n");
} bool check_ip(pcap_if_t *d, const char* ip)
{
bool ret = false;
char szip[32];
pcap_addr_t *a;
/* 名稱 */
printf("%s\n",d->name);
/* 描述 */
if (d->description)
printf("\tDescription: %s\n",d->description);
/* 迴環地址 */
printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
/* IP 地址 */
for(a=d->addresses;a;a=a->next) {
printf("\tAddress Family: #%d\n",a->addr->sa_family);
switch(a->addr->sa_family)
{
case AF_INET:
printf("\tAddress Family Name: AF_INET\n");
if (a->addr)
/* Y- IP 地址 */
{
strcpy(szip, iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
printf("\tAddress: %s\n", szip); if ( strcmp(szip, ip) == 0 )
ret = true;
}
if (a->netmask)
/* Y- 掩碼 */
printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
if (a->broadaddr)
/* Y- 廣播地址 */
printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
if (a->dstaddr)
/* Y - 目標地址 */
printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
break;
default:
/* 未知 */
printf("\tAddress Family Name: Unknown\n");
break;
}
}
printf("\n"); return ret;
} main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
/* 獲取裝置列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
} inum = 0; /* 遍歷所有元素 */
for(d=alldevs;d;d=d->next)
{
ifprint(d);
} /* 遍歷所有元素 */
for(d=alldevs;d;d=d->next)
{
//找到有這個ip的網絡卡
if ( check_ip(d, "192.168.1.100") )
break;
}
/* 轉到選擇的裝置 */
//for(d=alldevs, i=0; i< inum;d=d->next, i++);
/* 開啟裝置 */
if ( (adhandle= pcap_open_live(d->name, //裝置名
65536, // 捕捉完整的資料包
1, // 混在模式
1000, // 讀入超時
errbuf // 錯誤緩衝
) ) == NULL)
// if ((adhandle = pcap_open(d->name, /* name of the device */
// 65536, /* portion of the packet to capture */
// /* 65535 guarantees that the whole packet will be captured on all the link layers */
// PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
// 1000, /* read timeout */
// NULL, /* authentication on the remote machine */
// errbuf /* error buffer */
// )) == NULL)
{
/* Y- 開啟失敗*/
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n");
/* 釋放列表 */
pcap_freealldevs(alldevs);
return -1;
}
// dst net(x.x.x.x||y.y.y.y)要多個地址過濾,
// dst net(x.x.x.x)||src net(y.y.y.y)或條件過濾
// dst net(x.x.x.x)&&src net(y.y.y.y)與條件過濾
char packet_filter[] = "ip && dst net(192.168.1.100) && port 8873";
// char packet_filter[] = "ip && dst net(192.168.1.111) && port (1160||1147)";
struct bpf_program fcode;
u_int netmask;
/* complie the filter */
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)
{
fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
/* Free the devices list */
pcap_freealldevs(alldevs);
return -1;
}
/* set the filter */
if (pcap_setfilter(adhandle, &fcode) < 0)
{
fprintf(stderr, "\nError setting the filter.\n");
/* Free the devices list */
pcap_freealldevs(alldevs);
return -1;
} printf("\nlistening on %s...\n", d->description);
/* 我們已經不需要裝置列表了, 釋放它 */
pcap_freealldevs(alldevs);
/* 開始捕捉 */
pcap_loop(adhandle, 0, packet_handler, NULL);
return 0;
} /* 處理資料包的回撥函式*/
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
IP_HDR* ip_head = (IP_HDR*)(pkt_data + sizeof(ETH_HDR));
unsigned short us_srcport = 0;
unsigned short us_dstport = 0; struct tm *ltime;
char timestr[16]; // if ( (strcmp(iptos(ip_head->sourceIP), "192.168.1.111") == 0 ||
// strcmp(iptos(ip_head->destIP), "192.168.1.111") == 0 ) )
// return;
/* 轉換時間戳為可以閱讀的格式 */
// ltime=localtime(&header->ts.tv_sec);
// strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
//
// printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
if ( ip_head->proto == PA_UDP)
{
UDP_HDR* up_head = (UDP_HDR*)(pkt_data + sizeof(ETH_HDR) + sizeof(IP_HDR));
us_srcport = ntohs(up_head->uh_sport);
us_dstport = ntohs(up_head->uh_dport);
unsigned short u_packlen = ntohs(up_head->uh_length); //if ( us_dstport == 4000 || us_srcport == 4000 )
{
/* 轉換時間戳為可以閱讀的格式 */
ltime=localtime(&header->ts.tv_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
printf("udp ");
printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
printf("%s:%d-->%s:%d\n", iptos(ip_head->sourceIP), us_srcport,
iptos(ip_head->destIP), us_dstport);
}
}
else
if ( ip_head->proto == PA_TCP )
{
TCP_HDR* tcp_head = (TCP_HDR*)(pkt_data + sizeof(ETH_HDR) + sizeof(IP_HDR)); //printf("tcp ");
us_srcport = ntohs(tcp_head->th_sport);
us_dstport = ntohs(tcp_head->th_dport); //if ( us_dstport == 4408 || us_srcport == 4408 )
{
/* 轉換時間戳為可以閱讀的格式 */
ltime=localtime(&header->ts.tv_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
printf("tcp ");
printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
printf("%s:%d-->%s:%d\n", iptos(ip_head->sourceIP), us_srcport,
iptos(ip_head->destIP), us_dstport);
}
} // if ( ip_head->proto == PA_UDP || ip_head->proto == PA_TCP )
// printf("%s:%d-->%s:%d\n", iptos(ip_head->sourceIP), us_srcport,
// iptos(ip_head->destIP), us_dstport);
}
#define PA_TCP 6 //傳輸控制協議
#define PA_EGP 8 //外部閘道器協議
#define PA_IGP 9 //內部閘道器協議
#define PA_UDP 17 //使用者資料報協議 typedef struct ethhdr {
unsigned char eh_dest[6]; /* destination eth addr */
unsigned char eh_source[6]; /* source ether addr */
unsigned short eh_proto; /* packet type ID field */
}ETH_HDR;
typedef struct ip_hdr //IP頭
{
unsigned char h_lenver; //4位首部長度+4位IP版本號
unsigned char tos; //8位服務型別TOS
unsigned short total_len; //16位總長度(位元組)
unsigned short ident; //16位標識
unsigned short frag_and_flags; //3位標誌位+13報片偏移
unsigned char ttl; //8位生存時間 TTL
unsigned char proto; //8位協議 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校驗和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HDR; typedef struct udp_hdr
{
unsigned short uh_sport;
unsigned short uh_dport;
unsigned short uh_length;
unsigned short uh_checksum;
}UDP_HDR; typedef struct tcp_hdr //TCP頭
{
unsigned short th_sport; //16位源埠
unsigned short th_dport; //16位目的埠
unsigned int th_seq; //32位序列號
unsigned int th_ack; //32位確認號
unsigned char th_lenres; //4位首部長度/6位保留字
unsigned char th_flag; //6位標誌位
unsigned short th_win; //16位視窗大小
unsigned short th_sum; //16位校驗和
unsigned short th_urp; //16位緊急資料偏移量
}TCP_HDR;
#include <pcap.h>
//#include "remote-ext.h"
#include <string.h>
#include <stdlib.h>
#include <time.h> #ifndef WIN32
#include <netinet/in.h>
#include <unistd.h>
//#include <sys/socket.h>
//#include <sys/types.h>
#else
//#include
#pragma comment(lib, "wpcap.lib")
#pragma comment(lib, "ws2_32.lib")
#endif //by rainfish
//from rainfish.cublog.cn
/* 資料包處理函式宣告 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); /* 來自 tcptracert, 把數字IP地址轉換為點格式 */
#define IPTOSBUFFERS 12
char* iptos(u_long in)
{
static char output[IPTOSBUFFERS][3*4+3+1];
static short which;
u_char *p;
p = (u_char *)∈
which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output[which];
}
/* Print all the available information on the given interface */
void ifprint(pcap_if_t *d)
{
pcap_addr_t *a;
/* 名稱 */
printf("%s\n",d->name);
/* 描述 */
if (d->description)
printf("\tDescription: %s\n",d->description);
/* 迴環地址 */
printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
/* IP 地址 */
for(a=d->addresses;a;a=a->next) {
printf("\tAddress Family: #%d\n",a->addr->sa_family);
switch(a->addr->sa_family)
{
case AF_INET:
printf("\tAddress Family Name: AF_INET\n");
if (a->addr)
/* Y- IP 地址 */
printf("\tAddress: %s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
if (a->netmask)
/* Y- 掩碼 */
printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
if (a->broadaddr)
/* Y- 廣播地址 */
printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
if (a->dstaddr)
/* Y - 目標地址 */
printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
break;
default:
/* 未知 */
printf("\tAddress Family Name: Unknown\n");
break;
}
}
printf("\n");
} bool check_ip(pcap_if_t *d, const char* ip)
{
bool ret = false;
char szip[32];
pcap_addr_t *a;
/* 名稱 */
printf("%s\n",d->name);
/* 描述 */
if (d->description)
printf("\tDescription: %s\n",d->description);
/* 迴環地址 */
printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
/* IP 地址 */
for(a=d->addresses;a;a=a->next) {
printf("\tAddress Family: #%d\n",a->addr->sa_family);
switch(a->addr->sa_family)
{
case AF_INET:
printf("\tAddress Family Name: AF_INET\n");
if (a->addr)
/* Y- IP 地址 */
{
strcpy(szip, iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
printf("\tAddress: %s\n", szip); if ( strcmp(szip, ip) == 0 )
ret = true;
}
if (a->netmask)
/* Y- 掩碼 */
printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
if (a->broadaddr)
/* Y- 廣播地址 */
printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
if (a->dstaddr)
/* Y - 目標地址 */
printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
break;
default:
/* 未知 */
printf("\tAddress Family Name: Unknown\n");
break;
}
}
printf("\n"); return ret;
} main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum;
int i=0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
/* 獲取裝置列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
} inum = 0; /* 遍歷所有元素 */
for(d=alldevs;d;d=d->next)
{
ifprint(d);
} /* 遍歷所有元素 */
for(d=alldevs;d;d=d->next)
{
//找到有這個ip的網絡卡
if ( check_ip(d, "192.168.1.100") )
break;
}
/* 轉到選擇的裝置 */
//for(d=alldevs, i=0; i< inum;d=d->next, i++);
/* 開啟裝置 */
if ( (adhandle= pcap_open_live(d->name, //裝置名
65536, // 捕捉完整的資料包
1, // 混在模式
1000, // 讀入超時
errbuf // 錯誤緩衝
) ) == NULL)
// if ((adhandle = pcap_open(d->name, /* name of the device */
// 65536, /* portion of the packet to capture */
// /* 65535 guarantees that the whole packet will be captured on all the link layers */
// PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
// 1000, /* read timeout */
// NULL, /* authentication on the remote machine */
// errbuf /* error buffer */
// )) == NULL)
{
/* Y- 開啟失敗*/
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n");
/* 釋放列表 */
pcap_freealldevs(alldevs);
return -1;
}
// dst net(x.x.x.x||y.y.y.y)要多個地址過濾,
// dst net(x.x.x.x)||src net(y.y.y.y)或條件過濾
// dst net(x.x.x.x)&&src net(y.y.y.y)與條件過濾
char packet_filter[] = "ip && dst net(192.168.1.100) && port 8873";
// char packet_filter[] = "ip && dst net(192.168.1.111) && port (1160||1147)";
struct bpf_program fcode;
u_int netmask;
/* complie the filter */
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)
{
fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
/* Free the devices list */
pcap_freealldevs(alldevs);
return -1;
}
/* set the filter */
if (pcap_setfilter(adhandle, &fcode) < 0)
{
fprintf(stderr, "\nError setting the filter.\n");
/* Free the devices list */
pcap_freealldevs(alldevs);
return -1;
} printf("\nlistening on %s...\n", d->description);
/* 我們已經不需要裝置列表了, 釋放它 */
pcap_freealldevs(alldevs);
/* 開始捕捉 */
pcap_loop(adhandle, 0, packet_handler, NULL);
return 0;
} /* 處理資料包的回撥函式*/
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
IP_HDR* ip_head = (IP_HDR*)(pkt_data + sizeof(ETH_HDR));
unsigned short us_srcport = 0;
unsigned short us_dstport = 0; struct tm *ltime;
char timestr[16]; // if ( (strcmp(iptos(ip_head->sourceIP), "192.168.1.111") == 0 ||
// strcmp(iptos(ip_head->destIP), "192.168.1.111") == 0 ) )
// return;
/* 轉換時間戳為可以閱讀的格式 */
// ltime=localtime(&header->ts.tv_sec);
// strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
//
// printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
if ( ip_head->proto == PA_UDP)
{
UDP_HDR* up_head = (UDP_HDR*)(pkt_data + sizeof(ETH_HDR) + sizeof(IP_HDR));
us_srcport = ntohs(up_head->uh_sport);
us_dstport = ntohs(up_head->uh_dport);
unsigned short u_packlen = ntohs(up_head->uh_length); //if ( us_dstport == 4000 || us_srcport == 4000 )
{
/* 轉換時間戳為可以閱讀的格式 */
ltime=localtime(&header->ts.tv_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
printf("udp ");
printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
printf("%s:%d-->%s:%d\n", iptos(ip_head->sourceIP), us_srcport,
iptos(ip_head->destIP), us_dstport);
}
}
else
if ( ip_head->proto == PA_TCP )
{
TCP_HDR* tcp_head = (TCP_HDR*)(pkt_data + sizeof(ETH_HDR) + sizeof(IP_HDR)); //printf("tcp ");
us_srcport = ntohs(tcp_head->th_sport);
us_dstport = ntohs(tcp_head->th_dport); //if ( us_dstport == 4408 || us_srcport == 4408 )
{
/* 轉換時間戳為可以閱讀的格式 */
ltime=localtime(&header->ts.tv_sec);
strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
printf("tcp ");
printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len);
printf("%s:%d-->%s:%d\n", iptos(ip_head->sourceIP), us_srcport,
iptos(ip_head->destIP), us_dstport);
}
} // if ( ip_head->proto == PA_UDP || ip_head->proto == PA_TCP )
// printf("%s:%d-->%s:%d\n", iptos(ip_head->sourceIP), us_srcport,
// iptos(ip_head->destIP), us_dstport);
}