如果你想去除一个程序集的强签名(strong name),目前为止可以有两个途径

1  反编译为IL代码,删除签名部分,再编译为程序集

2  应用Re-Sign程序,直接对一个程序集再签名

生成和读取强命名

先来看,如何生成.NET的签名文件,调用命令SN传入参数。

下面的代码读取该文件,

  1. FileStream keyPairFile = File.OpenRead(“key.sn”);
  2. this.byte_2 = new StrongNameKeyPair(keyPairFile).PublicKey;
  3. keyPairFile.Close();

再深究一下,BCL中原来还有一个StrongNameKeyPair的类型,它的构造方法如下

  1. [SecuritySafeCritical, SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
  2. public StrongNameKeyPair(FileStream keyPairFile)
  3. {
  4. if (keyPairFile == null)
  5. {
  6. throw new ArgumentNullException("keyPairFile");
  7. }
  8. int length = (int) keyPairFile.Length;
  9. this._keyPairArray = new byte[length];
  10. keyPairFile.Read(this._keyPairArray, 0, length);
  11. this._keyPairExported = true;
  12. }

这个类型中的方法,用调用BCL的内部帮助函数StrongNameHelpers

  1. namespace Microsoft.Runtime.Hosting
  2. {
  3. [ComImport, SecurityCritical, Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D"), ComConversionLoss, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  4. internal interface IClrStrongName
  5.  
  6. [ComImport, Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D"), SecurityCritical, ComConversionLoss, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  7. internal interface IClrStrongNameUsingIntPtr
  8.  
  9. internal static class StrongNameHelpers
  10. }
  1.  

.NET 框架对Strong Name的支持

关于strong name的创建,生成与验证,可以参考StrongNameHelpers的源代码。

为了完成这个任务,先参考几个不常见的BLC中的API

  1. [DllImport("mscoree.dll", CharSet=CharSet.Auto)]
  2. private static extern bool StrongNameKeyInstall([MarshalAs(UnmanagedType.LPWStr)] string wszKeyContainer, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] byte[] pbKeyBlob, int int_1);

向容器中导入一个公钥/私钥对, 如果成功完成,则为 true;否则为 false。

  1. [DllImport("mscoree.dll", CharSet=CharSet.Auto)]
  2. private static extern bool StrongNameKeyDelete(string string_3);

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

删除指定的密钥容器。如果成功完成,则为 true;否则为 false。

  1. [DllImport("mscoree.dll", CharSet=CharSet.Auto)]
  2. 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。

  1. [DllImport("mscoree.dll", CharSet=CharSet.Auto)]
  2. 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 位哈希。该标记是程序集的强名称的一部分,并且可以从程序集元数据中读取。

  1. [DllImport("mscoree.dll", CharSet=CharSet.Auto)]
  2. private static extern void StrongNameFreeBuffer(IntPtr intptr_0);

释放上一次调用强名称函数(如 StrongNameGetPublicKey、StrongNameTokenFromPublicKey 或 StrongNameSignatureGeneration)时分配的内存。

  1. [DllImport("mscoree.dll", CharSet=CharSet.Auto)]
  2. private static extern uint StrongNameErrorInfo();

获取由某个强名称函数引发的上一个错误代码。由某一个强名称函数设置的上一个 COM 错误代码。

大部分强名称方法返回简单的 true 或 false 以指示是否成功完成。使用 StrongNameErrorInfo 函数检索指定由强名称函数生成的上一个错误的 HRESULT。

程序中的代码流程分析

先用代码读取一个程序集的strong name

  1. this.byte_1 = AssemblyName.GetAssemblyName("Test.dll").GetPublicKey();

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

再把整个程序集读取内存中

  1. using (FileStream stream2 = File.OpenRead(“Test.dll"))
  2. {
  3. this.byte_3 = new byte[stream2.Length];
  4. stream2.Read(this.byte_3, 0, (int) stream2.Length);
  5. }

下面的代码获取已经签名的程序集的签名信息

  1. int num;
  2. int num2;
  3. StrongNameTokenFromAssemblyEx(string_3, ref ptr2, out num2, ref zero, out num);
  4. byte[] destination = new byte[num2];
  5. Marshal.Copy(ptr2, destination, 0, num2);

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

读取签名文件的长度,它将是要写入到程序集中的签名

  1. FileStream input = new FileStream(“sn.key”, FileMode.OpenOrCreate, FileAccess.Read);
  2. BinaryReader reader = new BinaryReader(input);
  3. byte[] buffer2 = new byte[(int) reader.BaseStream.Length];
  4. reader.BaseStream.Seek(0L, SeekOrigin.Begin);
  5. reader.Read(buffer2, 0, (int) reader.BaseStream.Length);
  6. int length = (int) reader.BaseStream.Length;
  7. reader.Close();
  8. input.Close();
  1.  

最后调用方法,添加和生成签名

  1. StrongNameKeyInstall("Test.dll", buffer, length))
  2. StrongNameSignatureGeneration("Test.dll", snKey, 0, 0, 0, 0))

因为这几个方法的调用不会抛出异常,所以要用Win32式的GetLastError函数一样,使用StrongNameErrorInfo()方法来截获错误,

整个过程几乎就是对BCL的API调用,全部代码在百行以内。我在想,Visual Studio内置的给程序集签名的方式,也应该与此有相似之处,毕竟核心的API都已经被

微软封装进BCL类库,只需要调用即可。

这个工具来源于一家专门研究逆向工程的研究小组,你可以通过下面的网址找到他们发布的研究成果。

http://www.reteam.org/index.html

  1.  
  1.  

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

  1.  

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.NET程序集强命名删除与再签名技术 源代码剖析的更多相关文章

  1. .net程序集强命名(签名)

    要想得到强签名的dll有两种情况: 1.给项目添加强命名 在你的项目右键->属性->签名,勾选“为程序集签名”,新建 或 浏览已经新建过的.pfx文件,然后重新build项目,生成的dll ...

  2. .NET中查看一个强命名程序集(*****.dll)的PublicKeyToken的方法

    使用命令行工具SDK Command Prompt,键入:SN -T C:\*****.dll  (dll文件所在的路径) 就会显示出该dll具体的PublicKeyToken数值. 如果该程序集没有 ...

  3. C#程序集使用强名字(Strong Name)签名/强名称签名

    强名称签名的方法: 强签名: 1. 可以将强签名的dll注册到GAC,不同的应用程序可以共享同一dll. 2. 强签名的库,或者应用程序只能引用强签名的dll,不能引用未强签名的dll,但是未强签名的 ...

  4. [.NET] - Enhanced Strong Naming (加强版的强签名程序集) – 如何迁移原有的强命名程序集

    依据文档: https://msdn.microsoft.com/en-us/library/hh415055(v=vs.110).aspx 虽然文档上给出了看似完整的步骤,但是如果按照上面的步骤,结 ...

  5. CLR 关于强命名程序集 .

    如何创建强命名程序集(Strong Name Assembly)     创建一个强命名程序集首先需要获得一个用强命名实用工具   (Strong Name Utility,即SN.exe,.NET  ...

  6. C# 强命名程序集,防止dll被修改,混淆下发布

    未能加载文件或程序集“Jonckers.Service.RedisCacheEngineExtend, Version=1.0.0.0, Culture=neutral, PublicKeyToken ...

  7. 第一部分 CLR基础:第3章 共享程序集和强命名程序集

    第一部分 CLR基础:第3章 共享程序集和强命名程序集

  8. 只有ReflectionOnlyLoadFrom才可以拯救与GAC冲突的强命名程序集

    先说结论,如果有两个拥有相同程序集名称的强命名程序集,一个在GAC里,一个不在.怎样动态加载那个不在GAC里的程序集?答案就是只有Assembly.ReflectionOnlyLoadFrom才可以加 ...

  9. membership DB生成 & dll 强命名 & 证书生成

    UPD(Membership)数据库安装1.使用 Aspnet_regsql.exe 安装数据库 在 C:\WINDOWS\Microsoft.NET\Framework\\aspnet_regsql ...

随机推荐

  1. node开发

    1. 国内使用npm安装某些插件的时候,偶尔会有网络问题,可以使用cnpm:(后续所有使用 npm 无法正常安装的,都改成 cnpm 试试) a. 首先使用 npm 安装 cnpm:npm insta ...

  2. Windows Phone 8.1 新特性 - 控件之FlipView

    本篇为大家介绍 Windows Phone 8.1 中新增的 FlipView 控件,它的中文名字叫做:翻转视图. 虽然听起来有点拗口,但是它的用途大家一定不会陌生.在 Windows Phone 8 ...

  3. Java学习日记之 Java-IO流

    Java中的IO流在处理上分为字节流和字符流.字节流和字符流的区别 : 1.字节流读取的时候,读到一个字节就返回一个字节:  字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8 ...

  4. ArcGIS百米网格自动生成

    最近需要用百米网格进行空间叠加分析,首先得自动生成百米网格数据.经过查找,发现ARCgis可以自动生成网格.方法如下 2.创建格网(Creat Fishnet).需要用到ArcGIS的ArcToolb ...

  5. [Leetcode]Palindrome Number

    Determine whether an integer is a palindrome. Do this without extra space. 这题貌似解法挺多,直接用简单的把数倒置,没有考虑数 ...

  6. SAP DataServices企业定制培训

    No. Item Remark 1 Dataservices overview DS概述 2 SAP Dataservices 安装与配置 DS的配置 3 DS ETL开发<1> for ...

  7. (转载)JAVA敏捷开发环境搭建

    整个软件项目分为四个环境 开发本地环境.开发环境.测试环境.IDC环境.和传统C++开发不一样的模式是多了第一个开发本地环境.这是为什么呢,因为目前大部分开发人员还是比较熟悉windows下开发.对于 ...

  8. SSIS oracle 64位 数据源链接

    新建数据源 提供程序选择:本机OLE DB ORACLE Provider For OLE DB 服务器名或文件名中选择Oracle Net Manager中配置好的服务名即可 填写账号,密码,测试, ...

  9. CSS 禁止浏览器滚动条的方法(转)

    1.完全隐藏 在<boby>里加入scroll="no",可隐藏滚动条: <boby scroll="no"> 这个我用的时候完全没效果 ...

  10. SQLServer 获取第几周开始日期

    不多说直接上code DECLARE @CurrDay DATETIME=GETDATE() --SET @CurrDay=CAST(('2013-01-10')AS DATETIME) --SET ...