防止通过接口拦截呼叫

本文关键字:呼叫 接口 | 更新日期: 2023-09-27 18:37:08

我有一个接口,在我的应用程序中通过MEF实现类导出。实现类位于单独的程序集中,在编译时不知道(想想插件)。

接口基本上由一个调用组成,该调用说"这里有一堆键值对,现在初始化您的许可状态"。 即

public LicensingInfo InitialiseLicense(IEnumerable<KeyValuePair<string, string>> keys)

我想知道的是 - 有没有办法保护该接口免受"中间人"实现的影响? 即,一个接收来自我的应用程序的调用,然后使用不同的键值对在插件程序集上调用相同的方法,基本上是说"是的 - 你去 - 拥有一切"。

我确实尝试以不同的方式思考它,因为应用程序将调用插件程序集并传入可以查询的对象。该方法可能如下所示:

public LicensingInfo InitialiseLicense(ILicenseQueryProvider provider)

但是,同样使用这种方法,我认为拦截对象可以简单地为库提供不同的提供程序。

那么,有没有办法防止这种接口拦截,或者我应该重构它,以便插件程序集完全负责它自己的代码中的许可证加载等?或者有没有另一种方法,也许,我可以重构我没有考虑过的它?

防止通过接口拦截呼叫

我相信

你可以让它更难破解,但不能用接口。

以下是您的操作:

你需要 2 + n 个项目:一个用于 exe(我们称之为 program.exe),一个用于合约(合约.dll),一个用于每个 n 个插件(插件.dll)。

program.exe 对 contract.dll 有一个硬引用,插件.dll也是如此。

使用强名称密钥对所有这些进行签名。请参阅 http://msdn.microsoft.com/en-us/library/xc31ft41.aspx

代替接口 ILicenceQueryProvider,在合约.dll中创建一个密封类 LicenceQueryProvider。确保它没有公共构造函数,只有一个内部构造函数,并且没有修改对象的方法(在构造时初始化,不可变且具有只读字段)。

使用 InternalsVisibleToAttribute 标记合约.dll授予程序.exe对内部构造函数的访问权限。请参阅 http://msdn.microsoft.com/en-us/library/System.Runtime.CompilerServices.InternalsVisibleToAttribute.aspx

这样,program.exe可以调用这个对象上的构造函数,插件.dll可以从中读取。

插件.dll"知道"由于强名称签名,对象类尚未被修改。而且因为它是密封的,所以中间的人不能在另一个实现中替代。

现在请记住,我说过,您可以使其更难破解,但这并非不可能,也永远不会,尤其是在使用托管代码时。

例如,中间的人可以使用反射通过内部构造函数实例化对象。

更糟糕的是,在您的插件中,有代码从该对象读取,并根据许可证信息做出决定。黑客可以将您的插件反编译.dll为 IL,并将该代码替换为始终授予所有权限的代码。

混淆只会有所帮助,但不能对抗反射攻击。本机代码会使它更加困难,但本机代码也可以修补。

最终,代码在黑客的机器上,黑客可以为所欲为。他甚至可以在调试器下运行它,并修改内存中的数据。这是所有复制保护和许可机制面临的问题。在我看来,许可证使您的客户更难使用您的软件,并且不会阻止坚定的黑客。您(或您的公司)是否想让您的客户难以使用您的软件?

这并不意味着没有解决方案。事实上是有的:黑客不能修改不在他的机器上的代码。让代码在您控制的服务器上运行。客户端应用通过 Web 服务访问它。Web 服务对用户进行身份验证(而不是调用代码,这是不可能的)。了解用户后,服务可以验证用户的许可证。这是唯一的解决方案。

更新

需要明确的是:这样的服务需要运行对用户有价值的实际代码,而不仅仅是许可证检查。在后一种情况下,黑客可以修改客户端以简单地不调用,甚至替换伪造的许可证服务器。但是,假设许可证比重新创建服务中的实际逻辑便宜。在这种情况下,即使是黑客也更愿意购买而不是重新创建代码。

没有一种防弹的方法可以保护您的软件。

我们曾经使用(广告前)Safenet Inc的Sentinel硬件密钥,dotfuscator pro和智能组装来保护我们的一些应用程序。

硬件密钥

可用于存储许可证(即每个功能/插件都有自己的许可证,可以在硬件密钥上启用并由应用程序查询)。(可选)他们的产品可用于加密您的应用程序 - 应用程序被加密,然后只能在内存中解密并在将正确的硬件密钥附加到系统时启动。有一些反调试机制使某人更难使用调试器,等待应用程序在内存中解密,然后复制它。

Dotfuscator 和智能装配可用于"混淆"应用程序的代码,使使用 Reflector 等工具的反编译更加困难。

不过,这些工具都不是防弹的。但是"实现/偷窃真的真的很痛苦"?我会这么说,但这是有代价的...您肯定可以在这些工具上投入很多钱。