Как определить оригинальный MAC-адрес после того, как он был подделан?
Мы используем следующий код для получения активного MAC-адреса компьютера с 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;
}
Он отлично работает, чтобы получить MAC-адрес. Проблема в том, что когда MAC-адрес подделан, он возвращает поддельный MAC-адрес. Мы хотим каким-то образом получить исходный MAC-адрес, который является уникальным и назначается на заводе. Есть ли способ сделать это?
4 ответа
Я хочу дать альтернативу. Я не знаю, действительно ли он отвечает "способу уникальной идентификации любого компьютера".
Однако этот метод запрашивает класс Win32_BIOS в System.Management и возвращает строку с высокой вероятностью быть уникальной. (В ожидании дезавуации!!)
/// <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();
}
Некоторое время назад мне пришлось написать нечто подобное, потому что я использовал несколько аппаратных параметров для "активации" своего программного обеспечения.
Посмотрите на 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);
}
}
Там может быть две альтернативы.
Вы можете получить MAC-адрес, используя фрагмент кода, который вы дали ранее, и проверить, принадлежит ли этот MAC-адрес какой-либо сетевой карте. Если он не принадлежит никому, то MAC-адрес явно подделан. Вот код, который находит сетевой адаптер с помощью 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);
Получите адрес сетевой карты напрямую.
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/))
Ну, я бы не поставил все свои деньги на порядок, в котором класс NetworkInterface перечисляет NetworkInterfaces. На моей материнской плате есть 2 адаптера, и при каждой перезагрузке порядок меняется.
Итак, вот предложение, которое сработало для меня (кстати: кредиты, вероятно, идут к другому удивительному вкладчику stackru, 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;
}