我正在尝试篡改程序集,以便能够模拟无法轻易模拟的代码such as SharePoint assemblies。
作为一个原型,我有一个解决方案,通过ILRepack和Mono.Cecil的自定义构建操作来修改测试代码,以便实际代码不是最初编写的代码。
当包含测试代码的程序集未签名时,一切正常。当程序集签名时,我看到了预期的错误:
找到的程序集的清单定义与程序集引用不匹配。
由于组件被篡改,显然,密钥要么不相同(如果在篡改后签名),要么不存在。
我认为通过AppDomain.CurrentDomain.AssemblyResolve
事件可以允许强制接受篡改的程序集,但事实并非如此。
如何让.NET Framework在完全信任的单元测试中忽略程序集匹配检查,并在希望签名时接受未签名的程序集?
据我了解,问题不在于强名称验证。不仅错误会有所不同,而且running the corresponding sn –Vr
也没有效果:错误仍然存在。
实际问题似乎是在装配绑定级别。这也是为什么我很惊讶地看到AppDomain.CurrentDomain.AssemblyResolve
事件被提出,但其结果仍被忽略;可能,它并没有像我一直认为的那样做。
答案 0 :(得分:0)
我认为解决方案要容易得多。因为,正如我猜测的那样,问题不是强名称验证,而是依赖于公钥令牌的程序集绑定,可以在篡改程序集时替换令牌。
第一步是在篡改之前获取原始公钥和公钥令牌。它们都在AssemblyName
内。
var originalAssemblyBytes = File.ReadAllBytes(originalFilePath);
var originalAssemblyName = Assembly.Load(originalAssemblyBytes).GetName();
下一步是篡改本身:首先使用ILRepack合并两个程序集,然后使用Mono.Cecil进行更细粒度的更改。在第二步中,Mono.Cecil用于替换公钥和公钥令牌:
var assemblyName = mergedModule.Assembly.Name;
assemblyName.HasPublicKey = true;
assemblyName.PublicKey = originalAssemblyName.GetPublicKey();
assemblyName.PublicKeyToken = originalAssemblyName.GetPublicKeyToken();
必须更改两者:如果只更改了令牌,则在使用程序集时会立即抛出错误“无效的程序集公钥”。
这适用于使用.snk和.pfx签名的程序集:由于测试以完全信任的方式运行,因此验证未完成,这意味着公钥与私钥不对应的事实是不相关的。