¿Cómo detectar la dirección MAC original después de que ha sido falsificada?

Estamos utilizando el siguiente código para recuperar la dirección MAC activa de una PC con Windows.

private static string macId() { return identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled"); } private static string identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue) { string result = ""; System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass); System.Management.ManagementObjectCollection moc = mc.GetInstances(); foreach (System.Management.ManagementObject mo in moc) { if (mo[wmiMustBeTrue].ToString() == "True") { //Only get the first one if (result == "") { try { result = mo[wmiProperty].ToString(); break; } catch { } } } } return result; } //Return a hardware identifier private static string identifier(string wmiClass, string wmiProperty) { string result = ""; System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass); System.Management.ManagementObjectCollection moc = mc.GetInstances(); foreach (System.Management.ManagementObject mo in moc) { //Only get the first one if (result == "") { try { result = mo[wmiProperty].ToString(); break; } catch { } } } return result; } 

Funciona bien para recuperar la dirección MAC. El problema es cuando la dirección MAC es falsificada y luego devuelve la dirección MAC falsificada. Queremos de alguna manera recuperar la dirección MAC original que es única y asignada de fábrica. ¿Hay alguna manera de hacerlo?

Deseo dar una alternativa. No sé si realmente responde a “una forma única de identificar cualquier computadora”.
Sin embargo, este método consulta la clase Win32_BIOS en System.Management y devuelve una cadena con grandes posibilidades de ser único. (¡Esperando ser desautorizado!)

 ///  /// BIOS IDentifier ///  ///  public static string BIOS_ID() { return GetFirstIdentifier("Win32_BIOS", "Manufacturer") + GetFirstIdentifier("Win32_BIOS", "SMBIOSBIOSVersion") + GetFirstIdentifier("Win32_BIOS", "IdentificationCode") + GetFirstIdentifier("Win32_BIOS", "SerialNumber") + GetFirstIdentifier("Win32_BIOS", "ReleaseDate") + GetFirstIdentifier("Win32_BIOS", "Version"); } ///  /// ManagementClass used to read the first specific properties ///  /// Object Class to query /// Property to get info ///  private static string GetFirstIdentifier(string wmiClass, string wmiProperty) { string result = string.Empty; ManagementClass mc = new System.Management.ManagementClass(wmiClass); ManagementObjectCollection moc = mc.GetInstances(); foreach (ManagementObject mo in moc) { //Only get the first one if (string.IsNullOrEmpty(result)) { try { if (mo[wmiProperty] != null) result = mo[wmiProperty].ToString(); break; } catch { } } } return result.Trim(); } 

Puede haber dos alternativas.

  1. Puedes obtener la dirección MAC usando el fragmento de código que diste antes y verificar si esa dirección MAC pertenece a cualquier NIC (tarjeta de interfaz de red). Si no pertenece a uno, entonces la dirección MAC es obviamente falsa. Aquí está el código que ubica la NIC usando una dirección MAC

     using System.Net.Sockets; using System.Net; using System.Net.NetworkInformation; string localNicMac = "00:00:00:11:22:33".Replace(":", "-"); // Parse doesn't like colons var mac = PhysicalAddress.Parse(localNicMac); var localNic = NetworkInterface.GetAllNetworkInterfaces() .Where(nic => nic.GetPhysicalAddress().Equals(mac)) // Must use .Equals, not == .SingleOrDefault(); if (localNic == null) { throw new ArgumentException("Local NIC with the specified MAC could not be found."); } var ips = localNic.GetIPProperties().UnicastAddresses .Select(x => x.Address); 
  2. Obtenga la dirección de la tarjeta de red directamente.

     a. NWIF = dotnetClass "System.Net.NetworkInformation.NetworkInterface" b. the_Mac_array = NWIF.GetAllNetworkInterfaces() -- this is an array of all the Networks c. the_PhysicalAddress_Array = #() d. for net in the_Mac_array where (net.NetworkInterfaceType.toString()) == "Ethernet" do append the_PhysicalAddress_Array ((net.GetPhysicalAddress()).toString()) e. print the_PhysicalAddress_Array 

((Lo encontré aquí http://snipplr.com/view/23006/ ))

Tuve que escribir algo similar hace poco porque estaba usando una serie de parámetros de hardware para “activar” mi software.

Eche un vistazo a DeviceIoControl y OID_802_3_PERMANENT_ADDRESS . Es una gran cantidad de código de interoperabilidad (mi clase para manejarlo es aproximadamente 200 líneas), pero me da el código de hardware garantizado.

Algunos fragmentos de código para que vayas,

 private const uint IOCTL_NDIS_QUERY_GLOBAL_STATS = 0x170002; [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool DeviceIoControl( SafeFileHandle hDevice, uint dwIoControlCode, ref int InBuffer, int nInBufferSize, byte[] OutBuffer, int nOutBufferSize, out int pBytesReturned, IntPtr lpOverlapped); [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] internal static extern SafeFileHandle CreateFile( string lpFileName, EFileAccess dwDesiredAccess, EFileShare dwShareMode, IntPtr lpSecurityAttributes, ECreationDisposition dwCreationDisposition, EFileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile); [Flags] internal enum EFileAccess : uint { Delete = 0x10000, ReadControl = 0x20000, WriteDAC = 0x40000, WriteOwner = 0x80000, Synchronize = 0x100000, StandardRightsRequired = 0xF0000, StandardRightsRead = ReadControl, StandardRightsWrite = ReadControl, StandardRightsExecute = ReadControl, StandardRightsAll = 0x1F0000, SpecificRightsAll = 0xFFFF, AccessSystemSecurity = 0x1000000, // AccessSystemAcl access type MaximumAllowed = 0x2000000, // MaximumAllowed access type GenericRead = 0x80000000, GenericWrite = 0x40000000, GenericExecute = 0x20000000, GenericAll = 0x10000000 } // Open a file handle to the interface using (SafeFileHandle handle = FileInterop.CreateFile(deviceName, FileInterop.EFileAccess.GenericRead | FileInterop.EFileAccess.GenericWrite, 0, IntPtr.Zero, FileInterop.ECreationDisposition.OpenExisting, 0, IntPtr.Zero)) { int bytesReturned; // Set the OID to query the permanent address // http://msdn.microsoft.com/en-us/library/windows/hardware/ff569074(v=vs.85).aspx int OID_802_3_PERMANENT_ADDRESS = 0x01010101; // Array to capture the mac address var address = new byte[6]; if (DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, ref OID_802_3_PERMANENT_ADDRESS, sizeof(uint), address, 6, out bytesReturned, IntPtr.Zero)) { // Attempt to parse the MAC address into a string // any exceptions will be passed onto the caller return BitConverter.ToString(address, 0, 6); } } 

Bueno, no apostaría todo mi dinero en el orden en que la clase NetworkInterface incluye NetworkInterfaces. Mi placa madre tiene 2 adaptadores y el orden parece cambiar cada vez que reinicio.

Así que aquí hay una sugerencia, que funcionó para mí (BTW: los créditos son probablemente para otro impresionante contribuidor de stackoverflow, ty):

  public static string GetMACAddress() { NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); //for each j you can get the MAC PhysicalAddress address = nics[0].GetPhysicalAddress(); byte[] bytes = address.GetAddressBytes(); string macAddress = ""; for (int i = 0; i < bytes.Length; i++) { // Format the physical address in hexadecimal. macAddress += bytes[i].ToString("X2"); // Insert a hyphen after each byte, unless we are at the end of the address. if (i != bytes.Length - 1) { macAddress += "-"; } } return macAddress; }