2012-03-03 101 views
21

我们使用下面的代码来检索Windows PC的活动MAC地址。如何检测原始MAC地址被欺骗后?

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; 
} 

它工作正常,检索MAC地址。问题是当MAC地址被欺骗时,它返回伪造的MAC地址。我们想以某种方式检索出厂时唯一和分配的原始MAC地址。有没有办法做到这一点?

+11

欺骗MAC的全部意义在于,使计算机(和软件就此)相信这是正确的MAC。 – Joe 2012-03-03 12:53:45

+0

@Joe,是的。我原来的问题是“是否真的有办法唯一识别任何计算机”?我得到了一些建议,可以将MAC地址用作唯一标识符。这导致了这个问题。 – 2012-03-03 13:17:56

+1

这里有一些其他的想法:http://stackoverflow.com/questions/671876/whats-a-good-way-to-uniquely-identify-a-computer – Joe 2012-03-03 14:05:40

回答

21

我想给出一个替代方案。我不知道它是否真的回答'唯一识别任何计算机的方式'。
但是,此方法查询System.Management中的Win32_BIOS类并返回一个很有可能是唯一的字符串。 (等待被否决!!)

/// <summary> 
/// BIOS IDentifier 
/// </summary> 
/// <returns></returns> 
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"); 
} 

/// <summary> 
/// ManagementClass used to read the first specific properties 
/// </summary> 
/// <param name="wmiClass">Object Class to query</param> 
/// <param name="wmiProperty">Property to get info</param> 
/// <returns></returns> 
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(); 
} 
+0

感谢您的选择,虽然我已经在我的脑海里。无论如何,我感谢任何合理的建议。没有什么可以拒绝的。 :) – 2012-03-03 13:55:01

+0

非常感谢! – 2013-10-15 08:21:10

8

可以有两种选择。

  1. 你可以使用代码的MAC地址段,您之前给了,并检查该MAC地址属于任何NIC(网络接口卡)。如果它不属于一个,那么MAC地址显然是欺骗性的。这里是使用MAC地址定位NIC的代码

    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. 直接获取网卡地址。

    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 
    

((我在这里找到http://snipplr.com/view/23006/))

+0

当MAC地址被欺骗时,此方法是否工作? – Guvante 2012-03-13 17:10:17

+1

@Guvante,不,它不。它会告诉你,伪造的MAC地址属于相应的NIC。实际上,到目前为止,我所使用的每个代码都检索当前的MAC地址,而不是在工厂分配的原始代码。 – 2012-03-14 06:48:24

+0

你的答案没有奏效但你是唯一一个试图给出这个问题的实际答案的人..所以我决定给你赏金.. :) – 2012-03-14 12:15:27

7

我不得不写类似的一点东西,而以前因为我用了一些硬件参数,我的软件的“激活”。

看一看,DeviceIoControl & OID_802_3_PERMANENT_ADDRESS。 它的很多互操作代码(我的类处理它大约是200行),但它让我保证硬件代码。

一些代码片段让你去,

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); 
    } 
} 
+0

这看起来很有希望。谢谢:) 我会测试并让你知道。 – 2012-06-26 13:01:27

+1

@SajibMahmood让我知道,如果你卡住了。在我的软件中,它已经在250多种不同的计算机硬件上运行了超过150,000台机器。它始终捕获该mac地址。不幸的是,WMI不会获得成功率。 – 2012-06-26 13:59:23

+0

@SajibMahmood有没有运气? – 2012-07-11 10:29:51

1

好了,我不会赌我所有的钱的顺序NetworkInterface类名单NetworkInterfaces上。 我的主板有2个适配器,每次重新启动时我都会切换顺序。

因此,这里是一个建议,这为我工作(BTW:学分转到大概到另一个真棒计算器贡献者,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; 
    }