luckone的文章

  • 编程获取计算机MAC地址等网卡信息并对网卡类型进行区分

    背景写了个小程序,用来获取计算机网卡的信息。例如枚举网卡名称、网卡描述、网卡MAC地址等等。同时,还对网卡的类别进行简单的判断,判断是否是物理网卡、无线网卡还是VMware的网卡。
    网卡信息获取主要使用API函数 GetAdaptersInfo,现对实现的过程进行介绍。
    函数介绍下面是 MSDN 的文档信息:

    The GetAdaptersInfo function retrieves adapter information for the local computer.On Windows XP and later: Use the GetAdaptersAddresses function instead of GetAdaptersInfo.
    SyntaxDWORD GetAdaptersInfo( _Out_ PIP_ADAPTER_INFO pAdapterInfo, _Inout_ PULONG pOutBufLen);
    Parameters
    pAdapterInfo [out]
    A pointer to a buffer that receives a linked list of IP_ADAPTER_INFO structures.
    pOutBufLen [in, out]
    A pointer to a ULONG variable that specifies the size of the buffer pointed to by the pAdapterInfo parameter. If this size is insufficient to hold the adapter information, GetAdaptersInfo fills in this variable with the required size, and returns an error code of ERROR_BUFFER_OVERFLOW.

    Return valueIf the function succeeds, the return value is ERROR_SUCCESS (defined to the same value as NO_ERROR).
    If the function fails, the return value is one of the following error codes.



    Return code
    Description




    ERROR_BUFFER_OVERFLOW
    The buffer to receive the adapter information is too small. This value is returned if the buffer size indicated by the pOutBufLen parameter is too small to hold the adapter information or the pAdapterInfo parameter was a NULL pointer. When this error code is returned, the pOutBufLen parameter points to the required buffer size.


    ERROR_INVALID_DATA
    Invalid adapter information was retrieved.


    ERROR_INVALID_PARAMETER
    One of the parameters is invalid. This error is returned if the pOutBufLen parameter is a NULL pointer, or the calling process does not have read/write access to the memory pointed to by pOutBufLen or the calling process does not have write access to the memory pointed to by the pAdapterInfo parameter.


    ERROR_NO_DATA
    No adapter information exists for the local computer.


    ERROR_NOT_SUPPORTED
    The GetAdaptersInfo function is not supported by the operating system running on the local computer.


    Other
    If the function fails, use FormatMessage to obtain the message string for the returned error.




    要注意的是,在 GetAdaptersInfo 的第二个参数,既是输入参数,也是输出参数,所以传入参数的时候,一定要对该参数赋值。
    原理分析我们可以单单通过 GetAdaptersInfo 函数,就可以获取计算机上所有网卡的名称、MAC地址、描述等信息。但是,并不能直接获取网卡所属的类型,也就是不能直接区分物理网卡、无线网卡、VMware网卡等信息。其实,下面介绍的区分方式,并不是正规方法,而是通过多次实践,总结而来的。

    区分物理网卡和虚拟网卡:pAdapter->Description中包含“PCI”的是物理网卡。区分无线网卡和有线网卡:pAdapter->Type为71的是无线网卡。
    VMware默认的网卡MAC地址前缀为“00-05-69”、“00-0C-29”或者“00-50-56”。 这前3节是由VMware分配的唯一标识符OUI,以供它的虚拟化适配器使用。

    编程实现1. 导入库文件#include <Iphlpapi.h>#pragma comment(lib, "iphlpapi.lib")
    2. 调用 GetAdaptersInfo 函数首先调用 GetAdaptersInfo 函数获取计算机网卡的信息,然后再根据网卡的描述、类型以及网卡地址来判断是物理网卡还是无线网卡还是VMware网卡,并显示网卡信息。
    BOOL GetComputerMacAddr(){ IP_ADAPTER_INFO AdapterInfo[16]; DWORD dwBufLen = sizeof(AdapterInfo); DWORD dwStatus = ::GetAdaptersInfo( AdapterInfo, &dwBufLen); if (ERROR_SUCCESS != dwStatus) { return FALSE; } PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo; do { printf("Description:%s\n", pAdapterInfo->Description); printf("AdapterName:%s\n", pAdapterInfo->AdapterName); printf("Address:%02X-%02X-%02X-%02X-%02X-%02X\n", pAdapterInfo->Address[0], pAdapterInfo->Address[1], pAdapterInfo->Address[2], pAdapterInfo->Address[3], pAdapterInfo->Address[4], pAdapterInfo->Address[5]); printf("Type:%d\n", pAdapterInfo->Type); // 判断网卡类型 if (NULL != strstr(pAdapterInfo->Description, "PCI")) { // 物理网卡 printf("[物理网卡]\n"); } else if (71 == pAdapterInfo->Type) { // 无线网卡 printf("[无线网卡]\n"); } else if ( // 00-05-69 (0x00 == pAdapterInfo->Address[0] && 0x05 == pAdapterInfo->Address[1] && 0x69 == pAdapterInfo->Address[2]) || // 00-0C-29 (0x00 == pAdapterInfo->Address[0] && 0x0c == pAdapterInfo->Address[1] && 0x29 == pAdapterInfo->Address[2]) || // 00-50-56 (0x00 == pAdapterInfo->Address[0] && 0x50 == pAdapterInfo->Address[1] && 0x56 == pAdapterInfo->Address[2]) ) { // VMware 网卡 printf("[VMware 网卡]\n"); } printf("\n"); // 获取下一个网卡信息 pAdapterInfo = pAdapterInfo->Next; } while (pAdapterInfo); return TRUE;}
    3. 结果显示在main函数中调用上述的 GetComputerMacAddr 函数,显示信息。main函数为:
    int _tmain(int argc, _TCHAR* argv[]){ GetComputerMacAddr(); system("pause"); return 0;}
    输出结果为:

    成功获取网卡信息,并能正确区分网卡的类别。
    总结主要是对 GetAdaptersInfo 函数的使用,其中,对网卡类别的区分并不是绝对正确的方法,因为该方法是从实践中总结得来,在大部分的应用场景是适用的。所以,请大家注意这一点。
    参考参考自《Windows黑客编程技术详解》一书
    2  留言 2018-12-20 12:38:00

发送私信

生活变得再糟糕,也不妨碍你变得更好

13
文章数
16
评论数
eject