VC++實現IP與ARP資訊獲取,可以同理實現APR攻擊
ARP(Address Resolution Protocol,地址解析協議)是獲取實體地址的一個TCP/IP協議。某節點的IP地址的ARP請求被廣播到網路上後,這個節點會收到確認 其實體地址的應答,這樣的資料包才能被傳送出去。RARP(逆向ARP)經常在無盤工作站上使用,以獲得它的邏輯IP地址。
地址解析協議(Address Resolution Protocol,ARP)是在僅知道主機的IP地址時確 地址解析協議定其實體地址的一種協議。
因IPv4和乙太網的廣泛應用,其主要用作將IP地址翻譯為乙太網的MAC地址,但其也能在ATM( 非同步傳輸模式)和FDDIIP(Fiber Distributed Data Interface 光纖分散式資料介面)網路中使用。
從IP地址到實體地址的對映有兩種方式:表格方式和非表格方式。
ARP具體說來就是將網路層(IP層,也就是相當於OSI的第三層)地址解析為資料連線層(MAC層,也就是相當於OSI的第二層)的MAC地址。
在TCP/IP協議中,A給B傳送IP包,在報頭中需要填寫B的IP為目標地址,但這個IP包在乙太網上傳輸的時候,還需要進行一次以太包的封裝,在這個以太包中,目標地址就是B的MAC地址.
計算機A是如何得知B的MAC地址的呢?解決問題的關鍵就在於ARP協議。
在A不知道B的MAC地址的情況下,A就廣播一個ARP請求包,請求包中填有B的IP(192.168.1.2),乙太網中的所有計算機都會接收這個請求,而正常的情況下只有B會給出ARP應答包,包中就填充上了B的MAC地址,並回復給A。
A得到ARP應答後,將B的MAC地址放入本機快取,便於下次使用。
本機MAC快取是有生存期的,生存期結束後,將再次重複上面的過程。
ARP協議並不只在傳送了ARP請求才接收ARP應答。當計算機接收到ARP應答資料包的時候,就會對本地的ARP快取進行更新,將應答中的IP和MAC地址儲存在ARP快取中。因此,當局域網中的某臺機器B向A傳送一個自己偽造的ARP應答,而如果這個應答是B冒充C偽造來的,即IP地址為C的IP,而MAC地址是偽造的,則當A接收到B偽造的ARP應答後,就會更新本地的ARP快取,這樣在A看來C的IP地址沒有變,而它的MAC地址已經不是原來那個了。由於區域網的網路流通不是根據IP地址進行,而是按照MAC地址進行傳輸。所以,那個偽造出來的MAC地址在A上被改變成一個不存在的MAC地址,這樣就會造成網路不通,導致A不能Ping通C!這就是一個簡單的ARP欺騙。
#include <stdio.h>
#include <windows.h>
#include <Iphlpapi.h>
#pragma comment(lib, "Iphlpapi.lib")
#pragma comment(lib, "WS2_32.lib")
PMIB_IPNETTABLE MyGetIpNetTable(BOOL bOrder);
void MyFreeIpNetTable(PMIB_IPNETTABLE pIpNetTable);
PMIB_IPADDRTABLE MyGetIpAddrTable(BOOL bOrder);
void MyFreeIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable);
BOOL InterfaceIdxToInterfaceIp(PMIB_IPADDRTABLE pIpAddrTable, DWORD dwIndex, char str[]);
// 根據IP地址表,將介面索引轉化為IP地址
// pIpAddrTable是IP地址表
// dwIndex是介面索引
// 函式執行成功之後,str將包含介面的IP地址
BOOL InterfaceIdxToInterfaceIp(PMIB_IPADDRTABLE pIpAddrTable, DWORD dwIndex, char str[])
{
char* szIpAddr;
if(pIpAddrTable == NULL || str == NULL)
return FALSE;
str[0] = '\0';
// 遍歷IP地址表,查詢索引dwIndex對應的IP地址
for(DWORD dwIdx = 0; dwIdx < pIpAddrTable->dwNumEntries; dwIdx++)
{
if(dwIndex == pIpAddrTable->table[dwIdx].dwIndex)
{
// 以字串的形式返回查詢結果
szIpAddr = inet_ntoa(*((in_addr*)&pIpAddrTable->table[dwIdx].dwAddr));
if(szIpAddr)
{
strcpy(str, szIpAddr);
return TRUE;
}
else
return FALSE;
}
}
return FALSE;
}
//----------------------------------------------------------------------------
// ARP表將以如下格式打印出來:
// Interface: 157.61.239.34 on Interface 2
// Internet Address Physical Address Type
// 159.61.230.39 00-aa-00-61-5d-a4 dynamic
//
// Interface: 157.54.178.219 on Interface 3
// Internet Address Physical Address Type
// 159.54.170.1 00-10-54-42-c0-88 dynamic
// 159.54.170.113 00-aa-00-c0-80-2e dynamic
//----------------------------------------------------------------------------
int main()
{
DWORD i, dwCurrIndex;
char szPrintablePhysAddr[256];
char szType[128];
char szIpAddr[128];
// 首先獲取ARP表
PMIB_IPNETTABLE pIpNetTable = MyGetIpNetTable(TRUE);
if (pIpNetTable == NULL)
{
printf( "pIpNetTable == NULL in line %d\n", __LINE__);
return -1;
}
// 獲取IP地址表,以便根據它將ARP表項中的介面索引轉化為IP地址
PMIB_IPADDRTABLE pIpAddrTable = MyGetIpAddrTable(TRUE);
// 當前的介面卡索引。注意,ARP表應該按照介面索引排序
dwCurrIndex = pIpNetTable->table[0].dwIndex;
if(InterfaceIdxToInterfaceIp(pIpAddrTable, dwCurrIndex, szIpAddr))
{
printf("\nInterface: %s on Interface 0x%X\n", szIpAddr, dwCurrIndex);
printf(" Internet Address Physical Address Type\n");
}
else
{
printf("Error: Could not convert Interface number 0x%X to IP address.\n",
pIpNetTable->table[0].dwIndex);
return -1;
}
// 打印出索引為dwCurrIndex的介面卡上的ARP表項
for(i = 0; i < pIpNetTable->dwNumEntries; ++i)
{
// 不相等則說明要列印下一個介面卡上的ARP表項了
if(pIpNetTable->table[i].dwIndex != dwCurrIndex)
{
dwCurrIndex = pIpNetTable->table[i].dwIndex;
if (InterfaceIdxToInterfaceIp(pIpAddrTable, dwCurrIndex, szIpAddr))
{
printf("Interface: %s on Interface 0x%X\n", szIpAddr, dwCurrIndex);
printf(" Internet Address Physical Address Type\n");
}
else
{
printf("Error: Could not convert Interface number 0x%X to IP address.\n",
pIpNetTable->table[0].dwIndex);
return -1;
}
}
// 打印出此ARP表項中的資料
// MAC地址
u_char *p = pIpNetTable->table[i].bPhysAddr;
wsprintf(szPrintablePhysAddr, "%02X-%02X-%02X-%02X-%02X-%02X", p[0], p[1], p[2], p[3], p[4], p[5]);
// IP地址
struct in_addr inadTmp;
inadTmp.s_addr = pIpNetTable->table[i].dwAddr;
// 型別
switch (pIpNetTable->table[i].dwType)
{
case 1:
strcpy(szType,"other");
break;
case 2:
strcpy(szType,"invalidated");
break;
case 3:
strcpy(szType,"dynamic");
break;
case 4:
strcpy(szType,"static");
break;
default:
strcpy(szType,"invalidType");
}
printf(" %-16s %-17s %-11s\n", inet_ntoa(inadTmp), szPrintablePhysAddr, szType);
}
return 0;
}
// 獲取IP地址到介面卡的對映關係,即ARP表
PMIB_IPNETTABLE MyGetIpNetTable(BOOL bOrder)
{
PMIB_IPNETTABLE pIpNetTable = NULL;
DWORD dwActualSize = 0;
// 查詢所需緩衝區的大小
if(::GetIpNetTable(pIpNetTable,
&dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER)
{
// 為MIB_IPNETTABLE結構申請記憶體
pIpNetTable = (PMIB_IPNETTABLE)::GlobalAlloc(GPTR, dwActualSize);
// 獲取ARP表
if(::GetIpNetTable(pIpNetTable,
&dwActualSize, bOrder) == NO_ERROR)
{
return pIpNetTable;
}
::GlobalFree(pIpNetTable);
}
return NULL;
}
void MyFreeIpNetTable(PMIB_IPNETTABLE pIpNetTable)
{
if(pIpNetTable != NULL)
::GlobalFree(pIpNetTable);
}
PMIB_IPADDRTABLE MyGetIpAddrTable(BOOL bOrder)
{
PMIB_IPADDRTABLE pIpAddrTable = NULL;
DWORD dwActualSize = 0;
// 查詢所需緩衝區的大小
if(::GetIpAddrTable(pIpAddrTable,
&dwActualSize, bOrder) == ERROR_INSUFFICIENT_BUFFER)
{
// 為MIB_IPADDRTABLE結構申請記憶體
pIpAddrTable = (PMIB_IPADDRTABLE)::GlobalAlloc(GPTR, dwActualSize);
// 獲取IP地址表
if(::GetIpAddrTable(pIpAddrTable,
&dwActualSize, bOrder) == NO_ERROR)
return pIpAddrTable;
::GlobalFree(pIpAddrTable);
}
return NULL;
}
void MyFreeIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable)
{
if(pIpAddrTable != NULL)
::GlobalFree(pIpAddrTable);
}
/*
void PrintIpAddrTable()
{
DWORD i;
struct in_addr inadTmp1;
struct in_addr inadTmp2;
char szAddr[128];
char szMask[128];
PMIB_IPADDRTABLE pIpAddrTable = MyGetIpAddrTable(TRUE);
if (pIpAddrTable == NULL)
{
printf( "pIpAddrTable == NULL in line %d\n", __LINE__);
return;
}
printf("ipAdEntAddr\t ifAdEntIfIndex\t ipAdEntNetMask\t ipAdEntBcastAddr\t ipAdEntReasmMaxSize\n");
for (i = 0; i < pIpAddrTable->dwNumEntries; ++i)
{
inadTmp1.s_addr = pIpAddrTable->table[i].dwAddr;
strcpy(szAddr, inet_ntoa(inadTmp1));
inadTmp2.s_addr = pIpAddrTable->table[i].dwMask;
strcpy(szMask, inet_ntoa(inadTmp2));
printf(" %s\t 0x%X\t %s\t %s\t %u\n",
szAddr,
pIpAddrTable->table[i].dwIndex,
szMask,
(pIpAddrTable->table[i].dwBCastAddr ? "255.255.255.255" : "0.0.0.0"),
pIpAddrTable->table[i].dwReasmSize);
}
MyFreeIpAddrTable(pIpAddrTable);
}
*/