你可以让它更复杂一点,但最终它会归结为一个(或几个)布尔值:要么运行代码,要么不运行。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 分钟的“进出”破解会话变成破解者数周的工作,因为他不仅需要找到和破解您的验证码,但他还必须进行测试以确保一切正常,并且他不只是修复诱饵或不情愿地创建令人讨厌的错误。现在,他只是无法确定没有测试。
最后,破解程序集只是更改几个字节的问题,您无法阻止任何人更改程序集文件中的字节。一切都可以破解。
但是,您可以使查找必须更改的字节变得更加困难,至少,您可以避免出现“您要查找的字节就在这里”的字符串。