生成唯一硬件ID的可靠方法

37

问题:我需要为每个网络客户端设计一个唯一的标识符,要求:

  • 该标识符应在客户端软件安装到目标计算机后保留,并且在同一计算机和操作系统上重新安装软件时也应保持不变。
  • 除更换主板外,硬件配置的大多数修改都不应该改变该标识符。
  • 当已安装有客户端软件的硬盘被克隆到具有相同硬件配置(或尽可能相似)的另一台计算机时,客户端软件应意识到这种变化。

一点解释和背景:

这个问题基本上是一个古老的问题,也触及了软件拷贝保护的主题,因为其中提到了一些用于该领域的机制。此时我应该明确,我不是在寻找拷贝保护方案。请继续往下看。:)

我正在开发一款客户端服务器软件,该软件应该在本地网络中运行。我需要解决的一个问题是识别网络中的每个唯一客户端(不是很难),以便我可以对每个特定客户端应用某些属性,并在特定客户端的部署寿命期间保留和强制执行这些属性。

在我寻找解决方案时,我意识到以下内容:

  • Windows激活系统使用某种非常敏感的硬件指纹机制,
  • 磁盘映像软件复制所有卷ID(与格式化时每个分区相关联),以及在安装过程中生成的自定义唯一ID,在首次运行时或以其他方式严格存储在注册表或硬盘上,因此很容易将两者混淆。

对于这种问题,明显的选择就是找出BIOS标识符(虽然不确定是否通过相同的主板型号是唯一的),因为这是我唯一可以依赖的东西,它不会被复制、克隆,并且不能被更改(至少不能使用某些用户空间程序)。其他方案要么不可靠(如MAC克隆),要么要求太高(太敏感于配置更改)。

我想要问的一个子问题是,从架构层面来看,我是否做得正确?也许有更好的工具可以完成我需要完成的任务...

我考虑过另一种方法,类似于握手机制,其中服务器维护一个内部查找表以连接客户端ID(可以完全基于软件且在任何给定时刻都不唯一),如果在连接时提供了重复的ID,则告诉客户端在握手期间提供不同的ID。然而,这种方法不能很好地满足将属性与特定客户端绑定的要求。


嗨,B先生,这是一个有趣的问题,我进行了一些研究,因为它引起了我的兴趣。但是,从不同的角度来看,您是否正在寻找一种在连接到服务器后唯一标识用户的方法?如果可以在用户级别上实现,而不是机器级别上,您可以在服务器端生成ID并存储在机器上吗?类似于会话ID如何跟踪Web应用程序中的用户并存储Cookie(但将其持久化更长时间)? - Alex KeySmith
4个回答

10
您需要的是 Windows WMI。您可以获取主板ID(在相同类型的主板中是唯一的)或许多其他类型的唯一标识符,并想出一些聪明的种子函数来生成UHID。哇,我刚刚编了一个缩写?
而如果您特别想获取主板(BIOS)ID:
WMI class: Win32_BIOS
Namespace: \Root\Cimv2

文档:http://msdn.microsoft.com/en-us/library/aa394077(VS.85).aspx
示例代码:http://msdn.microsoft.com/en-us/library/aa390423%28VS.85%29.aspx

编辑:您没有指定语言(但我假设是C++),但这可以在Java(使用COM驱动程序)和任何.NET语言中完成。


没错,我没有指定语言,因为我认为具体的语言与问题本身无关。我对实现这个目标的更高层次的方法感兴趣。我觉得你的答案非常精确。我需要找出的唯一一件事是这个接口的向后兼容性如何,也就是说,使用这种方法支持多老的主板? - mr.b
我非常确定自90年代初期至中期以来,所有BIOS都已经标准化。WMI自Windows 2000以来就存在(并且可作为Windows 95和Windows NT的补丁程序提供)。简而言之,您无需担心 :) 它是完全向后兼容的,除非您要在Windows 3.1或30年前构建的计算机上安装软件。 - David Titarenco
该死,90年代早中期已经过去了15-20年...时间过得真快啊!我知道最近的过去(比如说10年前以及以后),大多数厂商都采用了这些标准化的方式,并且很想听听它们在时间上的延续情况。现在我有了答案。谢谢。 - mr.b
我已经得出了关于支持唯一的与BIOS相关的标识符的结论。不幸的是,4-5个主板(全部为1-2年)都没有BIOS SerialNumber。我做错了什么吗?我正在使用提到的属性来生成唯一的ID,但是毫无作用...有什么想法吗? - mr.b
无论如何,结果证明这不是我的问题的解决方案。我将采用一个通用答案。 - mr.b
2
WMI并非所有计算机都默认提供的功能。此外,它也很容易出现故障。我曾经遇到过这种情况。幸运的是,有一种解决方法(http://searchwindowsserver.techtarget.com/tip/Repairing-damaged-WMI)。无论如何,在这些情况下,许可证验证代码可能会失败。 - Gabriel

10

我认为你应该构建与你要求相对应的唯一标识符。 可以通过重要信息(有关软件和硬件组件的某些信息)的哈希(如MD5、SHA1或SHA512)来构建此ID。

如果使用私钥对此哈希值进行签名,并且在启动期间您的软件验证密钥(已签名的哈希值),则可以使您的解决方案更加安全。(只需将公钥与软件一起安装即可)。 您可以通过不同的在线服务扩展此类解决方案,但企业客户可能会发现在线服务不那么理想。


软件组件不可靠,因为它很容易被克隆,对吧?像你提出的那样,将两个组件结合起来可能是更好的解决方案,因为这可以使远程服务器识别克隆客户端并调用它们。好主意。谢谢。 - mr.b
2
我的意思是,您可以生成一个包含所有重要信息(这些信息在计算机克隆期间不变)的字符串或字节数组。然后,从这个字节数组计算哈希值。这个哈希值将成为您的唯一标识符。您在软件安装期间保存这样的哈希值。每次启动软件时,您都会再次计算ID(哈希),并与安装期间保存的值进行比较。这不是您想要的吗?如何读取硬件信息不是问题。有很多方法,包括WMI。 - Oleg
谢谢,我可能过于描述了,出于最好的意图解释我想要完成的目标。我并不是想说我在寻找精确的代码解决方案,而是在寻找一些唯一可识别的信息,例如BIOS和/或主板ID字符串。如何读取它是另一回事(尽管我已经得到了可以读取它的精确位置)。确实,WMI可能不是正确的选择,正如你所建议的那样。对于混淆感到抱歉。老实说,我正在寻求有关该主题的第二个意见,这正是我从你们两个人那里得到的。非常感谢! - mr.b
更加诚实地说,你们两个都给出了完全可接受的答案,但是我想标记一个更接近我期望的答案。这样做可能会更好些。 - mr.b
没问题,我有足够的声望点数。不用谢。如果我发现一个问题,它让我想起了几年前的自己,那就很有趣了。由于我的以前经验,我非常清楚如何实现你正在寻找的东西。所以欢迎你,祝你好运! - Oleg
显示剩余3条评论

5

这个项目的好处是用户不必费力去更改MAC地址,因为这样做不会带来任何好处(因为它不是软件保护的形式)。但是,由于程序的性质,很遗憾硬盘序列号不是一个选择:( MAC地址很麻烦,因为即使在网络计算机关闭NIC时也不会公开其MAC地址... :(这意味着大多数用户不会乱动他们的NIC(因为他们不应该,因为此程序与网络密切相关)。 - mr.b

5

MAC地址
永远不要依赖MAC地址!它并不是永久的。用户可以在30秒内轻松更改它 (点击此处)。

卷标ID
永远不要依赖卷标ID!它也不是永久的。用户可以轻松更改它,甚至只需格式化驱动器即可。

WMI
WMI是一项服务。可以轻松禁用。实际上,我尝试过,在许多计算机上它都被禁用或损坏(是的,经常会出现这种情况)。

许可服务器
连接到验证服务器可能会给您带来很多麻烦,因为:
* 您的客户可能并不总是连接到互联网。
* 您的客户可能使用特殊设置(路由器/NAT/代理/网关),需要在您的程序中输入这些设置,以允许其连接到验证服务器。
* 他们可能位于防火墙后面,该防火墙将阻止所有程序,除了少数几个(我的情况)。在某些情况下,防火墙可能不受他们的控制(适用于大多数企业用户)!
* 很容易将您的程序重定向到一个本地虚假Web服务器,以模拟您的许可服务器 (点击此处)。

硬件数据
如果您需要强大的保护,您需要依赖硬件。一些用户无法编辑的东西。例如Intel/AMD CPU中可用的CPU ID指令和写入驱动器IDE接口的序列号。
CPU ID和HDD ID是永久的。即使在计算机格式化并重新安装Windows后,它们也不会改变。

这是可以实现的。例如此库读取计算机的硬件ID。该库提供了已编译的演示程序以及源代码/DLL。免责声明:链接指向商业产品(19€/无版税)。


9
抱歉,这并没有回答问题——它只是链接到一个商业网站,提供了一个所谓的 DLL 文件来“解决问题”。请问需要翻译什么? - robnick
@robnick - 它还显示哪些选项保证不起作用 :) - Gabriel
@robnick...我并没有强迫任何人从口袋里“提取”钱来购买那个DLL。我只是建议说,因为其他人已经做到了,所以这是可能的。问问题的人可以实现自己的ASM代码来从IDE驱动器接口板获取ID。但如果他开始深入研究高级硬件文档以编写自己的ASM代码,以节省19欧元,那么他必须非常吝啬。 - Gabriel
我敢肯定我回复了你最近的评论。看,你正在回复4年前的评论。更新你的答案以使其更清晰,做得很好。 - robnick

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