在哪里可以存储(和管理)应用程序许可证信息?

29

我正在开发一个Windows应用程序。它需要用户注册才能使用... 现在,我将许可证信息存储为APpData中的文件。但删除该文件会重置试用版本日期。因此,我现在计划将其保存在注册表中。但是,大多数用户在Windows中没有管理权限(受限用户)以访问注册表。我该怎么办?在哪里可以保存我的序列号和日期?


如果用户需要安装应用程序,则仍然需要安装权限,因此需要管理员帐户,因此,如果您将其存储在注册表中,则可以。此外,类似的问题在这里讨论:https://dev59.com/tHA65IYBdhLWcg3wzx9l - Usman Waheed
1
为什么不对密钥进行编码并将其保存在数据库中? - Kurubaran
@UsmanWaheed 安装我的应用程序不需要管理员权限,它也不使用任何注册表... - Yesudass Moses
@AccessDenied 它已经被加密并存储在AppData文件夹中的文件中了...但问题是,如果用户在程序到期后删除了该文件...程序将无法获取安装日期信息,因此它将创建另一个带有试用版本的文件...用户将获得额外的30天。 - Yesudass Moses
@YesudassMoses 我在我的答案中提出了一些解决方法,但是...就像我之前所说的那样...如果他们真的想要做到,无论你付出多少努力(想想 Microsoft 或蓝光光盘复制保护这样的 10^9 美元公司)他们都会去做。 - Adriano Repetti
3个回答

77
在我看来,关键是要改变您管理许可证的方式。

在哪里存储许可证数据?

如果他们删除了许可证数据文件,那么试用版会重新开始吗? 如果文件不存在,则不要启动应用程序,并在第一次安装时使用安装操作创建它。

现在你面临第二个问题:如果他们卸载并重新安装应用程序怎么办? 第二步是将此文件移动到应用程序数据文件夹中(例如Environment.SpecialFolder.CommonApplicationData)。 这仅稍微安全一些(因为卸载时不会删除应用程序数据),但他们仍然有可能手动找到并删除它。 如果低权限用户安装应用程序,则无多少可做的(您无法尝试在注册表中隐藏许可证)。

现在这是你和破解者之间的游戏。 他们总是会获胜。 您只会增加合法用户的生活难度,因此请慎重考虑。 存储许可证数据的位置:

  • 注册表。 优点:易于执行。 缺点:易于破解,对于低权限用户,每次只能在一个用户中有效。 如果注册表键(在每个用户基础上)具有\0在其名称中,则可以隐藏。 请参见帖子。
  • 文件。 优点:易于执行,并且在我的意见中比注册表更安全。 缺点:易于破解(但您可以将其隐藏得更多,稍后再看)。
  • 应用程序本身(将数据附加到可执行文件上,在此帖子中简要介绍)。 优点:更难检测。 缺点:杀毒软件可能会将其视为...病毒,应用程序更新也可能删除许可证(当然,如果您没有正确处理此情况),因此它将使您的代码和部署更加复杂。

如何在文件中隐藏许可证?
如果使用文件(无论其位于何处),则可以考虑使破解者的生活变得(略微)困难一些。 现在我想到了两种解决方案:

  • 备用数据流。文件附加到另一个文件上,他们不会在Windows Explorer中仅通过搜索看到它。 当然有一些工具可以管理它们,但至少他们必须明确地搜索它。

  • 将其隐藏在应用程序数据中(例如,使用隐写术的位图)。他们不知道这是许可证数据,更安全的是什么?问题是他们可以轻松反编译你的C#程序以查看你的操作(请参阅代码混淆一节)。

    可能还有其他方式(幻想是我们的主人),但别忘了……黑客会找到它(如果他们真的想要),所以你必须平衡自己的努力。

    如何做到

    保持你的许可架构,你现在走上了一条死路。你需要决定的是,如果他们使用试用期比允许的时间更长的风险高于因乏味的保护而停止使用你的应用程序的风险。

    验证
    如果你可以假设用户拥有网络连接,那么你可以使用一些 唯一标识符 在线验证许可证(仅在用户首次运行应用程序时)。即使是针对Windows 8的应用程序,你也可以参考这篇SO帖子。服务器端的验证可能会非常棘手(如果你想以正确的方式来做),在这篇帖子中,解释了如何在适当的方式下管理程序流程。

    数据混淆/加密
    您的许可文件/数据现在已经安全存放。黑客几乎无法找到它。现在您需要进行另一个步骤:混淆。如果您的许可数据以纯文本形式存在,一旦他们找到您的文件就太容易更改了。您有几个选项(按安全性和复杂性顺序排列):

    • 混淆您的文件。如果他们无法使用简单的文本编辑器(甚至十六进制编辑器)理解文件内部内容,那么他们将需要更多的时间和精力来破解它。例如,您可以将它们压缩:参见此处关于使用压缩的XML文件混淆的帖子。请注意,即使是简单的Base64编码也可以混淆您的文本文件。
    • 使用对称算法加密它们。即使是非常简单的算法也可以很好地工作,这里你只是试图隐藏数据。有关示例,请参阅此处的帖子。我不认为有理由选择这种方法而不是更简单的混淆方法。
    • 使用非对称算法加密它们。 这种类型的加密是复杂性和安全性的重大进步,只有在许可令牌由服务器/外部实体提供时才会非常有用。在这种情况下,它将混淆使用其私钥签名的许可证。客户端应用程序将使用其公钥验证签名,即使黑客找到了这个文件(并反编译你的代码来读取公钥),他们仍然不能更改它,因为他们没有私钥。

    请注意,数据混淆/加密可以与上述隐写术相结合使用(例如将加密的许可文件隐藏在图像中)。

    代码混淆
    如果你没有使用非对称加密的许可证签名,那么最后一步是混淆你的代码。无论你做什么,他们都能看到你的代码,检查你的算法并绕过它。很遗憾,你正在部署说明手册。如果你想要混淆,请使用混淆器,但我强烈建议将许可证检查移动到不太明显的地方。

    • 将所有与许可证相关的代码放在单独的DLL中。签名它(请注意,已签名的程序集可能会被反编译和重新编译以删除签名,甚至有工具可以几乎自动完成这个过程)。
    • 将其打包到可执行资源中(使用不太明显的名称),并且不要部署DLL。
    • 处理事件AppDomain.AssemblyResolve,当需要运行时DLL时,您将在内存中解压缩并返回其字节流。有关此技术的更多信息,请参见Jeffrey Richter的这篇文章

    我喜欢这种方法,因为他们会看到有许可证检查,但是...他们找不到许可证代码。当然,任何好的破解者都可以在10分钟内解决此问题,但你将比较(稍微)安全,免受随机攻击。

    结论

    简要总结一下,这是一个提供更强的许可证检查的方法列表(当然可以跳过一个或多个步骤,但这会降低安全性):

    • 将许可证检查代码分成两个程序集(一个用于执行检查和管理许可证,另一个用于向该引擎提供公共接口)。
    • 对所有程序集进行强签名。
    • 嵌入您的许可证引擎程序集到您的许可接口程序集中(请参见代码混淆部分)。
    • 创建一个许可证服务器来管理您的许可证。请注意,使其安全,具有安全连接和安全身份验证(请参见验证部分)。
    • 在本地保存许可证文件到一个安全位置(请参见位置部分),并使用非对称加密算法对其进行加密(请参见数据混淆部分)。
    • 有时使用您的许可证服务器验证许可证(请参见验证部分)。

    补充说明:软件保护狗
    关于硬件密钥(软件保护狗)的一个小补充。它们是保护您的软件的宝贵工具,但是您必须更仔细地设计您的保护。您可以假设硬件本身非常安全,但其与计算机的连接和与您的软件通信的弱点。

    想象一下将许可证简单存储到密钥内,黑客可以使用外部USB(假设你的SPD是USB)将相同的密钥共享给多台计算机。你还应该在密钥中存储一些硬件唯一ID,但在这种情况下,弱点是连接(硬件可以被软件驱动程序仿真)。这是一种相当容易破解的方式,这种虚假的安全感("我正在使用软件保护加密狗,我的软件是安全的")会使你的应用程序更加脆弱(因为你有风险忘记其他基本保护措施来简化许可证管理)。
    对于一个设计不良的SPD所产生的成本与收益比应该让你考虑使用普通的USB闪存驱动器。它只需要1美元而不是15/20美元(或者更多),而且你对随意的黑客具有同样的保护水平。当然,它无法阻止严重的黑客,但是一个设计不良的SPD也无法阻止他们。
    一个真正的保护(假设你不在运行DRM启用设备)是一个可以执行你的代码的加密狗。如果你能将一些基本算法(至少是解密重要的且动态的支持文件)移动到密钥中,那么要破解你的软件,他们就需要破解硬件。对于一台半称职的加密狗,这是一个非常非常非常困难的任务。你越仔细地设计它并将更多的代码移入密钥中,你就会更安全。
    无论如何,你都应该对市场营销活动表示怀疑:使用加密狗的软件保护不是更容易。它可能会(更)安全,但它不像供应商所说的那样容易。在我看来,即插即用的保护成本太高,与其相比,它的收益(即它将使黑客的生活更加艰难)不值得。

PHP和MySQL中的激活服务器,加上机器ID = 排序。 - AStopher
4
绝对没错,我们刚刚实施了类似的架构,依赖于外部 Web 主机。要小心客户端实现,这总是一个薄弱点。正在准备一个带有参考/示例实现的 git。总有一天我会发布... - Adriano Repetti

1
很不幸,无论您在客户机上存储许可证信息的位置是什么,它都容易被滥用(因为这是他们的机器!)。唯一安全的方法是让您的程序与远程服务进行检查,显然,这需要大量的开销。我的做法是,如果客户搞乱了他们的许可证密钥,那么他们应该预料到会有问题,您没有义务提供帮助。我建议确保您的密钥包含有关运行的机器的信息(以防止简单地复制密钥),但否则保持非常简单。在研究许可证时,我发现一种哲学,我倾向于坚持 - 您通过复杂和困难的许可设置驱走了更多的潜在客户,而不是通过盗版失去的客户。我的建议是,您可以反转逻辑 - 不要允许删除许可证密钥来重新启动免费试用,而是强制用户使用许可证密钥来解锁完整应用程序。

是的...序列号基于机器码,只对该机器有用,并且它是MD5加密的...(我还添加了一些填充字符串)...用户不能仅仅复制或解密代码...但是他可以删除文件或密钥...这将让程序认为它是全新安装,并且它将再次创建一个试用版本的许可文件,有效期为30天...这就是问题所在 :-/ - Yesudass Moses
我认为在那种情况下,你的程序不能指望处理它!这时他们必须联系技术支持。 - Liath
抱歉,我误解了 - 正在编辑中 - Liath
2
@YesudassMoses,如果您的应用程序可以在没有许可证的情况下运行,那么这就很奇怪了。即使是试用版也应该需要许可证(不是由您的应用程序在该机器上生成)。我的建议是,如果没有许可证,您的应用程序应始终崩溃并自动关闭。对于试用用户,请为他们提供一个Web门户,以便根据他们的机器生成试用许可证,并检查是否有多个尝试来自单一来源。 - Lex Li

0

如果你要写入 HKEY_CURRENT_USER,你不需要管理员权限。 另一方面,写入 HKEY_LOCAL_MACHINE 需要管理员权限。

当你打开用于写入的键时,请确保像这样调用它

RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\YourAppPath", true);

如果那对你不起作用,还有一个技巧是将内容写入可执行文件的末尾,但那是另一回事。


这是一个好主意……但人们可以从注册表中删除密钥,对吧? - Yesudass Moses
1
当然,如果他们知道自己在做什么,除了其他人建议的方法,我建议您使用组合方法使其尽可能复杂,虽然在线身份验证/激活可能是最好的选择。第一次运行应用程序: 写入文件末尾, 创建加密许可文件, 使用加密值更新注册表键。 这些组合中任何缺失的项目都应该让您知道他们试图进行非法操作,因此在该计算机上关闭它。 - Amro
请考虑发送一个预标记的设置文件/可执行文件,其中包含有关许可证的信息,而不是提供任何人都可以下载的公共下载链接。 - Amro
@OHDev 是的,我同意!如果适用的话,它是存储“隐藏”数据的很好的地方。我总是建议将其用于“支持”文件。如果数据是动态的(比如许可证),我对此还有更多疑虑,因为会受到杀毒软件的影响。 - Adriano Repetti
@Adriano,像LogMeIn这样的网站在您单击添加计算机时会发送一个单独的msi文件,安装时它已经具有值以链接到您用于下载的帐户,我认为防病毒软件不会有问题,也许只有在客户端写入文件末尾时才会出现问题。 - Amro
显示剩余3条评论

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