如何防止.NET中的DLL欺骗

时间:2012-11-12 15:13:52

标签: c# .net

我有一个引用托管DLL的.NET应用程序。

此DLL包含一个类,例如ScoreKeeper,它实现了一个名为GetHighScore()的方法。应用程序会定期调用它。

有没有办法阻止.NET应用程序在这里使用“未授权”的DLL代替我提供的DLL?

2 个答案:

答案 0 :(得分:49)

你提到:

  

此DLL包含一个类,例如ScoreKeeper,它实现了一个名为GetHighScore()的方法。应用程序会定期调用它。

然后:

  

有没有办法阻止.NET应用程序使用"未授权的"这里的DLL取代了我提供的那个?

假设您想要阻止某人更换您自己的程序集,该程序集具有相同的名称和类型(位于同一名称空间中),您可以 { {3}}包含ScoreKeeper类,让您的消费者引用该类。

但是,我们会发现有些问题导致这不是100%可靠。强名称可帮助您保护不知情的用户免受恶意欺骗副本替换您的DLL。但是如果用户是欺骗的同谋(如果他试图作弊就是这种情况),那么代码签名只不过是速度提升并且没有提供真正的保护。当然,强名称不能提供与例如强名称相媲美的保护。 PunkBuster的。

使用强名称验证程序集发布者的身份

向程序集添加强名称时,您正在使用私钥(非对称公钥/私钥对的一部分,稍后会详细介绍)生成加密哈希,并且公钥包含在程序集名称中(连同哈希)。

使用公共哈希和公钥,CLR能够验证程序集的签名确实来自私钥。

当然,这意味着,您应该保护密钥(内部和外部);如果其他人拥有你的密钥,那么他们就可以有效地冒充你并发布人们信任你的集会。

然后,当您添加对已签名程序集的引用时,如果有人尝试使用相同的程序集名称(不是完全限定的程序集,只是没有版本,哈希和公钥的名称)和相同类型的不同程序集名称,CLR填充失败时尝试加载类型,表明它无法找到它;使用完全限定的程序集名称以及名称空间和类型名称来解析类型。

为什么强名称不是100%安全(什么都可以?)

1)哈希碰撞

仍然是正在验证的哈希。虽然散列非常大(默认散列算法为SHA-1的160位),但任何具有有限数值的散列都会发生冲突。虽然不太可能,但 可能(不可能与不可能)。此外,默认情况下仅使用最后8个字节。结合表明SHA-1相对较弱的研究,这是使用apply a strong name to the assembly中描述的SHA-256增强强命名的一个很好的理由。

2)删除强名称

可以删除强名称​​ 。但是,在这种情况下,因为您的程序集是MSDN,当程序集尝试使用受损版本时,它会在运行时失败,假设您已正确重新启用验证(见下文)。

3)对程序集的物理访问意味着所有程序集

如果有人可以访问物理机并且可以修改您引用的程序集,那么您的程序集只是易受攻击。如果攻击者能够修改您引用的程序集的强名称,那么他们就可以轻松地修改您的程序集以及执行中涉及的所有其他人。为此,referencing the strong named version of the referenced assembly。当然,这会带来一系列不同的安全问题。

4)管理员禁用强名称检查

计算机管理员可以使用sn -Vr绕过强名称检查。根据{{​​3}}:

  

注册程序集以进行验证跳过...恶意程序集可以使用添加到跳过验证列表的程序集的完全指定的程序集名称(程序集名称,版本,区域性和公钥标记)来伪造其标识。这将允许恶意程序集也跳过验证。

5)必须在.NET 3.5 SP 1

之后明确启用强名称检查

从.NET 3.5 SP 1开始,the only way to be 100% sure that the physical assembly isn't hacked is to deny physical access through it

  

从.NET Framework 3.5版Service Pack 1(SP1)开始,当程序集加载到完全信任的AppDomain对象(例如MyComputer区域的默认AppDomain)时,不会验证强名称签名。

为了让.NET检查加载到应用程序中的每个程序集的强名称,您需要将以下代码段(由MSDN提供)插入到应用程序配置文件中:

<configuration>
  <runtime>
     <bypassTrustedAppStrongNames enabled="false" />
  </runtime>
</configuration>

但要注意,这只能防止删除强名称。

  

当您覆盖旁路功能时,强名称仅在正确性方面有效;没有检查StrongNameIdentityPermission。如果要确认特定的强名称,则必须单独执行该检查。


如果考虑到上述问题,您仍然希望强力命名您的大会,请按照以下方式进行。

生成强名称并签署程序集

生成强名称时,您有两个选项可供使用。在Visual Studio中,转到项目属性上的“签名”选项卡,然后单击“#34;签署程序集&#34;:

"Sign the assembly" option on the "Signing" tab of the project properties in VS.NET

从那里,你有两个选项来生成公钥/私钥,让VS.NET为你生成密钥,或指向现有密钥:

"New" or "Browse" options for choosing a strong name key file

选择&#34; New&#34;时,Visual Studio会提示您输入要生成的文件的名称,以及是否要选择使用密码来访问它:

Create strong name key dialog

此时,密钥将添加到您的项目中:

Key added to project

现在,您可以将其移至解决方案项目(如果您的解决方案中有多个项目)。

在这种情况下,Visual Studio实际上只是调用MSDN来生成公钥和私钥对。如果您自己这样做,则需要使用sn.exe命令行选项调用-k来生成密钥,如下所示:

sn -k keyPair.snk

然后通过&#34;浏览&#34;添加它。上面的对话。

请注意,执行此操作时,会将密钥拉入项目中。如果您不想这样做(因为它将密钥复制到每个项目中),然后从项目中删除密钥 ,然后simply having a strong name doesn't provide any protection 。这将清除&#34;选择强名称密钥文件&#34;选项,但如果您将其删除,您将看到链接密钥文件的完整路径。

答案 1 :(得分:3)

似乎最简单的答案是计算您正在加载的DLL的安全哈希值,然后将其与您预先计算的黄金值进行比较。当然,这仍然容易被一个足够坚定的攻击者打破,但它会显着提高想要作弊的人的标准。