2015-08-09 46 views
1

我正在嘗試篡改組件,以便能夠模擬不容易被嘲笑的代碼,such as SharePoint assemblies如何忽略單元測試中的程序集引用不匹配?

作爲一個原型,我有一個解決方案,通過ILRepack和Mono.Cecil的自定義構建動作來篡改測試代碼,以便實際代碼不是原來編寫的代碼。

當包含測試代碼的程序集未簽名時,一切正常。當組件簽字,我看到好預期的錯誤:

The located assembly's manifest definition does not match the assembly reference.

由於裝配被篡改,顯然,密鑰是不一樣的(如果被篡改後簽署),或不存在。

我認爲通過AppDomain.CurrentDomain.AssemblyResolve事件可能允許強制篡改的程序集被接受,但事實並非如此。

如何在完全信任的單元測試期間,如何讓.NET Framework忽略對程序集匹配的檢查,並在接受未簽名的程序集時接受它們?


據我所知,問題不在於強名稱驗證。不僅錯誤會有所不同,而且running the corresponding sn –Vr也不起作用:錯誤仍然存​​在。

實際問題似乎是在程序集綁定級別。這也是爲什麼我驚訝地看到AppDomain.CurrentDomain.AssemblyResolve事件被提出,但其結果仍然被忽略;可能,它不會做我一直認爲它做的事。

+0

我不確定自己是否正確理解,但這聽起來像是在試圖擊敗您編寫的安全代碼。即如果你知道如何通過單元測試來勝過你的代碼,那麼這並不意味着黑客可以使用相同的方法來打敗你的生產防禦。 –

+0

@PaulSasik:正好。在生產中,黑客確實可以使用相同的技術,但它適用於以完全信任方式運行的代碼。除此之外,我希望單元測試的具體環境也可能有所幫助:例如,在執行代碼覆蓋或分析時使用的機制不同; –

+0

http:// stackoverflow。com/a/3268952似乎提到了能夠使用'sn -T '的地方,其中'fullname'是'Assembly = MyAssembly.dll,公鑰標記= '。也許你可以在修改程序集後設置它? – Eris

回答

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簽名的程序集:既然測試是以完全信任的方式運行,驗證沒有完成,這意味着公鑰與私鑰不對應的事實是不相關的。

相關問題