在區域網路中,IP 位址屬於網路層 (Layer 3),MAC 位址屬於資料鏈路層 (Layer 2)。當我們只知道目標 IP,需取得其 MAC 位址時(如網路掃描、ARP 綁定、Wake-on-LAN),可利用 Windows IP Helper API 中的 SendARP 函式,發送 ARP 請求封包並解析回應。
#include
#pragma comment(lib, "Iphlpapi.lib")
ULONG SendARP(
IPAddr DestIP, // 目標 IP 位址 (網路位元組序)
IPAddr SrcIP, // 來源 IP (通常為 0,由系統自動選擇)
PULONG pMacAddr, // 接收 MAC 位址的緩衝區 (至少 6 bytes)
PULONG PhyAddrLen // 輸入/輸出:緩衝區大小 / 實際 MAC 長度
);
回傳 NO_ERROR (0) 表示成功,否則為 Windows 錯誤碼。
支援掃描單一 IP 或連續 IP 範圍 (指定數量),輸出 IP、主機名、MAC 位址。
#include
#include
#include
#include
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "Iphlpapi.lib")
void PrintUsage()
{
printf("RmtMac v1.0 - Get remote MAC address via ARP\n");
printf("Usage: RmtMac.exe [Count]\n");
printf("Example: RmtMac.exe 192.168.1.100\n");
printf(" RmtMac.exe 192.168.1.1 10 (scan 10 consecutive IPs)\n");
}
int main(int argc, char* argv[])
{
if (argc < 2 || argc > 3)
{
PrintUsage();
return 1;
}
// 初始化 Winsock
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
fprintf(stderr, "WSAStartup failed: %d\n", GetLastError());
return 1;
}
// 解析目標 IP
ULONG targetIP = inet_addr(argv[1]);
if (targetIP == INADDR_NONE)
{
fprintf(stderr, "Invalid IP address: %s\n", argv[1]);
WSACleanup();
return 1;
}
int count = (argc == 3) ? atoi(argv[2]) : 1;
if (count <= 0) count = 1;
// 逐一掃描
for (int i = 0; i < count; ++i)
{
ULONG currentIP = htonl(ntohl(targetIP) + i); // 處理位元組序與遞增
struct in_addr addr;
addr.s_addr = currentIP;
printf("IP: %-15s ", inet_ntoa(addr));
// 1. 嘗試反向解析主機名
struct hostent* host = gethostbyaddr((char*)¤tIP, 4, AF_INET);
if (host)
printf("Host: %-30s ", host->h_name);
else
printf("Host: (unknown) ");
// 2. 發送 ARP 取得 MAC
BYTE macAddr[6] = {0};
ULONG macLen = 6;
DWORD ret = SendARP(currentIP, 0, (PULONG)macAddr, &macLen);
if (ret == NO_ERROR && macLen == 6)
{
printf("MAC: %02X-%02X-%02X-%02X-%02X-%02X\n",
macAddr[0], macAddr[1], macAddr[2],
macAddr[3], macAddr[4], macAddr[5]);
}
else
{
printf("MAC: (failed, error=%lu)\n", ret);
}
}
WSACleanup();
return 0;
}
inet_addr 回傳「網路位元組序」(Big Endian) 的 ULONG。ntohl)、加 1 後再轉回 (htonl)。SendARP 實際上會先查詢本機 ARP 快取,若無則發送 ARP Request 廣播。| 錯誤碼 | 常數名稱 | 說明 |
|---|---|---|
| 0 | NO_ERROR | 成功 |
| 1168 | ERROR_NOT_FOUND | ARP 快取無此 IP,且廣播無回應 |
| 87 | ERROR_INVALID_PARAMETER | 參數錯誤 (如緩衝區太小) |
| 1753 | ERROR_NO_MORE_ITEMS | 無更多項目 |