How to reliably and quickly get the MAC address of a network card given its device instance ID

前端 未结 3 994
感动是毒
感动是毒 2021-02-08 04:19

Given a device instance ID for a network card, I would like to know its MAC address. Example device instance ID on my system for integrated Intel Gigabit card:

         


        
3条回答
  •  囚心锁ツ
    2021-02-08 04:57

    I guess you want to get the MAC address in order to implement some sort of DRM, inventory, or classification system, since you tried to get the permanent MAC address instead of the current one.

    You seem to forget that there's even an administratively super-imposed MAC address (in other words: a "forced" MAC address).
    Some drivers let you do this from the Device Property page, under the Advanced tab (for example: my Marvell network adapter let me do this), while some others don't let you do that (read: they don't support that property).

    However, it all ends in a Registry value: HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\xxxx\NetworkAddress, with a REG_SZ type. Here you can set a different MAC address than the original one, in the form "01020304abcd" (6 bytes, plain hexadecimal, without : separators or 0x prefix). After you set it, reboot the machine, and on power-up the new MAC address will have effect.

    I happen to have a motherboard with two Marvell integrated NICs, and a NETGEAR USB WiFi NIC. The Marvell one supports changing the MAC address: if you set the NetworkAddress value in the Registry, you see the new value in the driver properties page, too, and it has effect immediately, without the need to restart (if you change it from device Property Page). Here follows the results of reading the MAC address with different methods:

    • GetAdaptersInfo: new MAC address
    • IOCTL_NDIS_QUERY_GLOBAL_STATS: original MAC address
    • MSNdis_EthernetPermanentAddress: original MAC address

    I tried adding the NetworkAddress value in the Registry for the NETGEAR USB WiFi NIC, and the results are:

    • GetAdaptersInfo: new MAC address
    • IOCTL_NDIS_QUERY_GLOBAL_STATS: new MAC address
    • MSNdis_EthernetPermanentAddress: new MAC address

    The original MAC addres is gone.

    So, in order to not be fooled by a "malicious" user, you always need to check the HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\xxxx\NetworkAddress Registry value. If that is set, i guess it's better to not trust that Network Adapter at all, since it is up to the driver implementation to decide what will be presented to you using the different methods.

    Some background for getting to that Registry key:

    Microsoft documentation about the HKLM\SYSTEM\CurrentControlSet\Class key
    According to the Microsoft documentation on that page,

    There is a subkey for each class that is named using the GUID of the setup class

    So we choose the {4D36E972-E325-11CE-BFC1-08002BE10318} subkey (aka GUID_DEVCLASS_NET, defined in , and further documented here)

    Again, according to Microsoft documentation,

    Each class subkey contains other subkeys known as software keys (or, driver keys) for each device instance of that class installed in the system. Each of these software keys is named by using a device instance ID, which is a base-10, four-digit ordinal value The xxxx part is a 4-character textual representation of a positive integer, starting from 0

    So, you can traverse the subkeys up from 0000, 0001, 0002, up to the number of network adapters in your system.
    The documentation stops here: I didn't find any other documentation about the different registry values, or such.

    However, in each of these subkeys, you can find REG_SZ values that can help you link the GetAdaptersInfo(), MSNdis_EthernetPermanentAddress, Win32_NetworkAdapter, and Device Instance ID worlds (and this answers your question).

    The Registry values are:

    • DeviceInstanceID: its value is, no surprise, the Device Instance ID
    • NetCfgInstanceId: its value is the AdapterName member of the IP_ADAPTER_INFO struct, returned by GetAdaptersInfo(). It is also the GUID member of the Win32_NetworkAdapter WMI class.
    • Don't forget the NetworkAddress one: should a valid MAC address exist here, a driver may report it as the MAC address in use by GetAdaptersInfo(), MSNdis_EthernetPermanentAddress, and IOCTL_NDIS_QUERY_GLOBAL_STATS!

    Then, as you already said, the only connection between the MSNdis_EthernetPermanentAddress WMI Class and the rest of the "world" is by its InstanceName member. You can relate it to the Description member of the IP_ADAPTER_INFO struct, returned by GetAdaptersInfo(). Although it may be a localized name, it seems to be unique for the system (For my two integrated Marvell NICs, the second one has a " #2" appended to its name).

    Final note:

    Said all the above, the user could choose to disable WMI...

提交回复
热议问题