用winpcap发送UDP数据包

今天尝试用winpcap提供的pcap_sendpacket函数成功发送一个udp数据包到目的地址。 下面就来回顾一下过程。

首先用pcap_findalldevs得到网络接口,比如在我的机器上得到这样的结果:

1: \Device\NPF_GenericDialupAdapter
2: \Device\NPF_{06864041-9387-44DC-AF44-37779B0F2E9E}

现在我们及应用"\Device\NPF_{06864041-9387-44DC-AF44-37779B0F2E9E}“对应的接口发送数据。

由于发送数据必须自己构建以太网数据头, IP数据包头 和 UDP数据包头, 数据结构大概是这个样子的。

" 以太网数据头 |  IP数据头 | UDP数据包头 | 数据"

以太网数据头结构如下

struct   ether_header{
 u_char   ether_dhost[ETHER_ADDR_LEN];
 u_char   ether_shost[ETHER_ADDR_LEN];
 u_short   ether_type;  //如果上一层为IP协议。则ether_type的值就是0x0800
};

以太网地址填充什么数据, 我不是很清楚, 你可以填上实际的地址, 我这里全部填1.

IP数据头

struct ip_header  //小端模式__LITTLE_ENDIAN
{
 unsigned   char  ihl:4;    //ip   header   length   
 unsigned   char  version:4;   //version  
 u_char    tos;    //type   of   service  
 u_short    tot_len;   //total   length  
 u_short    id;     //identification  
 u_short    frag_off;   //fragment   offset  
 u_char    ttl;    //time   to   live  
 u_char    protocol;   //protocol   type  
 u_short    check;    //check   sum  
 u_int    saddr;    //source   address  
 u_int    daddr;    //destination   address  
};

tot_len为 整个IP数据包长度 (IP数据头 | UDP数据包头 | 数据)

ihl 为IP数据头的总长度 除以4.  (4字节对齐)

check 为在数据填好后, check为0 时的校验和, 是对于IP数据头。

 

  1. u_int16_t in_cksum (u_int16_t * addr, int len)  
  2. {  
  3.  int     nleft = len;  
  4.  u_int32_t sum = 0;  
  5.  u_int16_t *w = addr;  
  6.  u_int16_t answer = 0;  
  7.   
  8.  /* 
  9.  * Our algorithm is simple, using a 32 bit accumulator (sum), we add 
  10.  * sequential 16 bit words to it, and at the end, fold back all the 
  11.  * carry bits from the top 16 bits into the lower 16 bits. 
  12.  */  
  13.  while (nleft > 1) {  
  14.   sum += *w++;  
  15.   nleft -= 2;  
  16.  }  
  17.  /* mop up an odd byte, if necessary */  
  18.  if (nleft == 1) {  
  19.   * (unsigned char *) (&answer) = * (unsigned char *) w;  
  20.   sum += answer;  
  21.  }  
  22.   
  23.  /* add back carry outs from top 16 bits to low 16 bits */  
  24.  sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */  
  25.  sum += (sum >> 16);     /* add carry */  
  26.  answer = ~sum;     /* truncate to 16 bits */  
  27.  return (answer);  
  28. }  

 

protocol 为IPPROTO_UDP。

UDP数据包头

struct udphdr
{
  u_int16_t source;         /* source port */
  u_int16_t dest;   /* destination port */
  u_int16_t len;            /* udp length */
  u_int16_t checkl;         /* udp checksum */
};

len 为UDP数据包长度,

checkl  校验和(IP为首部 | UDP数据包头 | 数据), 这个比较特殊一点, 要加一个伪首部

struct Psd_Header {
 ULONG sourceip; //源IP地址
 ULONG destip; //目的IP地址
 BYTE mbz; //置空(0)
 BYTE ptcl; //协议类型
 USHORT plen; //TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度 单位:字节)
};

plen 和UDP长度是一样的。

当把这些都填充好了, 就可以用pcap_sendpacket发送出去了

 

  1. #define HAVE_REMOTE  
  2.  
  3. #include <pcap.h>  
  4. #pragma comment(lib, "wpcap.lib")  
  5. #include <stdio.h>  
  6.  
  7. #pragma comment(lib, "Ws2_32.lib")  
  8.   
  9.   
  10. //typedef void(* pcap_handler)(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)   
  11. void my_pcap_handler(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);  
  12.  
  13. #define ETHER_ADDR_LEN 6  
  14. //from linux's ethernet.h  
  15. #define ETHERTYPE_PUP           0x0200          /* Xerox PUP */  
  16. #define ETHERTYPE_SPRITE        0x0500          /* Sprite */  
  17. #define ETHERTYPE_IP            0x0800          /* IP */  
  18. #define ETHERTYPE_ARP           0x0806          /* Address resolution */  
  19. #define ETHERTYPE_REVARP        0x8035          /* Reverse ARP */  
  20. #define ETHERTYPE_AT            0x809B          /* AppleTalk protocol */  
  21. #define ETHERTYPE_AARP          0x80F3          /* AppleTalk ARP */  
  22. #define ETHERTYPE_VLAN          0x8100          /* IEEE 802.1Q VLAN tagging */  
  23. #define ETHERTYPE_IPX           0x8137          /* IPX */  
  24. #define ETHERTYPE_IPV6          0x86dd          /* IP protocol version 6 */  
  25. #define ETHERTYPE_LOOPBACK      0x9000          /* used to test interfaces */  
  26.   
  27. struct   ether_header{   
  28.     u_char   ether_dhost[ETHER_ADDR_LEN];   
  29.     u_char   ether_shost[ETHER_ADDR_LEN];   
  30.     u_short   ether_type;  //如果上一层为IP协议。则ether_type的值就是0x0800  
  31. };  
  32.   
  33. char* prase_ether_host(u_char ether_host[ETHER_ADDR_LEN], char* buffer);  
  34.   
  35. struct ip_header  //小端模式__LITTLE_ENDIAN  
  36. {   
  37.     unsigned   char     ihl:4;              //ip   header   length      
  38.     unsigned   char     version:4;          //version     
  39.     u_char              tos;                //type   of   service     
  40.     u_short             tot_len;            //total   length     
  41.     u_short             id;                 //identification     
  42.     u_short             frag_off;           //fragment   offset     
  43.     u_char              ttl;                //time   to   live     
  44.     u_char              protocol;           //protocol   type     
  45.     u_short             check;              //check   sum     
  46.     u_int               saddr;              //source   address     
  47.     u_int               daddr;              //destination   address     
  48. };  
  49.   
  50.   
  51. struct tcphdr //小端模式__LITTLE_ENDIAN  
  52. {  
  53.     u_int16_t source;  
  54.     u_int16_t dest;  
  55.     u_int32_t seq;  
  56.     u_int32_t ack_seq;  
  57.     u_int16_t res1:4;  
  58.     u_int16_t doff:4;  
  59.     u_int16_t fin:1;  
  60.     u_int16_t syn:1;  
  61.     u_int16_t rst:1;  
  62.     u_int16_t psh:1;  
  63.     u_int16_t ack:1;  
  64.     u_int16_t urg:1;  
  65.     u_int16_t res2:2;  
  66.     u_int16_t window;  
  67.     u_int16_t check;  
  68.     u_int16_t urg_ptr;  
  69. };  
  70.   
  71.   
  72.   
  73. struct udphdr  
  74. {  
  75.   u_int16_t source;         /* source port */  
  76.   u_int16_t dest;           /* destination port */  
  77.   u_int16_t len;            /* udp length */  
  78.   u_int16_t checkl;         /* udp checksum */  
  79. };  
  80.   
  81. char* uint_to_addr(u_int addr);  
  82.   
  83. u_int16_t in_cksum (u_int16_t * addr, int len)  
  84. {  
  85.     int     nleft = len;  
  86.     u_int32_t sum = 0;  
  87.     u_int16_t *w = addr;  
  88.     u_int16_t answer = 0;  
  89.   
  90.     /* 
  91.     * Our algorithm is simple, using a 32 bit accumulator (sum), we add 
  92.     * sequential 16 bit words to it, and at the end, fold back all the 
  93.     * carry bits from the top 16 bits into the lower 16 bits. 
  94.     */  
  95.     while (nleft > 1) {  
  96.         sum += *w++;  
  97.         nleft -= 2;  
  98.     }  
  99.     /* mop up an odd byte, if necessary */  
  100.     if (nleft == 1) {  
  101.         * (unsigned char *) (&answer) = * (unsigned char *) w;  
  102.         sum += answer;  
  103.     }  
  104.   
  105.     /* add back carry outs from top 16 bits to low 16 bits */  
  106.     sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */  
  107.     sum += (sum >> 16);     /* add carry */  
  108.     answer = ~sum;     /* truncate to 16 bits */  
  109.     return (answer);  
  110. }  
  111.   
  112. struct Psd_Header {  
  113.     ULONG sourceip; //源IP地址  
  114.     ULONG destip; //目的IP地址  
  115.     BYTE mbz; //置空(0)  
  116.     BYTE ptcl; //协议类型  
  117.     USHORT plen; //TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度 单位:字节)  
  118. };   
  119.   
  120. har* device = "\\Device\\NPF_{06864041-9387-44DC-AF44-37779B0F2E9E}";  
  121. pcap_t* adhandle = NULL;  
  122. char errbuf[PCAP_ERRBUF_SIZE] = { 0 };  
  123.   
  124. void main()  
  125. {  
  126.     if((adhandle = pcap_open(device, 0x10000, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf)) == NULL)  
  127.     {  
  128.         printf("[pcap_open error] : %s\n", errbuf);  
  129.         return;  
  130.     }  
  131.   
  132.     char buffer[64] = { 0 };  
  133.   
  134.     ether_header* pether_header =   (ether_header*)buffer;  
  135.     ip_header* pip_herder       =   (ip_header*)(buffer + sizeof(ether_header));  
  136.     udphdr* pudp_herder         =   (udphdr*)(buffer + sizeof(ether_header) + sizeof(ip_header));  
  137.   
  138.     pether_header->ether_dhost[0] = 1;       //0x0 * 16 + 0x0;;  
  139.     pether_header->ether_dhost[1] = 1;       //0x2 * 16 + 0x1;  
  140.     pether_header->ether_dhost[2] = 1;       //0x2 * 16 + 0x7;  
  141.     pether_header->ether_dhost[3] = 1;       //0x2 * 16 + 0x3;  
  142.     pether_header->ether_dhost[4] = 1;       //0x7 * 16 + 0x2;  
  143.     pether_header->ether_dhost[5] = 1;       //0xf * 16 + 0xe;  
  144.   
  145.     pether_header->ether_shost[0] = 1;       //0x0 * 16 + 0x0;;  
  146.     pether_header->ether_shost[1] = 1;       //0x1 * 16 + 0xF;  
  147.     pether_header->ether_shost[2] = 1;       //0xD * 16 + 0x0;  
  148.     pether_header->ether_shost[3] = 1;       //0x1 * 16 + 0x6;  
  149.     pether_header->ether_shost[4] = 1;       //0x6 * 16 + 0x3;  
  150.     pether_header->ether_shost[5] = 1;       //0x7 * 16 + 0x1;  
  151.       
  152.   
  153.     pether_header->ether_type = htons(ETHERTYPE_IP);  
  154.   
  155.     //构建IP数据头  
  156.     if((sizeof(ip_header) % 4) != 0)  
  157.     {  
  158.         printf("[IP Header error]\n");  
  159.         return;  
  160.     }  
  161.   
  162.     pip_herder->ihl = sizeof(ip_header) / 4;  
  163.     pip_herder->version = 4;  
  164.     pip_herder->tos = 0;  
  165.     pip_herder->tot_len = htons(sizeof(buffer) - sizeof(ether_header));  
  166.     pip_herder->id = htons(0x1000);  
  167.     pip_herder->frag_off = htons(0);  
  168.     pip_herder->ttl = 0x80;  
  169.     pip_herder->protocol = IPPROTO_UDP;  
  170.     pip_herder->check = 0;  
  171.     pip_herder->saddr = inet_addr("192.168.18.*");  
  172.     pip_herder->daddr = inet_addr("122.*.*.*");  
  173.     pip_herder->check  = in_cksum((u_int16_t*)pip_herder, sizeof(ip_header));  
  174.   
  175.     //构建UDP数据头;  
  176.     pudp_herder->dest = htons(7865);  
  177.     pudp_herder->source = htons(2834);  
  178.     pudp_herder->len = htons(sizeof(buffer) - sizeof(ether_header) - sizeof(ip_header));  
  179.     pudp_herder->checkl = 0;  
  180.   
  181.     //构造伪UDP首部  
  182.   
  183.     //pudp_herder->checkl  = in_cksum((u_int16_t*)pudp_herder, 24);  
  184.   
  185.     char buffer2[64] = { 0 };  
  186.     Psd_Header* psd = (Psd_Header*)buffer2;  
  187.     psd->sourceip = inet_addr("192.168.18.*");  
  188.     psd->destip = inet_addr("122.*.*.*");  
  189.     psd->ptcl = IPPROTO_UDP;  
  190.     psd->plen =  htons(sizeof(buffer) - sizeof(ether_header) - sizeof(ip_header));  
  191.     psd->mbz = 0;  
  192.   
  193.     memcpy(buffer2 + sizeof(Psd_Header), (void*)pudp_herder, sizeof(buffer) - sizeof(ether_header) - sizeof(ip_header));  
  194.     pudp_herder->checkl  = in_cksum((u_int16_t *)buffer2,   
  195.         sizeof(buffer) - sizeof(ether_header) - sizeof(ip_header) + sizeof(Psd_Header));  
  196.   
  197.   
  198.     if(pcap_sendpacket(adhandle, (const u_char*)buffer, 64) == -1)  
  199.     {  
  200.         printf("[pcap_sendpacket error]\n");  
  201.         return;  
  202.     }  
  203. }  

转自:http://blog.csdn.net/liqinghua1653/archive/2009/04/08/4058041.aspx

posted on 2011-03-01 16:26  意扬  阅读(2974)  评论(0)    收藏  举报

导航