linux libpcab怎么抓包,使用winPcap(libpcap)实现的简单抓包程序

这两天做了一个抓包程序,因为现在局域网内都是交换机组网,想在本地监听局域网内其他机器的信息是不可能的,而工作中需要监听一台机器的一个程序和外界的交互信息,解决办法是:在目标机器上运行一个抓包程序,监听的信息,再发给另外一台机器。 其中抓包的主干程序来自网上,经过自己的整理,比网上的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 //#include "remote-ext.h"

#include #include #include

#ifndef WIN32

#include #include //#include //#include #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);

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值