生成唯一的机器 ID

发布于 2024-07-05 19:50:39 字数 667 浏览 10 评论 0原文

我需要编写一个函数来生成一个对于运行 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

I need to write a function that generates an id that is unique for a given machine running a Windows OS.

Currently, I'm using WMI to query various hardware parameters and concatenate them together and hash them to derive the unique id. My question is, what are the suggested parameters I should use?
Currently, I'm using a combination of bios\cpu\disk data to generate the unique id. And am using the first result if multiple results are there for each metric.

However, I ran into an issue where a machine that dual boots into 2 different Windows OS generates different site codes on each OS, which should ideally not happen.

For reference, these are the metrics I'm currently using:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

挽清梦 2024-07-12 19:50:40

从 Windows 10 1607(“周年更新”Build 14393)开始,系统可以通过 Windows.System.Profile.SystemIdentification 类。 GetSystemIdForPublisher() 返回一个设备 ID,即

在 Windows 重新启动、重新安装和升级(包括全新安装)后仍然存在

此 API 使用 TPM 或 UEFI。 如果两者都不存在,系统会生成一个新 ID 并将其保留在注册表中。 在此情况下,上述保证不成立。 API 将通过 来源 属性。

以下 C++ 代码请求设备 ID 并将十六进制编码表示与其源一起打印到 STDOUT:

#include <winrt/Windows.System.Profile.h>
#include <winrt/Windows.Security.Cryptography.h>

#include <iostream>

namespace wsp = ::winrt::Windows::System::Profile;
namespace wsc = ::winrt::Windows::Security::Cryptography;

int main()
{
    auto buffer = wsp::SystemIdentification::GetSystemIdForPublisher();

    auto const id = buffer.Id();
    auto const hex_id = wsc::CryptographicBuffer::EncodeToHexString(id);

    ::std::wcout << L"Id: " << hex_id.c_str() << ::std::endl;

    wchar_t const* src = nullptr;
    switch (buffer.Source())
    {
    case wsp::SystemIdentificationSource::Tpm:
        src = L"TPM";
        break;
    case wsp::SystemIdentificationSource::Uefi:
        src = L"UEFI";
        break;
    case wsp::SystemIdentificationSource::Registry:
        src = L"Registry";
        break;
    case wsp::SystemIdentificationSource::None:
        src = L"None";
        break;
    default:
        src = L"<unknown>";
        break;
    }

    ::std::wcout << L"Source: " << src << ::std::endl;
}

此标准“Windows 控制台应用程序 (C++/WinRT)”具有以下 packages.config 文件:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Windows.CppWinRT" version="2.0.230706.1" targetFramework="native" />
</packages>

Raymond Chen 的博客文章 如何获得 Windows 系统的签名,即使该签名也将保持不变如果用户重新安装 Windows? 还有一些文档中未详细说明的详细信息。

Starting with Windows 10 1607 ("Anniversary Update" Build 14393), the system can generate a unique device ID via the Windows.System.Profile.SystemIdentification class. GetSystemIdForPublisher() returns a device ID, that

Persists across restarts, reinstalls and upgrades of Windows, including clean installs

This API uses the TPM or UEFI. If neither is present, the system generates a new ID and persists it in the registry. In that case, the above guarantees do not hold. The API will report how reliable the ID is through the Source property.

The following C++ code requests the device ID and prints a hex-encoded representation to STDOUT alongside its source:

#include <winrt/Windows.System.Profile.h>
#include <winrt/Windows.Security.Cryptography.h>

#include <iostream>

namespace wsp = ::winrt::Windows::System::Profile;
namespace wsc = ::winrt::Windows::Security::Cryptography;

int main()
{
    auto buffer = wsp::SystemIdentification::GetSystemIdForPublisher();

    auto const id = buffer.Id();
    auto const hex_id = wsc::CryptographicBuffer::EncodeToHexString(id);

    ::std::wcout << L"Id: " << hex_id.c_str() << ::std::endl;

    wchar_t const* src = nullptr;
    switch (buffer.Source())
    {
    case wsp::SystemIdentificationSource::Tpm:
        src = L"TPM";
        break;
    case wsp::SystemIdentificationSource::Uefi:
        src = L"UEFI";
        break;
    case wsp::SystemIdentificationSource::Registry:
        src = L"Registry";
        break;
    case wsp::SystemIdentificationSource::None:
        src = L"None";
        break;
    default:
        src = L"<unknown>";
        break;
    }

    ::std::wcout << L"Source: " << src << ::std::endl;
}

This standard "Windows Console Application (C++/WinRT)" has the following packages.config file:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Windows.CppWinRT" version="2.0.230706.1" targetFramework="native" />
</packages>

Raymond Chen's blog post How can I get a signature for a Windows system that will remain unchanged even if the user reinstalls Windows? has a few more details that aren't spelled out in the documentation.

爱你是孤单的心事 2024-07-12 19:50:40

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

Maybe cheating a little, but the MAC Address of a machines Ethernet adapter rarely changes without the motherboard changing these days.

罗罗贝儿 2024-07-12 19:50:40

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

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

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

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

I hate to be the guy who says, "you're just doing it wrong" (I always hate that guy ;) but...

Does it have to be repeatably generated for the unique machine? Could you just assign the identifier or do a public/private key? Maybe if you could generate and store the value, you could access it from both OS installs on the same disk?

You've probably explored these options and they doesn't work for you, but if not, it's something to consider.

If it's not a matter of user trust, you could just use MAC addresses.

浅忆流年 2024-07-12 19:50:40

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

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

Can you pull some kind of manufacturer serial number or service tag?

Our shop is a Dell shop, so we use the service tag which is unique to each machine to identify them. I know it can be queried from the BIOS, at least in Linux, but I don't know offhand how to do it in Windows.

离去的眼神 2024-07-12 19:50:40

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

I had an additional constraint, I was using .net express so I couldn't use the standard hardware query mechanism. So I decided to use power shell to do the query. The full code looks like this:

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
慕巷 2024-07-12 19:50:40

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

Look up CPUID for one option. There might be some issues with multi-CPU systems.

不弃不离 2024-07-12 19:50:39

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

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

In my program I first check for Terminal Server and use the WTSClientHardwareId. Else the MAC address of the local PC should be adequate.

If you really want to use the list of properties you provided leave out things like Name and DriverVersion, Clockspeed, etc. since it's possibly OS dependent. Try outputting the same info on both operating systems and leave out that which differs between.

自由如风 2024-07-12 19:50:39

对于我的一个应用程序,如果是非域计算机,则使用计算机名称;如果是域计算机,则使用域计算机帐户 SID。 Mark Russinovich 在这篇博文中讨论了这个问题,机器 SID< /a>:

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

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

For one of my applications, I either use the computer name if it is non-domain computer, or the domain machine account SID for domain computers. Mark Russinovich talks about it in this blog post, Machine SID:

The final case where SID duplication would be an issue is if a distributed application used machine SIDs to uniquely identify computers. No Microsoft software does so and using the machine SID in that way doesn’t work just for the fact that all DC’s have the same machine SID. Software that relies on unique computer identities either uses computer names or computer Domain SIDs (the SID of the computer accounts in the Domain).

You can access the domain machine account SID via LDAP or System.DirectoryServices.

烟酉 2024-07-12 19:50:39

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

What about just using the UniqueID of the processor?

夏末的微笑 2024-07-12 19:50:39

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

You should look into using the MAC address on the network card (if it exists). Those are usually unique but can be fabricated. I've used software that generates its license file based on your network adapter MAC address, so it's considered a fairly reliable way to distinguish between computers.

热鲨 2024-07-12 19:50:39

自己解析 SMBIOS 并将其哈希为任意长度。 有关所有可用的 SMBIOS 结构,请参阅 PDF 规范

要从 Windows 查询 SMBIOS 信息,您可以使用 EnumSystemFirmwareEntriesEnumSystemFirmwareTablesGetSystemFirmwareTable

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

Parse the SMBIOS yourself and hash it to an arbitrary length. See the PDF specification for all SMBIOS structures available.

To query the SMBIOS info from Windows you could use EnumSystemFirmwareEntries, EnumSystemFirmwareTables and GetSystemFirmwareTable.

IIRC, the "unique id" from the CPUID instruction is deprecated from P3 and newer.

清君侧 2024-07-12 19:50:39

通过我们的许可工具,我们考虑以下组件

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

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

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

With our licensing tool we consider the following components

  • MAC Address
  • CPU (Not the serial number, but the actual CPU profile like stepping and model)
  • System Drive Serial Number (Not Volume Label)
  • Memory
  • CD-ROM model & vendor
  • Video Card model & vendor
  • IDE Controller
  • SCSI Controller

However, rather than just hashing the components and creating a pass/fail system, we create a comparable fingerprint that can be used to determine how different two machine profiles are. If the difference rating is above a specified tolerance then ask the user to activate again.

We've found over the last 8 years in use with hundreds of thousands of end-user installs that this combination works well to provide a reliably unique machine id - even for virtual machines and cloned OS installs.

水晶透心 2024-07-12 19:50:39

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

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

I had the same problem and after a little research I decided the best would be to read MachineGuid in registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography, as @Agnus suggested. It is generated during OS installation and won't change unless you make another fresh OS install. Depending on the OS version it may contain the network adapter MAC address embedded (plus some other numbers, including random), or a pseudorandom number, the later for newer OS versions (after XP SP2, I believe, but not sure). If it's a pseudorandom theoretically it can be forged - if two machines have the same initial state, including real time clock. In practice, this will be rare, but be aware if you expect it to be a base for security that can be attacked by hardcore hackers.

Of course a registry entry can also be easily changed by anyone to forge a machine GUID, but what I found is that this would disrupt normal operation of so many components of Windows that in most cases no regular user would do it (again, watch out for hardcore hackers).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文