WinPcap实战(一)——发送ARP包

来源:互联网 发布:手机淘宝改好评怎么改 编辑:程序博客网 时间:2024/05/15 11:12

ARP包的结构:

  1. ARP包格式:物理帧头(14B)——ARP帧结构(28B)——填充数据(18B)——CRC(4B)。这里给出一张图(图中没有18字节的填充数据和4字节的校验位):这里写图片描述

  2. 物理帧头(14B):目的MAC (6B) ——源MAC(6B) ——类型(2B, ARP帧:0x0806)

  3. ARP帧结构(28B):硬件类型(2B,Ethernet:0x1)——上层协议类型(2B,IP:0x0800)——硬件地址长度(1B,0x6)——IP地址长度(1B,0x4)——操作(2B,请求: 0x1; 应答: 0x2)——源MAC地址(6B)——源IP地址(6B)——目的MAC地址(6B)——目的IP地址(6B)

依据ARP包的结构定义结构体

//14字节以太网首部struct EthernetHeader{    u_char DestMAC[6];    //目的MAC地址 6字节    u_char SourMAC[6];   //源MAC地址 6字节    u_short EthType;         //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp  2字节};//28字节ARP帧结构struct ArpHeader{    unsigned short hdType;   //硬件类型    unsigned short proType;   //协议类型    unsigned char hdSize;   //硬件地址长度    unsigned char proSize;   //协议地址长度    unsigned short op;   //操作类型,ARP请求(1),ARP应答(2),RARP请求(3),RARP应答(4)。    u_char smac[6];   //源MAC地址    u_char sip[4];   //源IP地址    u_char dmac[6];   //目的MAC地址    u_char dip[4];   //目的IP地址};//定义整个arp报文包,总长度42字节struct ArpPacket {    EthernetHeader ed;    ArpHeader ah;};

源代码

#include "stdafx.h"#include <pcap.h>#define ETH_ARP         0x0806  //以太网帧类型表示后面数据的类型,对于ARP请求或应答来说,该字段的值为x0806#define ARP_HARDWARE    1  //硬件类型字段值为表示以太网地址#define ETH_IP          0x0800  //协议类型字段表示要映射的协议地址类型值为x0800表示IP地址#define ARP_REQUEST     1   //ARP请求#define ARP_RESPONSE       2      //ARP应答//14字节以太网首部struct EthernetHeader{    u_char DestMAC[6];    //目的MAC地址 6字节    u_char SourMAC[6];   //源MAC地址 6字节    u_short EthType;         //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp  2字节};//28字节ARP帧结构struct ArpHeader{    unsigned short hdType;   //硬件类型    unsigned short proType;   //协议类型    unsigned char hdSize;   //硬件地址长度    unsigned char proSize;   //协议地址长度    unsigned short op;   //操作类型,ARP请求(1),ARP应答(2),RARP请求(3),RARP应答(4)。    u_char smac[6];   //源MAC地址    u_char sip[4];   //源IP地址    u_char dmac[6];   //目的MAC地址    u_char dip[4];   //目的IP地址};//定义整个arp报文包,总长度42字节struct ArpPacket {    EthernetHeader ed;    ArpHeader ah;};int main(){    pcap_if_t *alldevs;   //所有网络适配器    pcap_if_t *d;   //选中的网络适配器     int inum;   //选择网络适配器    int i = 0;   //for循环变量    pcap_t *adhandle;   //打开网络适配器,捕捉实例,是pcap_open返回的对象    char errbuf[PCAP_ERRBUF_SIZE];   //错误缓冲区,大小为256    /* 获取本机设备列表 */    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)    {        fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);        exit(1);    }    /* 打印列表 */    for (d = alldevs; d; d = d->next)    {        printf("%d. %s", ++i, d->name);        if (d->description)            printf(" (%s)\n", d->description);        else            printf(" (No description available)\n");    }    if (i == 0)    {        printf("\nNo interfaces found! Make sure WinPcap is installed.\n");        return -1;    }    printf("Enter the interface number (1-%d):", i);    scanf("%d", &inum);    if (inum < 1 || inum > i)    {        printf("\nInterface number out of range.\n");        /* 释放设备列表 */        pcap_freealldevs(alldevs);        return -1;    }    /* 跳转到选中的适配器 */    for (d = alldevs, i = 0; i< inum - 1; d = d->next, i++);    /* 打开设备 */    if ((adhandle = pcap_open(d->name,          // 设备名        65536,            // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容        PCAP_OPENFLAG_PROMISCUOUS,    // 混杂模式        1000,             // 读取超时时间        NULL,             // 远程机器验证        errbuf            // 错误缓冲池        )) == NULL)    {        fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);        /* 释放设备列表 */        pcap_freealldevs(alldevs);        return -1;    }    /*以上代码在WinPcap开发文档中都可以找到,填充ARP包的代码则要自己编写*/    //开始填充ARP包,填充数据写死在代码中,测试用时数据可随意填写    unsigned char sendbuf[42]; //arp包结构大小,42个字节    unsigned char mac[6] = { 0x00,0x11,0x22,0x33,0x44,0x55 };    unsigned char ip[4] = { 0x01,0x02,0x03,0x04 };    EthernetHeader eh;    ArpHeader ah;    //赋值MAC地址    memset(eh.DestMAC, 0xff, 6);   //以太网首部目的MAC地址,全为广播地址    memcpy(eh.SourMAC, mac, 6);   //以太网首部源MAC地址    memcpy(ah.smac, mac, 6);   //ARP字段源MAC地址    memset(ah.dmac, 0xff, 6);   //ARP字段目的MAC地址    memcpy(ah.sip, ip, 4);   //ARP字段源IP地址    memset(ah.dip, 0x05, 4);   //ARP字段目的IP地址    eh.EthType = htons(ETH_ARP);   //htons:将主机的无符号短整形数转换成网络字节顺序    ah.hdType = htons(ARP_HARDWARE);    ah.proType = htons(ETH_IP);    ah.hdSize = 6;    ah.proSize = 4;    ah.op = htons(ARP_REQUEST);    //构造一个ARP请求    memset(sendbuf, 0, sizeof(sendbuf));   //ARP清零    memcpy(sendbuf, &eh, sizeof(eh));    memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));    //如果发送成功    if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {        printf("\nPacketSend succeed\n");    }    else {        printf("PacketSendPacket in getmine Error: %d\n", GetLastError());    }    /* 释放设备列表 */    pcap_freealldevs(alldevs);    return 0;}

运行结果

程序在VS2015企业版里面运行无误,需要提前配置好WinPcap的编程环境

选择第三个网卡,成功发送ARP包
这里写图片描述

抓包软件抓到ARP包:
这里写图片描述

传送门

接收ARP包:
http://blog.csdn.net/u013539342/article/details/48525525
参考网址:http://blog.csdn.net/cqcre/article/details/40213911
WinPcap编程配置:http://www.findspace.name/easycoding/871
VS下This function or variable may be unsafe解决办法:
http://jingyan.baidu.com/article/49711c616b8a1ffa441b7cdc.html

1 0
原创粉丝点击