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

目前,我正在使用 WMI 查询各种硬件参数,并将它们连接在一起并对它们进行哈希处理以得出唯一的 id。我的问题是,我应该使用哪些建议参数?目前,我使用 BIOS\CPU\磁盘数据的组合来生成唯一 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
有帮助吗?

解决方案

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

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

IIRC,CPUID 指令中的“唯一 ID”从 P3 及更高版本中已弃用。

其他提示

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

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

跟我们 许可工具 我们考虑以下组成部分

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

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

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

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

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

您可能已经探索过这些选项,但它们并不适合您,但如果不适合,则需要考虑。

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

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

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

对于我的一个应用程序,如果是非域计算机,则使用计算机名称;如果是域计算机,则使用域计算机帐户 SID。马克·鲁西诺维奇 (Mark Russinovich) 在这篇博文中谈到了这一点, 机器SID:

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

您可以通过LDAP或访问域机器帐户SID System.DirectoryServices.

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

如果您确实想使用您提供的属性列表,请忽略以下内容 NameDriverVersion, Clockspeed, , ETC。因为它可能依赖于操作系统。尝试在两个操作系统上输出相同的信息,并忽略不同的信息。

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

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

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

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

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

我有一个额外的限制,我使用的是 .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

查找 CPUID 以获得一个选项。多 CPU 系统可能会出现一些问题。

试试这个,它给出了一个唯一的硬盘 ID: Delphi 7-2010 的 DiskId32 端口.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top