那有什么办法可以获取网卡的真实的物理地址呢?

时间:2021-04-09 17:31:26

网卡MAC ID 可以通过.net提供的WMI类库来实现,如果用户通过第三方软件修改了mac地址,WMI就是无法获取真实的网卡地址了。

那有什么办法可以获取网卡的真实的物理地址呢?有,那就要用到Windows API函数DeviceIoControl了,代码如下:

public static string GetLocalMac()
        {
            List<string> netCardList = GetNetCardList();
            List<string>.Enumerator enumNetCard = netCardList.GetEnumerator();

            string macAddr = string.Empty;
            while (enumNetCard.MoveNext())
            {
                macAddr = GetPhysicalAddr(enumNetCard.Current);
                if (macAddr != string.Empty)
                {
                    break;
                }
            }
            return macAddr;
        }
        public static List<string> GetNetCardList()
        {
            List<string> cardList = new List<string>();
            try
            {
                //请求“System.Security.Permissions.RegistryPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”类型的权限已失败。
                RegistryKey regNetCards = Registry.LocalMachine.OpenSubKey(Win32Utils.REG_NET_CARDS_KEY);
                if (regNetCards != null)
                {
                    string[] names = regNetCards.GetSubKeyNames();
                    RegistryKey subKey = null;
                    foreach (string name in names)
                    {
                        subKey = regNetCards.OpenSubKey(name);
                        if (subKey != null)
                        {
                            object o = subKey.GetValue("ServiceName");
                            if (o != null)
                            {
                                cardList.Add(o.ToString());
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }

            return cardList;
        }
        private static string GetPhysicalAddr(string cardId)
        {
            string macAddress = string.Empty;
            uint device = 0;
            try
            {
                string driveName = "\\\\.\\" + cardId;
                device = Win32Utils.CreateFile(driveName,
                Win32Utils.GENERIC_READ | Win32Utils.GENERIC_WRITE,
                Win32Utils.FILE_SHARE_READ | Win32Utils.FILE_SHARE_WRITE,
                0, Win32Utils.OPEN_EXISTING, 0, 0);
                if (device != Win32Utils.INVALID_HANDLE_VALUE)
                {
                    byte[] outBuff = new byte[6];
                    uint bytRv = 0;
                    int intBuff = Win32Utils.PERMANENT_ADDRESS;

                    if (0 != Win32Utils.DeviceIoControl(device, Win32Utils.IOCTL_NDIS_QUERY_GLOBAL_STATS,
                    ref intBuff, 4, outBuff, 6, ref bytRv, 0))
                    {
                        string temp = string.Empty;
                        foreach (byte b in outBuff)
                        {
                            temp = Convert.ToString(b, 16).PadLeft(2, '0');
                            macAddress += temp;
                            temp = string.Empty;
                        }
                    }
                }
            }
            finally
            {
                if (device != 0)
                {
                    Win32Utils.CloseHandle(device);
                }
            }

            return macAddress;
        }
    }
    

 

  #region Win32Utils
    public class Win32Utils
    {
        public const string REG_NET_CARDS_KEY = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards";
        public const uint GENERIC_READ = 0x80000000;
        public const uint GENERIC_WRITE = 0x40000000;
        public const uint FILE_SHARE_READ = 0x00000001;
        public const uint FILE_SHARE_WRITE = 0x00000002;
        public const uint OPEN_EXISTING = 3;
        public const uint INVALID_HANDLE_VALUE = 0xffffffff;
        public const uint IOCTL_NDIS_QUERY_GLOBAL_STATS = 0x00170002;
        public const int PERMANENT_ADDRESS = 0x01010101;

        [DllImport("kernel32.dll")]
        public static extern int CloseHandle(uint hObject);

        [DllImport("kernel32.dll")]
        public static extern int DeviceIoControl(uint hDevice,
                                                  uint dwIoControlCode,
                                                  ref int lpInBuffer,
                                                  int nInBufferSize,
                                                  byte[] lpOutBuffer,
                                                  int nOutBufferSize,
                                                  ref uint lpbytesReturned,
                                                  int lpOverlapped);

        [DllImport("kernel32.dll")]
        public static extern uint CreateFile(string lpFileName,
                                              uint dwDesiredAccess,
                                              uint dwShareMode,
                                              int lpSecurityAttributes,
                                              uint dwCreationDisposition,
                                              uint dwFlagsAndAttributes,
                                              int hTemplateFile);

    }
    #endregion
}