【问题标题】:Verifying license information without a boolean check? [closed]在没有布尔检查的情况下验证许可证信息? [关闭]
【发布时间】:2009-02-10 02:44:09
【问题描述】:

我目前正在使用一个简单的 XML 文件,其中包含许可证信息以及数据的签名和公钥。到目前为止,这种方法效果很好。但是,我看到了一个相当大的安全漏洞......

当我的 ASP.NET MVC 应用程序启动时,它会验证许可证并相应地设置“ValidLicense”布尔属性。在每次请求期间,都会检查此属性,如果许可证无效,则会显示错误消息。

您可以猜到,无论许可证的有效性如何,绝对没有什么可以阻止合格的用户简单地修改我的程序集以将“ValidLicense”设置为 true。我知道这几乎可以用于任何应用程序,但使用 .NET 程序集似乎非常容易。

有什么方法可以阻止这种情况发生,或者至少让破解许可证验证程序变得更加困难?

如果可能的话,我宁愿远离程序集加密和混淆系统。但是,如果您认为它们足够好,可以保证成本和额外的头痛,请继续建议它们。

【问题讨论】:

    标签: c# asp.net-mvc licensing


    【解决方案1】:

    赢的唯一方法就是不玩。

    将窃取您的东西的人(无论您采取了何种保护措施),不是如果他们很难破解,他们会为此付出代价。

    【讨论】:

    • 我同意,不要专注于许可证安全...专注于让人们想要购买您的软件的功能。无论您采取何种预防措施,简单或复杂,您都永远无法摆脱盗版。因此,免去您的麻烦,尽量为您的合法客户提供最好的产品。
    【解决方案2】:

    您可以在每次需要验证许可证并将逻辑基于该计算的结果时执行复杂的计算,而不是简单的布尔变量。不过,您确实会受到打击。无论如何,破解你的程序集也不会那么难。

    您还可以使用一些更高级的技术,例如代码的动态变异和使用相应的可变函数来控制逻辑流。

    但是,您应该问问自己,您的程序集是否真的包含如此宝贵的知识产权,以保证花费时间和精力来实施这样的事情?走合法途径并与潜在的盗版作斗争可能更可行,成本更低。

    【讨论】:

      【解决方案3】:

      你可以让它更复杂一点,但最终它会归结为一个(或几个)布尔值:要么运行代码,要么不运行。非混淆的 .NET 代码与开源代码几乎相同,而且非常容易破解。

      即使混淆不是一个完整的解决方案,我认为混淆是有意义的,只是为了防止边缘业余爱好者制作破解版本。

      当然这不会阻止真正的饼干愿意花时间,但只要把门槛提高一点,你就可以淘汰很多喜欢饼干的人。

      混淆可以很简单地免费实现。如果您有 Visual Studio 的商业版本,则可以使用 DotFuscator(不是“Express”版本)。我从未尝试过,但我想应该很简单。

      否则,您可以使用 Assemblur。 (http://www.metapropeller.com/)。免费版是一个命令行应用程序(有一个 GUI 来创建设置文件,但您需要从命令行运行设置)。

      总而言之,混淆一个简单的 exe 文件只需几分钟,而且是免费的

      如果你想让你的license检查更具挑战性,你可以在各种方法中进行不同的检查,你也可以确保license检查代码实际上不会直接输出任何字符串。 (例如,您在方法 A 中进行了许可证检查,但您从方法 B 输出了错误警告,因此当破解者查找许可证错误消息时,他不会正确地找到要更改的代码位) .

      它所做的只是提高了想成为饼干的人的标准,并使真正的饼干变得更加复杂。

      案例 1:具有 1 种许可检查方法的非混淆 .NET 应用程序输出“未许可”错误消息。 任何可以运行反射器的人都可以在大约 5 分钟内破解。

      案例 2:混淆的 .NET 应用程序,带有几个不同的许可证检查,并且没有明显的字符串输出。 一个饼干可能需要几个小时,对于一个想要的人来说太难了。

      您可以从案例 1 到案例 2 只需大约 1 小时的工作,而无需花费一分钱。超出此范围可能是浪费时间(所有 都可以破解),但至少,您可以淘汰那些在 Reflector 中打开您的应用程序的人,看看它是否容易。如果这个人在反射器中打开应用程序并看到类似的内容:

      public bool ValidateLicense(string sLicense)
      {
          string sInvalidLicense = "Your license is not valid";
          ...
      }
      

      猜猜接下来会发生什么?

      //编辑:在评论中,LC 问:

      你怎么不让它输出任何字符串消息但仍然通知用户?即使您以两种不同的方法进行许可证检查和输出,您仍然会有二元决策“if(!ValidateLicense(LicenseCode)) {NotifyUserOfInvalidLicense(); throw new LicenseException();}”之类的,不是吗?

      设身处地地为自己着想:您正在寻找许可证验证码。您不会为了找到它而研究整个代码。相反,您在未经许可的情况下运行应用程序:出现错误消息。

      您获取该错误消息,在 Refactor 中打开程序集并搜索该错误消息的一部分。

      如果该字符串位于“ValidateLicence()”内,您会立即找到 ValidateLicence() 函数。从那里,您只需要找到返回值并更改该 1 个字节。完成。

      如果在 "WhatEver()" 中找到了字符串,您仍然需要找到调用 "WhatEver()" 的方法。它甚至可能不在同一个程序集中(在这种情况下,Refactor 不会为您找到它)。这使您的想成为饼干的人的工作变得更加困难。他将不得不查看该方法以了解它如何验证代码(它没有)。他甚至可能草率地更改了错误方法的返回值,在这种情况下他引入了一个错误(如果方法被混淆了,弄清楚它的作用并不是那么简单)。

      更好的是,根本不要使用字符串:您可以将错误消息存储为十六进制代码序列,并在需要显示消息时将其动态转换为字符串。没有错误字符串意味着破解者将不得不依靠其他东西来定位您的许可证验证码。阅读混淆代码并不好玩。

      您还可以使用包含错误消息的虚假验证方法并隐藏警告以使其看起来像破解工作。

      因此,像这样的一些简单、愚蠢的技巧 + 简单的混淆非常容易实现,它们可以将 5 分钟的“进出”破解会话变成破解者数周的工作,因为他不仅需要找到并破解您的验证码,但他还必须进行测试以确保一切正常,并且他不只是修复诱饵或不情愿地创建令人讨厌的错误。现在,如果不进行测试,他就无法确定。

      最后,破解程序集只是更改几个字节的问题,您无法阻止任何人更改程序集文件中的字节。一切都可以破解。

      但是,您可以使查找必须更改的字节变得更加困难,至少,您可以避免出现“您要查找的字节就在这里”的字符串。

      【讨论】:

      • 请不要把“能看源码”和“开源”混为一谈;后者具有开放许可含义,而前者不一定保证该权利。
      • 你怎么不让它输出任何字符串消息但仍然通知用户?即使您以两种不同的方法进行许可证检查和输出,您仍然会有二元决策“if(!ValidateLicense(LicenseCode)) {NotifyUserOfInvalidLicense(); throw new LicenseException();}”之类的,不是吗?
      • @Rob:“能够看到源代码”/“开源”。我只是指这样一个事实,即使用 .NET 程序集访问代码几乎一样容易。当然,仅仅因为你可以看到代码并没有给你这样做的权利。
      【解决方案4】:

      我在尝试破解一个小型 .NET 产品时遇到的一种方法是使用非托管 .DLL 进行许可证检查。不仅如此,.DLL 还包含大量软件中实际使用的代码。因此,要破解产品,我实际上必须破解非托管的 .DLL(或制作完美的包装器)。不用说,这阻止了像我这样的狂热饼干。 :)

      【讨论】:

        猜你喜欢
        • 2019-01-25
        • 2011-04-18
        • 1970-01-01
        • 1970-01-01
        • 2019-06-02
        • 1970-01-01
        • 2013-06-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多