.NET程序集強命名刪除與再簽名技術 源代碼剖析


如果你想去除一個程序集的強簽名(strong name),目前為止可以有兩個途徑

1  反編譯為IL代碼,刪除簽名部分,再編譯為程序集

2  應用Re-Sign程序,直接對一個程序集再簽名

image

 

生成和讀取強命名

先來看,如何生成.NET的簽名文件,調用命令SN傳入參數。

image

下面的代碼讀取該文件,

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

 

 
 
         
        
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM