Chinaunix首页 | 论坛 | 博客
  • 博客访问: 358220
  • 博文数量: 46
  • 博客积分: 4936
  • 博客等级: 上校
  • 技术积分: 575
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-25 20:14
文章分类

全部博文(46)

文章存档

2012年(4)

2011年(1)

2010年(23)

2009年(18)

分类: 系统运维

2009-11-07 15:13:02

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

}

 
阅读(10420) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~