網上存在很多關于的文章,大多都是關于ARP欺騙,這里介紹ARP的另類用法:探測目標主機是否處于活動狀態(tài)。
傳統(tǒng)探測遠程主機是否存活的方法是通過ICMP協(xié)議中的回顯應答報文來探測(ping)。隨著對安全的越來越多的了解和重視,很多主機為了避免被掃描器探測,通過將ICMP包屏蔽,從而達到在網絡中隱藏的目的。
這里我們介紹一下利用探測網絡中的活動主機的思路,這種方法的缺點只能探測以太網內的活動主機。
先大概了解一下ARP協(xié)議。ARP協(xié)議是“Address Resolution Protocol”(地址解析協(xié)議)的縮寫,它的作用是將IP地址轉換成物理地址(就是常說的地址),其詳細過程參考《詳解 卷一》。協(xié)議ARP的分組格式如下:
------------------------------------------
以太網目的地址(6個字節(jié))
以太網源地址(6個字節(jié))
幀類型(ARP = 0806)(2個字節(jié))
------------------------------------------
硬件類型(Ethernet=01)(2個字節(jié))
協(xié)議類型(IPv4=0800)(2個字節(jié))
硬件地址長度(1個字節(jié))
協(xié)議地址長度(1個字節(jié))
OP操作選項(ARP request=01,ARP reply=02)(2個字節(jié))
發(fā)送端以太網地址(6個字節(jié))
發(fā)送端IP地址(4個字節(jié))
目的以太網地址(6個字節(jié))
目的IP地址(4個字節(jié))
--------------------------------------------
我們向目標主機發(fā)送一個ARP請求,如果目標主機處于活動狀態(tài)則會返回其MAC地址,如果對方返回MAC地址,則表明對方處于活動狀態(tài),這樣達到探測目的。ARP請求包內容如下:
------------------------------------------
以太網目的地址 |FFFFFFFFFFFF(廣播地址)
以太網源地址 |本地MAC地址
幀類型 |0806
------------------------------------------
硬件類型 |01
協(xié)議類型 |0800
硬件地址長度 |06
協(xié)議地址長度 |04
OP操作選項 |01
發(fā)送端以太網地址|本地MAC地址
發(fā)送端IP地址 |目標主機IP地址
目的以太網地址 |000000000000
目的IP地址 |目標主機IP地址
--------------------------------------------
注意:這里以太網目的地址為FFFFFFFFFFFF,這是廣播地址,以太網上所有主機都能收到這個包,在收到這個數(shù)據(jù)包后,判斷目的IP地址是不是這臺主機,如果不是則丟棄(不作處理),否則發(fā)送回一個ARP應答包,包的內容如下:
------------------------------------------
以太網目的地址 |探測主機的MAC地址
以太網源地址 |本地MAC地址 (這里本地指被探測主機)
幀類型 |0806
------------------------------------------
硬件類型 |01
協(xié)議類型 |0800
硬件地址長度 |06
協(xié)議地址長度 |04
OP操作選項 |02
發(fā)送端以太網地址|本地MAC地址 (這里本地指被探測主機)
發(fā)送端IP地址 |本機IP地址 (這里本地指被探測主機)
目的以太網地址 |探測主機的MAC地址
目的IP地址 |探測主機的IP地址
--------------------------------------------
我們可以使用Pcap自己來構造這個數(shù)據(jù)包(具體過程參考Pcap的相關文檔,這里我們使用SendARP()來實現(xiàn)),SendARP()是 Platform SDK中提供用來獲得目標主機的MAC地址的函數(shù),SendARPSendARP的函數(shù)原型如下:
DWORD SendARP(
IPAddr DestIP, // 目標IP地址
IPAddr SrcIP, // 源IP地址
PULONG pMacAddr, // 返回MAC地址指針
PULONG PhyAddrLen // 返回MAC地址長度
);
下面這個例子摘至MSND,稍做改動可以成為一個以太網內活動主機探測工具
//
// Link with ws2_32.lib and iphlpapi.lib
//
#include
#include
#include
#include
int __cdecl main()
{
HRESULT hr;
IPAddr ipAddr;
ULONG pulMac[2];
ULONG ulLen;
ipAddr = inet_addr ("192.168.0.1");
memset (pulMac, 0xff, sizeof (pulMac));
ulLen = 6;
hr = SendARP (ipAddr, 0, pulMac, &ulLen);
printf ("Return %08x, length %8d\n", hr, ulLen);
size_t i, j;
char * szMac = new char[ulLen*3];
PBYTE pbHexMac = (PBYTE) pulMac;
//
// Convert the binary MAC address into human-readable
//
for (i = 0, j = 0; i < ulLen - 1; ++i) {
j += sprintf (szMac + j, "%02X:", pbHexMac[i]);
}
sprintf (szMac + j, "%02X", pbHexMac[i]);
printf ("MAC address %s\n", szMac);
delete [] szMac;
return 0;
}