5

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

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

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

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

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

4

4 回答 4

8

获胜的唯一方法就是不玩。

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

于 2009-02-10T03:07:29.180 回答
3

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

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

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

于 2009-02-10T02:53:59.320 回答
1

你可以让它更复杂一点,但最终它会归结为一个(或几个)布尔值:要么运行代码,要么不运行。Non-obfuscated .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 分钟的“进出”破解会话变成破解者数周的工作,因为他不仅需要找到和破解您的验证码,但他还必须进行测试以确保一切正常,并且他不只是修复诱饵或不情愿地创建令人讨厌的错误。现在,他只是无法确定没有测试。

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

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

于 2009-02-10T04:45:32.890 回答
0

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

于 2009-02-10T08:28:41.340 回答