如果你想去除一個程序集的強簽名(strong name),目前為止可以有兩個途徑
1 反編譯為IL代碼,刪除簽名部分,再編譯為程序集
2 應用Re-Sign程序,直接對一個程序集再簽名
生成和讀取強命名
先來看,如何生成.NET的簽名文件,調用命令SN傳入參數。
下面的代碼讀取該文件,
FileStream keyPairFile = File.OpenRead(“key.sn”); this.byte_2 = new StrongNameKeyPair(keyPairFile).PublicKey; keyPairFile.Close();
再深究一下,BCL中原來還有一個StrongNameKeyPair的類型,它的構造方法如下
[SecuritySafeCritical, SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] public StrongNameKeyPair(FileStream keyPairFile) { if (keyPairFile == null) { throw new ArgumentNullException("keyPairFile"); } int length = (int) keyPairFile.Length; this._keyPairArray = new byte[length]; keyPairFile.Read(this._keyPairArray, 0, length); this._keyPairExported = true; }
這個類型中的方法,用調用BCL的內部幫助函數StrongNameHelpers
namespace Microsoft.Runtime.Hosting { [ComImport, SecurityCritical, Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D"), ComConversionLoss, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IClrStrongName [ComImport, Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D"), SecurityCritical, ComConversionLoss, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface IClrStrongNameUsingIntPtr internal static class StrongNameHelpers }
.NET 框架對Strong Name的支持
關於strong name的創建,生成與驗證,可以參考StrongNameHelpers的源代碼。
為了完成這個任務,先參考幾個不常見的BLC中的API
[DllImport("mscoree.dll", CharSet=CharSet.Auto)] private static extern bool StrongNameKeyInstall([MarshalAs(UnmanagedType.LPWStr)] string wszKeyContainer, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] byte[] pbKeyBlob, int int_1);
向容器中導入一個公鑰/私鑰對, 如果成功完成,則為 true;否則為 false。
[DllImport("mscoree.dll", CharSet=CharSet.Auto)] private static extern bool StrongNameKeyDelete(string string_3);
刪除指定的密鑰容器。如果成功完成,則為 true;否則為 false。
[DllImport("mscoree.dll", CharSet=CharSet.Auto)] private static extern bool StrongNameSignatureGeneration(string string_3, string string_4, int int_1, int int_2, int int_3, int int_4);
生成指定程序集的強名稱簽名。如果成功完成,則為 true;否則為 false。
[DllImport("mscoree.dll", CharSet=CharSet.Auto)] private static extern bool StrongNameTokenFromAssemblyEx([MarshalAs(UnmanagedType.LPWStr)] string wszFilePath, ref IntPtr intptr_0, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken, ref IntPtr intptr_1, [MarshalAs(UnmanagedType.U4)] out int pcbPublicKeyBlob);
從指定的程序集文件創建強名稱標記,並返回標記代表的公鑰。強名稱標記是公鑰的縮寫形式。該標記是依據用於對程序集進行簽名的公鑰創建的 64 位哈希。該標記是程序集的強名稱的一部分,並且可以從程序集元數據中讀取。
[DllImport("mscoree.dll", CharSet=CharSet.Auto)] private static extern void StrongNameFreeBuffer(IntPtr intptr_0);
釋放上一次調用強名稱函數(如 StrongNameGetPublicKey、StrongNameTokenFromPublicKey 或 StrongNameSignatureGeneration)時分配的內存。
[DllImport("mscoree.dll", CharSet=CharSet.Auto)] private static extern uint StrongNameErrorInfo();
獲取由某個強名稱函數引發的上一個錯誤代碼。由某一個強名稱函數設置的上一個 COM 錯誤代碼。
大部分強名稱方法返回簡單的 true 或 false 以指示是否成功完成。使用 StrongNameErrorInfo 函數檢索指定由強名稱函數生成的上一個錯誤的 HRESULT。
程序中的代碼流程分析
先用代碼讀取一個程序集的strong name
this.byte_1 = AssemblyName.GetAssemblyName("Test.dll").GetPublicKey();
再把整個程序集讀取內存中
using (FileStream stream2 = File.OpenRead(“Test.dll")) { this.byte_3 = new byte[stream2.Length]; stream2.Read(this.byte_3, 0, (int) stream2.Length); }
下面的代碼獲取已經簽名的程序集的簽名信息
int num; int num2; StrongNameTokenFromAssemblyEx(string_3, ref ptr2, out num2, ref zero, out num); byte[] destination = new byte[num2]; Marshal.Copy(ptr2, destination, 0, num2);
讀取簽名文件的長度,它將是要寫入到程序集中的簽名
FileStream input = new FileStream(“sn.key”, FileMode.OpenOrCreate, FileAccess.Read); BinaryReader reader = new BinaryReader(input); byte[] buffer2 = new byte[(int) reader.BaseStream.Length]; reader.BaseStream.Seek(0L, SeekOrigin.Begin); reader.Read(buffer2, 0, (int) reader.BaseStream.Length); int length = (int) reader.BaseStream.Length; reader.Close(); input.Close();
最后調用方法,添加和生成簽名
StrongNameKeyInstall("Test.dll", buffer, length)) StrongNameSignatureGeneration("Test.dll", snKey, 0, 0, 0, 0))
因為這幾個方法的調用不會拋出異常,所以要用Win32式的GetLastError函數一樣,使用StrongNameErrorInfo()方法來截獲錯誤,
整個過程幾乎就是對BCL的API調用,全部代碼在百行以內。我在想,Visual Studio內置的給程序集簽名的方式,也應該與此有相似之處,畢竟核心的API都已經被
微軟封裝進BCL類庫,只需要調用即可。
這個工具來源於一家專門研究逆向工程的研究小組,你可以通過下面的網址找到他們發布的研究成果。
http://www.reteam.org/index.html