107

我需要编写一个函数来生成一个对于运行 Windows 操作系统的给定机器唯一的 id。

目前,我正在使用 WMI 查询各种硬件参数并将它们连接在一起并散列它们以派生唯一 id。我的问题是,我应该使用哪些建议参数?目前,我正在使用 bios\cpu\disk 数据的组合来生成唯一 ID。如果每个指标都有多个结果,我将使用第一个结果。

但是,我遇到了一个问题,即双启动到 2 个不同 Windows 操作系统的机器在每个操作系统上生成不同的站点代码,这在理想情况下不应该发生。

作为参考,这些是我目前使用的指标:

Win32_Processor:UniqueID,ProcessorID,Name,Manufacturer,MaxClockSpeed
Win32_BIOS:Manufacturer
Win32_BIOS:SMBIOSBIOSVersion,IdentificationCode,SerialNumber,ReleaseDate,Version
Win32_DiskDrive:Model, Manufacturer, Signature, TotalHeads
Win32_BaseBoard:Model, Manufacturer, Name, SerialNumber
Win32_VideoController:DriverVersion, Name
4

15 回答 15

75

我遇到了同样的问题,经过一番研究后,我决定最好的办法是按照@Agnus 的建议读取MachineGuid注册表项。HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography它是在操作系统安装期间生成的,除非您重新安装操作系统,否则它不会更改。根据操作系统版本,它可能包含嵌入的网络适配器 MAC 地址(加上一些其他数字,包括随机数)或伪随机数,后者适用于较新的操作系统版本(我相信在 XP SP2 之后,但不确定)。如果它是理论上的伪随机,它可以被伪造 - 如果两台机器具有相同的初始状态,包括实时时钟。在实践中,这种情况很少见,但请注意,如果您希望它成为可能被铁杆黑客攻击的安全基础。

当然,任何人也可以轻松更改注册表项以伪造机器 GUID,但我发现这会破坏 Windows 的许多组件的正常运行,在大多数情况下没有普通用户会这样做(再次,当心对于铁杆黑客)。

于 2009-05-04T15:18:52.640 回答
37

使用我们的许可工具,我们考虑以下组件

  • MAC地址
  • CPU(不是序列号,而是实际的 CPU 配置文件,如步进和型号)
  • 系统驱动器序列号(不是卷标)
  • 记忆
  • CD-ROM 型号和供应商
  • 显卡型号和供应商
  • IDE 控制器
  • SCSI 控制器

然而,我们不只是对组件进行哈希处理并创建通过/失败系统,而是创建一个可比较的指纹,可用于确定两个机器配置文件的差异程度。如果差异等级高于指定的容差,则要求用户再次激活。

在过去的 8 年中,我们发现在数十万最终用户安装中使用这种组合可以很好地提供可靠的唯一机器 ID,即使对于虚拟机和克隆的操作系统安装也是如此。

于 2012-03-07T21:46:52.443 回答
26

自己解析SMBIOS并将其散列到任意长度。请参阅PDF 规范了解所有可用的 SMBIOS 结构。

要从 Windows 查询 SMBIOS 信息,您可以使用EnumSystemFirmwareEntries,EnumSystemFirmwareTablesGetSystemFirmwareTable.

IIRC,来自 CPUID 指令的“唯一 ID”在 P3 和更新版本中已被弃用。

于 2008-09-22T13:48:52.980 回答
3

仅使用处理器的 UniqueID 怎么样?

于 2008-09-19T05:32:30.557 回答
1

您应该考虑使用网卡上的 MAC 地址(如果存在)。这些通常是独一无二的,但可以伪造。我使用了根据您的网络适配器 MAC 地址生成许可证文件的软件,因此它被认为是区分计算机的一种相当可靠的方法。

于 2008-09-19T05:32:01.617 回答
1

我讨厌成为那种说“你做错了”的人(我一直讨厌那个人;)但是......

是否必须为独特的机器重复生成?你可以只分配标识符或做一个公钥/私钥吗?也许如果您可以生成并存储该值,您可以从同一磁盘上的两个操作系统安装中访问它?

您可能已经探索过这些选项,但它们对您不起作用,但如果不是,则需要考虑。

如果这不是用户信任的问题,您可以只使用 MAC 地址。

于 2008-09-19T05:36:45.927 回答
1

在我的程序中,我首先检查终端服务器并使用 WTSClientHardwareId。否则本地 PC 的 MAC 地址应该足够了。

如果您真的想使用您提供的属性列表,请忽略Nameand DriverVersionClockspeed等内容,因为它可能取决于操作系统。尝试在两个操作系统上输出相同的信息,并忽略不同的信息。

于 2008-11-14T11:12:57.627 回答
1

对于我的一个应用程序,如果它是非域计算机,我要么使用计算机名称,要么使用域计算机的域计算机帐户 SID。Mark Russinovich 在这篇博文Machine SID中谈到了这一点:

SID 重复成为问题的最后一种情况是分布式应用程序使用机器 SID 来唯一标识计算机。没有 Microsoft 软件会这样做,并且以这种方式使用机器 SID 并不能仅仅因为所有 DC 都具有相同的机器 SID 的事实。依赖于唯一计算机身份的软件要么使用计算机名称,要么使用计算机域 SID(域中计算机帐户的 SID)。

您可以通过 LDAP 或System.DirectoryServices.

于 2011-03-31T16:04:54.660 回答
1

有一个库可用于获取硬件特定信息:硬件序列号提取器(CPU、RAM、HDD、BIOS)

于 2014-03-13T08:26:52.427 回答
0

为什么不使用网卡的 MAC 地址?

于 2008-09-19T05:35:37.427 回答
0

也许有点作弊,但现在机器以太网适配器的 MAC 地址很少在不改变主板的情况下改变。

于 2008-09-19T05:36:16.863 回答
0

您可以提取某种制造商序列号或服务标签吗?

我们的商店是戴尔商店,因此我们使用每台机器唯一的服务标签来识别它们。我知道它可以从 BIOS 中查询,至少在 Linux 中是这样,但我不知道如何在 Windows 中临时做到这一点。

于 2008-09-19T05:36:54.053 回答
0

我有一个额外的限制,我使用的是 .net express,所以我不能使用标准的硬件查询机制。所以我决定使用 power shell 来进行查询。完整的代码如下所示:

Private Function GetUUID() As String
    Dim GetDiskUUID As String = "get-wmiobject Win32_ComputerSystemProduct  | Select-Object -ExpandProperty UUID"
    Dim X As String = ""
    Dim oProcess As New Process()
    Dim oStartInfo As New ProcessStartInfo("powershell.exe", GetDiskUUID)
    oStartInfo.UseShellExecute = False
    oStartInfo.RedirectStandardInput = True
    oStartInfo.RedirectStandardOutput = True
    oStartInfo.CreateNoWindow = True
    oProcess.StartInfo = oStartInfo
    oProcess.Start()
    oProcess.WaitForExit()
    X = oProcess.StandardOutput.ReadToEnd
    Return X.Trim()
End Function
于 2018-07-03T19:50:25.723 回答
-1

查找 CPUID 以获取一个选项。多 CPU 系统可能存在一些问题。

于 2008-09-19T05:35:14.463 回答
-1

试试这个,它提供了一个唯一的硬盘 ID:Port of DiskId32 for Delphi 7-2010

于 2013-06-27T11:03:13.670 回答