2012-03-03 100 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; 
    }