如何防止.NET中的DLL欺骗

jgl*_*uie 24 .net c#

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

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

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

cas*_*One 49

你提到:

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

然后:

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

假设您想要阻止某人更换您自己的程序集,该程序集具有相同的名称和类型(在同一名称空间中),您可以 将强名称应用于包含ScoreKeeper该类的程序集并让您的消费者参考.

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

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

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

使用公共哈希和公钥,CLR能够验证程序集的签名实际上是否来自私钥.

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

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

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

1)哈希碰撞

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

2)删除强名称

强名称可以删除.但是,在这种情况下,因为您的程序集引用了引用程序集的强命名版本,所以当程序集尝试使用受损版本时,它将在运行时失败,假设您已正确地重新启用验证(请参阅下文).

3)对组件的物理访问意味着所有组件

如果有人可以访问物理机并且可以修改您引用的程序集,那么您的程序集就像容易受到攻击一样.如果攻击者能够修改您引用的程序集的强名称,那么他们就可以轻松地修改程序集以及执行中涉及的所有其他程序.为此,100%确定物理组件未被黑客攻击的唯一方法是拒绝通过它进行物理访问.当然,这带来了一系列不同的安全问题.

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

计算机管理员可以使用简单地绕过强名称检查sn -Vr.根据MSDN:

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

5)必须在.NET 3.5 SP 1之后明确启用强名称检查

从.NET 3.5 SP 1开始,只有一个强名称不提供任何保护:

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

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

<configuration>
  <runtime>
     <bypassTrustedAppStrongNames enabled="false" />
  </runtime>
</configuration>
Run Code Online (Sandbox Code Playgroud)

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

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


如果考虑到上述问题,你仍然希望强力命名你的装配,这就是方法.

生成强名称并签署程序集

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

在VS.NET中项目属性的

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

用于选择强名称密钥文件的

选择"新建"时,Visual Studio将提示您输入要生成的文件的名称,以及是否要选择使用密码来访问它:

创建强名称密钥对话框

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

密钥添加到项目中

现在,您可以将其移动到解决方案项目(如果解决方案中有多个项目).

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

sn -k keyPair.snk
Run Code Online (Sandbox Code Playgroud)

然后通过上面的"浏览"对话框添加它.

请注意,执行此操作时,它会将密钥拉入项目中.如果您不想这样做(因为它将密钥复制到每个项目中),则从项目中删除密钥,然后将现有文件添加到项目中,但链接.这将清除"选择强名称密钥文件"选项,但如果将其删除,您将看到链接密钥文件的完整路径.