您的位置:程序门 -> vc/mfc -> 网络编程



求助:用winpcap写的一个程序,功能是发送rst包阻断tcp链接,能运行但是不能阻断tcp链接,怎么回事?


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


求助:用winpcap写的一个程序,功能是发送rst包阻断tcp链接,能运行但是不能阻断tcp链接,怎么回事?
发表于:2007-04-30 15:00:01 楼主
本人在做毕业设计,用winpcap写的一个程序,功能是发送rst包阻断tcp链接,能运行但是不能阻断tcp链接,怎么回事?谁能告诉我哪里出错了,应该怎么改,在线等候答案,急!
谢谢!

代码如下:
#include   "pcap.h "
#include   "stdio.h "
//#include   <afx.h>
/*下边是以太网的协议格式   */
struct   ethernet_header
  {    
 
    u_int8_t   ether_dhost[6];     /*目的以太地址*/
  u_int8_t   ether_shost[6];     /*源以太网地址*/
  u_int16_t   ether_type;     /*以太网类型*/
  };
/*ip地址格式*/
typedef   u_int32_t   in_addr_t;

struct   ip_header
  {
  #ifdef   works_bigendian
    u_int8_t   ip_version:4,     /*version:4*/
              ip_header_length:4;   /*ip协议首部长度*/
  #else
  u_int8_t   ip_header_length:4,
              ip_version:4;
  #endif
  u_int8_t   ip_tos;       /*tos服务质量*/
  u_int16_t   ip_length;     /*总长度*/
  u_int16_t   ip_id;       /*标识*/
  u_int16_t   ip_off;       /*偏移*/
  u_int8_t   ip_ttl;       /*生存时间*/
  u_int8_t   ip_protocol;     /*协议类型*/
  u_int16_t   ip_checksum;     /*校验和*/
                struct   in_addr     ip_source_address;   /*源ip*/
                struct   in_addr     ip_destination_address;   /*目的ip*/
  };
/*关于tcp头部的定义*/
struct   tcp_header
  {  
    u_int16_t   tcp_source_port;
   
    u_int16_t   tcp_destination_port;
   
    u_int32_t   tcp_acknowledgement;//序列号
   
    u_int32_t   tcp_ack;//ack号
  #ifdef   words_bigendian
    u_int8_t   tcp_offset:4   ,
          tcp_reserved:4;
  #else
    u_int8_t   tcp_reserved:4,
          tcp_offset:4;
  #endif
    u_int8_t   tcp_flags;
   
    u_int16_t   tcp_windows;
   
    u_int16_t   tcp_checksum;
   
    u_int16_t   tcp_urgent_pointer;
};

//tcp伪首部
struct   psd_header
{
struct   in_addr   saddr;
struct   in_addr   daddr;
        u_int16_t   mbz;
u_int8_t   ptcl;
u_int32_t   tcpl;
};
struct   ethernet_header   *ethernet_protocol;     /*以太网协议变量*/
struct   ip_header   *ip_protocol;       /*ip协议变量*/
struct   tcp_header   *tcp_protocol   ;           /*tcp协议变量*/
char   *   ip_s_addr;
char   *   ip_d_addr;
//计算校验和
unsigned   short   int   check_sum(unsigned   char*   addr,   size_t   count)
{
unsigned   short   checksum   =   0;
/*   compute   internet   checksum   for   "count "   bytes
*   beginning   at   location   "addr ".
*/
register   long   sum   =   0;
while(   count   >   1   )   {
/*   this   is   the   inner   loop   */
sum   +=   *   (unsigned   short*)   addr++;
count   -=   2;
}
/*   add   left-over   byte,   if   any   */
if(   count   >   0   )
sum   +=   *   (unsigned   char   *)   addr;
/*   fold   32-bit   sum   to   16   bits   */
while   (sum> > 16)
sum   =   (sum   &   0xffff)   +   (sum   > >   16);

checksum   =   ~sum;

return   checksum;
}

//发包函数
void   send_rst_packet()
{
  struct   ethernet_header   *eth_pro;    
  struct   ip_header   *ip_pro;      
  struct   tcp_header   *tcp_pro;    
  struct   psd_header     *   psdheader;  
  struct   psd_header   abc;
  psdheader=&abc;
  char   szsendbuf[100]={0};
  pcap_t   *pcap_handle;
  char   *net_interface;
  char   error_content[100];
  eth_pro=ethernet_protocol;
  ip_pro=ip_protocol;
  tcp_pro=tcp_protocol;
//填充mac地址
  memcpy(eth_pro-> ether_dhost,ethernet_protocol-> ether_shost,sizeof(ethernet_protocol-> ether_shost));          
  memcpy(eth_pro-> ether_shost,ethernet_protocol-> ether_dhost,sizeof(ethernet_protocol-> ether_dhost));          
  eth_pro-> ether_type=ethernet_protocol-> ether_type;      
//填充ip首部          
    ip_pro-> ip_version=ip_protocol-> ip_version;          
    ip_pro-> ip_header_length=ip_protocol-> ip_header_length;
    ip_pro-> ip_tos=ip_protocol-> ip_tos;
    ip_pro-> ip_length=ip_protocol-> ip_length;          
    ip_pro-> ip_id=ip_protocol-> ip_id;          
    ip_pro-> ip_off=ip_protocol-> ip_off;      
    ip_pro-> ip_ttl=ip_protocol-> ip_ttl;          
    ip_pro-> ip_protocol=ip_protocol-> ip_protocol;          
    ip_pro-> ip_checksum=0;          
    ip_pro-> ip_source_address=ip_protocol-> ip_destination_address;//客户端ip地址      
    ip_pro-> ip_destination_address=ip_protocol-> ip_source_address;       //服务器端ip地址
//填充tcp首部          
    tcp_pro-> tcp_destination_port=tcp_protocol-> tcp_source_port;//源端口号,          
    tcp_pro-> tcp_source_port=tcp_protocol-> tcp_destination_port;//目的端口号       (ptcphdr-> dest)这是因为我们要假冒从服务器发出的包      
    tcp_pro-> tcp_acknowledgement=0;//32位序列号       tcpheader.seq+=1;//序列号+2      
    tcp_pro-> tcp_ack=htonl(ntohl(tcp_protocol-> tcp_acknowledgement)+1);//32位确认号          
    tcp_pro-> tcp_reserved=0;          
    tcp_pro-> tcp_flags=4;       //修改这里来实现不同的标志位探测,2是syn,1是fin,16是ack,4是rst      
    tcp_pro-> tcp_windows=0;          
    tcp_pro-> tcp_urgent_pointer=0;          
    tcp_pro-> tcp_checksum=0;    
//填充tcp伪首部      
    psdheader-> saddr=ip_protocol-> ip_source_address;          
    psdheader-> daddr=ip_protocol-> ip_destination_address;          
    psdheader-> mbz=0;          
    psdheader-> ptcl=ip_protocol-> ip_protocol;          
    psdheader-> tcpl=htons(sizeof(tcp_pro));  
//计算校验和  
    memcpy(szsendbuf,       &psdheader,       sizeof(psdheader));          
    memcpy(szsendbuf+sizeof(psdheader),       &tcp_pro,       sizeof(tcp_pro));          
    tcp_pro-> tcp_checksum=check_sum((unsigned   char   *)szsendbuf,sizeof(psdheader)+sizeof(tcp_pro));          
       
    memcpy(szsendbuf,       &ip_pro,       sizeof(ip_pro));          
    memcpy(szsendbuf+sizeof(ip_pro),       &tcp_pro,       sizeof(tcp_pro));          
    memset(szsendbuf+sizeof(ip_pro)+sizeof(tcp_pro),       0,       4);          
    ip_pro-> ip_checksum=check_sum((unsigned   char   *)szsendbuf,       sizeof(ip_pro)+sizeof(tcp_pro));          
    memcpy(szsendbuf,       &ip_pro,       sizeof(ip_pro));      
//使用winpcap库函数发送包
    net_interface=pcap_lookupdev(error_content);
    pcap_handle=pcap_open_live(net_interface,sizeof(szsendbuf),1,1,error_content);
    pcap_sendpacket(pcap_handle,(unsigned   char   *)szsendbuf,sizeof(szsendbuf));
    printf( "ok\n ");
    pcap_close(pcap_handle);
}
发表于:2007-04-30 15:00:241楼 得分:0
/*下边实现tcp数据包分析的函数定义tcp_protocol_packet_callback*/
void   tcp_protocol_packet_callback(u_char   *argument,const   struct   pcap_pkthdr*  
packet_header,const   u_char*   packet_content)
{
 
  u_char   flags;         /*标记*/
  int   header_length;       /*头长度*/
  u_short   source_port;       /*源端口*/
  u_short   destination_port;     /*目的端口*/
  u_short   windows;       /*窗口大小*/
  u_short   urgent_pointer;       /*紧急指针*/
  u_int   sequence;       /*序列号*/  
  u_int   acknowledgement;     /*确认号*/
  u_int16_t       checksum;     /*检验和*/
  tcp_protocol=(struct   tcp_header   *)   (packet_content+14+20);     /*获得tcp首部内容*/
  source_port   =ntohs(tcp_protocol-> tcp_source_port);   /*获得源端口号*/
  destination_port   =ntohs(tcp_protocol-> tcp_destination_port);   /*获得目的端口号*/
  header_length   =tcp_protocol-> tcp_offset   *4;       /*获得首部长度*/
  sequence   =ntohl(tcp_protocol-> tcp_acknowledgement);          
    /*获得序列号*/
  acknowledgement   =ntohl(tcp_protocol-> tcp_ack);   //ack号
  windows   =   ntohs(tcp_protocol-> tcp_windows);
  urgent_pointer   =   ntohs(tcp_protocol-> tcp_urgent_pointer);
  flags   =   tcp_protocol-> tcp_flags;   //flags,发送rst包时值为4
  checksum   =ntohs   (tcp_protocol-> tcp_checksum);
  printf( "***************tcp   protocol   (transprot   layer   )***************\n ");
  printf( "source   port   %d\n ",source_port);
  printf( "destination   port   %d\n ",destination_port);
 
        switch   (destination_port)
      {
    case   80:printf( "protocol   is   http   ");break;
   
    case   21:printf( "protocol   is   ftp ");break;
   
    case   23:printf( "protocol   is   telnet   ");break;
   
    case   25:printf( "protocol   is   smtp ");break;
   
    case   110:printf( "protocol   is   pop3 ");break;
    default   :break;
      }
 

  printf( "sequence   number   %u   \n ",sequence);
  printf( "acknowledgement   number   %u   \n ",acknowledgement);
  printf( "header   length   %d   \n ",header_length);
  printf( "reserved     %d   \n ",tcp_protocol-> tcp_reserved);
  printf( "flags: ");
  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 ");
  printf( "windows   size   :%d   \n ",windows);
  printf( "checksum   :%d\n ",checksum);
  printf( "urgent   pointer   :%d\n ",urgent_pointer);
  if(!strcmp(ip_s_addr, "172.29.3.111 "))//本机ip地址
  {
  ip_d_addr=inet_ntoa(ip_protocol-> ip_destination_address);  
  if(!strcmp(ip_d_addr, "202.102.144.56 "))       //要阻断的网页的ip地址
  {
                  send_rst_packet();//调用发包函数
  }
  }
}

/*下边实现ip数据包分析的函数定义*/
void   ip_protocol_packet_callback(u_char   *argument,const   struct   pcap_pkthdr*  
packet_header,const   u_char*   packet_content)
  {
   
    u_int     header_length;         /*长度*/
    u_int     offset;           /*偏移*/
    u_char     tos;           /*服务质量*/
    u_int16_t   checksum;         /*校验和*/
   
    ip_protocol=(struct   ip_header*)   (packet_content+14);  
              /*获得ip数据包的内容去掉以太头部*/
   
    checksum=ntohs(ip_protocol-> ip_checksum);     /*获得校验和*/
    header_length=ip_protocol-> ip_header_length*4;   /*获得长度*/
    tos=ip_protocol-> ip_tos;         /*获得tos*/
    offset=ntohs(ip_protocol-> ip_off);       /*获得偏移量*/
  printf( "***************ip   protocol   network   layer***************\n   \n ");
  printf( "ip   version   :%d\n ",ip_protocol-> ip_version);
  printf( "header   length   :%d\n ",header_length);
  printf( "tos   :%d\n ",tos);
  printf( "total   length:%d\n ",ntohs(ip_protocol-> ip_length));/*获得总长度*/
  printf( "identification:%d\n ",ntohs(ip_protocol-> ip_id));     /*获得标识*/
  printf( "offset:%d\n ",(offset&0x1fff)*8);         /**/
  printf( "ttl:%d\n ",ip_protocol-> ip_ttl);           /*获得ttl*/    
  printf( "protocol:%d\n ",ip_protocol-> ip_protocol);                   /*获得协议类型*/
 
  printf( "header   checksum:%d\n ",checksum);
  printf( "source   address:%s\n ",inet_ntoa(ip_protocol-> ip_source_address));                     /*
获得源ip地址*/
  printf( "destinastion   address   :%s\n ",inet_ntoa(ip_protocol-> ip_destination_address));  
/*获得目的ip地址*/
  ip_s_addr=inet_ntoa(ip_protocol-> ip_source_address);
 

  switch(ip_protocol-> ip_protocol)
  {
      case   6   :printf( "the   transport   layer   protocol   is   tcp#####################################\n ");
                tcp_protocol_packet_callback(argument,packet_header,packet_content);
               
          break;   /*协议类型是6代表tcp*/
      case   17:printf( "the   transport   layer   protocol   is     udp\n ");break;/*17代表udp*/
        case   1:printf( "the   transport   layer   protocol   is   icmp\n ");break;/*代表icmp*/
      case   2:printf( "the   transport   layer   protocol   is   igmp\n ");break;/*代表igmp*/
    default   :break;
  }

  }


void   ethernet_protocol_packet_callback(u_char   *argument,const   struct   pcap_pkthdr   *packet_header,const   u_char*   packet_content)
  {
  u_short   ethernet_type;           /*以太网协议类型*/
 
  u_char   *mac_string;
  static   int   packet_number=1;
  printf( "*******************************************************************************\n ");
  printf( "the   %d   ip   packet   is   captured,\n ",packet_number);  
  printf( "**********ethernet   protocol   (link   layer)*******************\n ");
  ethernet_protocol   =(struct   ethernet_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;
    case   0x8035   :     printf( "the   network   layer   is   rarp   protocol\n ");break;
    default:   break;
            }
printf( "mac   souce   address   is   :\n ");
mac_string=ethernet_protocol-> ether_shost;
printf( "%02x:%02x:%02x:%02x:%02x:%02x:\n ",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));

/*获得以太网地址*/
 
printf( "mac   destination   address   is   :\n ");
mac_string=ethernet_protocol-> ether_dhost;
printf( "%02x:%02x:%02x:%02x:%02x:%02x:\n ",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
 
/*获得目的端口地址*/
 
    switch   (ethernet_type)
  {case   0x0800:       ip_protocol_packet_callback(argument,packet_header,packet_content);break;
    /*如果上层是ip协议,就调用分析ip协议的函数对ip包进行分析*/    
   
    default   :break;
                }
 
    packet_number++;
}
 

//主函数
main()
{
    pcap_if_t     *alldevs;
    pcap_if_t   *d;
    int   inum=0;
    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);
    }
   

   
 
    /*   打开选择的网卡   */
    d=alldevs;
    adhandle=   pcap_open_live(d-> name,   /*   设备名称*/
                                    65536,       /*   portion   of   the   packet   to   capture.*/  
                                    /*   65536   grants   that   the   whole   packet   will   be   captured   on   allthe   macs.*/
                                    1,               /*   混杂模式*/
                                    1000,           /*   读超时为1秒*/
                                    errbuf       /*   error   buffer*/
                                    )   ;
   
   
    /*   at   this   point,   we   don 't   need   any   more   the   device   list.   free   it   */
    pcap_freealldevs(alldevs);
   
    /*   开始捕获包   */
    pcap_loop(adhandle,   0,   ethernet_protocol_packet_callback,   null);
   
    return   0;
}
发表于:2007-04-30 20:32:522楼 得分:0
太长,帮顶
发表于:2007-04-30 21:28:423楼 得分:0
收藏
发表于:2007-05-03 21:43:424楼 得分:0
windows还是   unix 上的?
发表于:2007-05-06 16:47:435楼 得分:0
windows下的
发表于:2007-05-14 16:57:516楼 得分:0
sinffer

看tcp的crc是不是正确的

大部分sinnffer软件都可以计算crc
发表于:2007-05-17 15:48:187楼 得分:0
该贴是要顶的。
发表于:2007-05-18 15:07:398楼 得分:0
顶贴
发表于:2007-05-20 07:33:429楼 得分:0
mark
发表于:2007-06-03 18:00:4910楼 得分:0
main()函数中的那个真能选择网卡么?
怀疑中.........
if   (pcap_findalldevs(&alldevs,   errbuf)   ==   -1)
    {
        fprintf(stderr, "error   in   pcap_findalldevs:   %s\n ",   errbuf);
        exit(1);
    }
//这里我没看错的话应该是得到一个所有设备的链表alldevs如果没有返回错误  
 
    /*   打开选择的网卡   */
    d=alldevs;

//这里只是将第一个网卡设备给了目标变量可是你怎么知道第一个就是选择的呢?
//这里这个等同于   pcap_lookupdev(),实际上现在是不用的。(至少我很少用)
//pcap_findalldevs()返回的链表中不存在错误的网卡信息,但是会有没有启用的网卡信息
//比如在我自己的机器上如果用d=alldevs;这样d-> name可以看到是我没有用的虚拟猫,就是
//网卡上现在用的比较少的电话线借口,而我真正在使用的是d-> next所指向的宽带连接,而且
//笔记本上还有一个1394接口,如果用这个上网的话,设备会出现在末尾,也就是最后一个指向
//null的alldevs中指向null的节点。
发表于:2007-06-03 18:07:0011楼 得分:0
所以呢选电话线口:d=   alldevs;
选宽带的话:d   =   alldevs-> next;一般机器上都是第二个设备;
选第第三个的话(譬如1394)   d   =   alldevs-> next;   d   =   d-> next;
其实应该让程序列出所有的网络设备后让用户选择一个网卡设备,不然的话如果每一个网卡都设定了ip,这样就不好判断哪个是使用终端了。
发表于:2007-06-03 18:09:4612楼 得分:0
最后,发包程序最好不要用winpcap写,因为默认的winpcap构造报文的函数,参数不够,一般服务器不会响应,有的还会当作冗余包处理,最好用libnet,手动配置报文详细内容。
发表于:2007-06-12 09:40:5213楼 得分:0
确认序列号是否伪装正确,这是我的经验.checksum错误一般系统没有处理.


快速检索

最新资讯
热门点击