真的有办法唯一地识别任何一台计算机吗?

28

有很多类似的问题在stackoverflow上,比如:

一些被接受的答案建议使用MAC地址作为唯一标识符,这是完全不正确的。其他答案建议使用各种组件的组合,这似乎更合理。然而,在使用组合的情况下,应该考虑哪个组件自然不太可能经常更改。几天前,我们为软件许可问题开发了一个密钥生成器,我们使用CPUID和MAC的组合来唯一地识别Windows PC,直到进行实际测试之前,我们认为我们的方法已足够好。具有讽刺意味的是,当我们进行测试时,我们发现三台计算机返回相同的ID与我们的密钥生成器!

那么,真的有办法唯一地识别任何计算机吗?现在我们只需要让我们的密钥生成器在Windows PC上工作。如果可能的话,使用c#的某种方式将是很好的,因为我们的系统是基于.NET开发的。

更新:

抱歉造成一些混乱和明显的虚假警报。我们发现我们检索硬件信息的方法有误。首先,我想删除这个问题,因为我的困惑已经消失,我确信两个或更多组件的组合足以识别计算机。然而,然后我决定保留它,因为我认为我应该澄清造成问题的原因,因为同样的事情可能会伤害未来的其他人。

这就是我们在做什么(不包括其他代码):

我们使用一个getManagementInfo函数来检索MAC和处理器ID

private String getManagementInfo(String StrKey_String, String strIndex)
    {
        String strHwInfo = null;
        try
        {
            ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from " + StrKey_String);
            foreach (ManagementObject share in searcher.Get())
            {
                strHwInfo += share[strIndex];
            }
        }
        catch (Exception ex)
        {
            // show some error message
        }
        return strHwInfo;
    } 

然后在需要的地方,我们使用了该函数来检索MAC地址。

string strMAC = getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress");

获取处理器ID

string strProcessorId = getManagementInfo("Win32_Processor", "ProcessorId");

在这一点上,如果有多个MAC地址,strMAC将包含多个MAC地址。要仅获取一个,我们只需取前17个字符(12个MAC数字和5个冒号之间的字符)。

strMAC = strMAC.Length > 17 ? strMAC.Remove(17) : strMAC;

我们犯了错误,是因为getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress")返回了许多额外的MAC地址,而这些地址实际上并没有使用。例如,在命令提示符中通过getmac命令搜索MAC地址时,每台计算机显示了一个或两个不同的MAC地址。但是getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress")则返回了4到5个MAC地址,其中一些对于所有计算机都相同。由于我们只取了我们函数返回的第一个MAC地址而没有检查其他任何内容,因此相同的MAC地址被意外地放在了strMAC中。

以下代码由Sowkot Osman编写,可通过返回仅第一个活动/启用的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;
    }

然而,我关于相同处理器 ID 问题的判断是正确的。当我们在三台机器的命令提示符中执行 wmic cpu get ProcessorId 命令时,它们都返回了相同的处理器 ID。

现在,我们决定使用主板序列号代替处理器 ID,并与 MAC 地址一起组成一个组合。我认为这样可以达到我们的目的,如果有些情况下不行,那我们就放手让它发展。


6
简单的答案必须是否定的。因为电脑由许多可互换的部件组成,随着时间的推移,唯一可能保持不变的是机箱。因此,你需要明确指定你认为“电脑”中的哪些部分(硬件方面)是指“电脑”。无论你选择什么,都会有某种妥协,因此对先前答案的观点存在歧义或不正确。 - James Gaunt
3
如果你使用CPUID和MAC地址来识别机器,而三台机器返回相同的ID,则你的代码存在错误。MAC地址是全球唯一的,并在出厂时被分配。 - Paul Alexander
2
MAC地址可以被更改/欺骗,因此仅依赖它作为单一身份验证方法可能不明智。这就是为什么我们决定采用MAC和CPUID的组合,受到@Paul Alexander和其他之前发布的类似问题的建议的影响。即使在这种情况下获得相同的ID也非常奇怪和离奇。我们使用另一个软件重新检查了这个问题,其中两台计算机返回了相同的MAC和处理器ID,而第三台计算机尚未测试。 - Sajib Mahmood
2
如果您坚持使用主板序列号,请确保您的代码能够处理如果无法检索序列号的情况。例如,在虚拟机上可能不可能,甚至在某些情况下在真实硬件上也可能不可能。(我仍然认为这是一个糟糕的决定,因为如果涉及的主板损坏,它会让用户完全陷入困境,这对客户关系来说是很糟糕的。) - Harry Johnston
1
伪造的MAC地址仅在局域网中有效。如果系统内部使用了像getManagementInfo("Win32_NetworkAdapterConfiguration", "MacAddress")这样的函数,它实际上会从硬件中检索原始的MAC ID,而不是伪造的MAC ID。因此,不必担心MAC地址欺骗。 - HUNKY_Monkey
显示剩余9条评论
5个回答

11

可以考虑添加主板序列号例如:

using System.management;


//Code for retrieving motherboard's serial number
ManagementObjectSearcher MOS = new ManagementObjectSearcher("Select * From Win32_BaseBoard");
foreach (ManagementObject getserial in MOS.Get())
{
textBox1.Text = getserial["SerialNumber"].ToString();
}

//Code for retrieving Processor's Identity
MOS = new ManagementObjectSearcher("Select * From Win32_processor");
foreach (ManagementObject getPID in MOS.Get())
{
textBox2.Text = getPID["ProcessorID"].ToString();
}

//Code for retrieving Network Adapter Configuration
MOS = new ManagementObjectSearcher("Select * From Win32_NetworkAdapterConfiguration");
foreach (ManagementObject mac in MOS.Get())
{
textBox3.Text = mac["MACAddress"].ToString();
}

有用的提示,谢谢。我会等待更多答案再接受。无论如何+1 :) - Sajib Mahmood
2
这需要管理员权限吗? - Harry Johnston
1
任何需要获取“基板序列号”的人,请参见https://dev59.com/mUjSa4cB1Zd3GeqPJu5-。 - Iman
用户需要 WMI 访问权限,这可以通过使用管理员特权执行命令来添加(请参阅 https://www.codeproject.com/Articles/15848/WMI-Namespace-Security)。 但是在某些计算机上,SMBIOS UUID 在重新启动后会更改,并且在其他计算机上,它只包含零或只有 FF …… 因此,从不同来源组合多个 ID 仍然是获取可靠系统的唯一方法…… - matthieu

5

获取全局唯一标识的事实是,只有MAC地址是在重新设置系统后不会改变的ID。如果您为特定产品生成密钥,则最好的方法是为产品分配唯一的ID,并将产品ID与MAC地址结合使用。希望这能帮到您。


将产品ID与MAC地址结合似乎是一个非常好的主意。+1 - Sajib Mahmood
1
请不要对名称更改感到惊慌。我只是合并了两个账户,依然是之前的同一个人。:) 对于这条评论给您带来的不便,我表示抱歉。 - HUNKY_Monkey
完全没有问题。顺便问一下,你能回答这个问题吗:https://dev59.com/Tmkw5IYBdhLWcg3w8fBJ - Sajib Mahmood
5
MAC地址可以由用户更改。 - ANeves
3
更换网络接口卡肯定会改变MAC地址:这是唯一识别网络接口卡而不是计算机的绝佳方式。 - jpaugh

2

我完全同意上面的评论。

对于软件许可证,您可以使用:

计算机 MAC 地址(如果有多个 NIC 卡,请全部获取)+ 您的软件产品代码

大多数著名的电信供应商都在使用这种技术。


1
看起来定制厨房是实现这一目标的方法。
SMBIOS UUID(主板序列号)不够强大,但在99%的情况下工作正常。然而,某些品牌会为多台计算机设置相同的UUID(可能是同一批次生产)。获取它需要用户拥有WMI访问权限(如果他不是管理员),您可以通过启动要求管理员特权的外部进程来解决此问题(请参阅codeproject.com/Articles/15848/WMI-Namespace-Security)。
Windows产品ID可能很好,但我读到在某些情况下它可能是相同的(https://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine) 有人能澄清一下是否可能在多台计算机上存在相同的产品ID(而不是产品密钥)吗?
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid似乎很有趣。它在安装Windows时生成,如果更改,则需要重新激活Windows。
Mac地址很有趣,但您只能使用第一个地址,否则当接口被禁用或添加另一个网络接口并首先出现时,您的唯一ID将发生更改等。
硬盘序列号虽好,但在安装ghost时,它可能会覆盖原始驱动器的序列号...而且硬盘序列号很容易更改。
最好的方法是使用这些机器标识符的组合生成一个ID,并通过比较这些标识符(例如,如果至少有一个Mac地址+ SMBIOS UUID或Product ID是正确的,则接受)来确定机器是否相同。

1

然而,我对于相同的处理器ID问题是完全正确的。当我们在它们的命令提示符中输入"wmic cpu get ProcessorId"命令时,所有三个系统返回了相同的处理器ID。

如果所有系统都运行在同一个虚拟化管理程序上,则处理器ID将相同。

MAC地址看起来没问题。唯一的问题是用户必须提供重置应用程序的选项,以防MAC地址发生更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接