C# 动态修改dll的签名 以及修改引用该dll文件的签名
在读取RedisSessionStateProvider配置 提到用mono ceil 来修改程序集以及它的签名,里面GetPublicKey 和GetPubliKeyToken 方法里面那个字符串的获取 以及后来的签名 我们都应该 用code来实现,还有应用该dll文件的签名也一同需要修改。
所以我这里实现了一个简单的helper方法 如下:
namespace ConsoleSession { using Mono.Cecil; using System; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; public class ChangeAssemblyInfo { public string FileName { set; get; } public string FullName { set; get; } } public class keyHelper { static byte[] GetNewKey(string keyFileName) { using (FileStream keyPairStream = File.OpenRead(keyFileName)) { return new StrongNameKeyPair(keyPairStream).PublicKey; } } public static void ReSign(string keyFileName, string assemblyFileName) { AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(assemblyFileName); asm.Name.PublicKey = GetNewKey(keyFileName); asm.Write(assemblyFileName); //用KEY文件建立密钥容器 byte[] pbKeyBlob = File.ReadAllBytes(keyFileName); string wszKeyContainer = Guid.NewGuid().ToString(); StrongNameKeyInstall(wszKeyContainer, pbKeyBlob, pbKeyBlob.Length); //使用新建的密钥容器对程序集经行签名 StrongNameSignatureGeneration(assemblyFileName, wszKeyContainer, IntPtr.Zero, 0, 0, 0); //删除新建的密钥容器 StrongNameKeyDelete(wszKeyContainer); } private static byte[] tryGetPublicKeyToken(string keyFileName) { try { byte[] newPublicKey; using (FileStream keyPairStream = File.OpenRead(keyFileName)) { newPublicKey = new StrongNameKeyPair(keyPairStream).PublicKey; } int pcbStrongNameToken; IntPtr ppbStrongNameToken; StrongNameTokenFromPublicKey(newPublicKey, newPublicKey.Length, out ppbStrongNameToken, out pcbStrongNameToken); var token = new byte[pcbStrongNameToken]; Marshal.Copy(ppbStrongNameToken, token, 0, pcbStrongNameToken); StrongNameFreeBuffer(ppbStrongNameToken); return token; } catch (Exception) { return null; } } public static void ReLink(string keyFileName, ChangeAssemblyInfo[] assemblyInfoList) { byte[] publicKeyToken = tryGetPublicKeyToken(keyFileName); if (publicKeyToken == null) { return; } //获得每个程序集的名称 foreach (ChangeAssemblyInfo assemblyInfo in assemblyInfoList) { assemblyInfo.FullName = AssemblyDefinition.ReadAssembly(assemblyInfo.FileName).Name.FullName; } //检查是否被引用,是的话,就替换PublicKeyToken foreach (ChangeAssemblyInfo assemblyInfo in assemblyInfoList) { AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(assemblyInfo.FileName); foreach (ModuleDefinition module in assembly.Modules) foreach (AssemblyNameReference reference in module.AssemblyReferences) if (assemblyInfoList.Any(a => a.FullName == reference.FullName)) { reference.PublicKeyToken = publicKeyToken; assembly.Write(assemblyInfo.FileName); } } } #region StrongName库作为一项资源包含在 MsCorEE.dll 中,其一系列API包含有 [DllImport("mscoree.dll", EntryPoint = "StrongNameKeyDelete", CharSet = CharSet.Auto)] static extern bool StrongNameKeyDelete(string wszKeyContainer); [DllImport("mscoree.dll", EntryPoint = "StrongNameKeyInstall", CharSet = CharSet.Auto)] static extern bool StrongNameKeyInstall([MarshalAs(UnmanagedType.LPWStr)] string wszKeyContainer, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2, SizeConst = 0)] byte[] pbKeyBlob, int arg0); [DllImport("mscoree.dll", EntryPoint = "StrongNameSignatureGeneration", CharSet = CharSet.Auto)] static extern bool StrongNameSignatureGeneration(string wszFilePath, string wszKeyContainer, IntPtr pbKeyBlob, int cbKeyBlob, int ppbSignatureBlob, int pcbSignatureBlob); [DllImport("mscoree.dll", EntryPoint = "StrongNameErrorInfo", CharSet = CharSet.Auto)] static extern uint StrongNameErrorInfo(); [DllImport("mscoree.dll", EntryPoint = "StrongNameTokenFromPublicKey", CharSet = CharSet.Auto)] static extern bool StrongNameTokenFromPublicKey(byte[] pbPublicKeyBlob, int cbPublicKeyBlob, out IntPtr ppbStrongNameToken, out int pcbStrongNameToken); [DllImport("mscoree.dll", EntryPoint = "StrongNameFreeBuffer", CharSet = CharSet.Auto)] static extern void StrongNameFreeBuffer(IntPtr pbMemory); #endregion } }
调用code 如下:
using System; using System.IO; using System.Linq; using Mono.Cecil; class Program { static void Main(string[] args) { #region 修改程序集 string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Microsoft.Web.RedisSessionStateProvider3.dll"); AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(filePath); TypeDefinition[] types = asm.MainModule.Types.ToArray(); //修改ProviderConfiguration为public TypeDefinition typeConfiguration = types.FirstOrDefault(x => x.Name == "ProviderConfiguration"); typeConfiguration.IsPublic = true; //修改ProviderConfiguration的字段为public TypeDefinition typeRedisProvide = types.FirstOrDefault(x => x.Name == "RedisSessionStateProvider"); FieldDefinition filedConfiguration = typeRedisProvide.Fields.ToArray().FirstOrDefault(x => x.Name == "configuration"); filedConfiguration.IsPublic = true; //保存dll文件 filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Microsoft.Web.RedisSessionStateProvider.dll"); asm.Write(filePath); #endregion string keyfileName = @"D:\mykey.snk"; //修改单个dll文件的签名 keyHelper.ReSign(keyfileName,filePath); //修改引用该dll文件的签名 keyHelper.ReLink(keyfileName, new ChangeAssemblyInfo[] { new ChangeAssemblyInfo { FileName = filePath } ,new ChangeAssemblyInfo { FileName=Path.Combine(@"C:\Users\UNIT12\Documents\visual studio 2015\Projects\SessionWebApp\SessionWebApp\bin","SessionWebApp.dll")} }); //Console.ReadLine(); } }
参考资料:
利用Mono-cecil实现.NET程序的重新签名,重新链接相关库的引用
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Python网络编程(epoll内核监听,多任务多进程)
OJBK 接着昨天的说 select模块内的epoll函数还没说 说完epoll和本地套接字套接字基本就没了 今天主要是多进程 理论性东西比较多 主要是理解 epoll 使用方法:代码与poll基本一致(Python语言中) 将生产的对象改为 epoll = epoll() 将关注事件类别名改为epoll的关注事件类别 epoll基本所有的方法和常量都一致 再原poll的常量名前加个E 创建方法改为 epoll()就可以了 这种情况只在Python中才会这么简单 epoll在别的语言实现比python要复杂的多 区别: epoll 效率要高于select 和 poll epoll 的触发机制更多 EPOLLET(边缘触发) 边缘触发是什么? 这就是epoll和poll的区别所在了 为什么说epoll效率会高呢 因为epoll的触发机制是在内核中直接完成整个功能 那个事件准备就绪我就直接返回这个IO事件 而poll的触发方式是什么呢 是我什么时候有IO准备就绪了我就...
- 下一篇
C#多线程编程系列(一)- 简介
原文: C#多线程编程系列(一)- 简介 目录 系列大纲 一、前言 二、目录结构 四、章节结构 五、相关链接 系列大纲 目前只整理到第二章,线程同步,笔者后面会慢慢更新,争取能把这本书中精华的知识都分享出来。C#多线程编程系列(一)- 简介C#多线程编程系列(二)- 线程基础C#多线程编程系列(三)- 线程同步C#多线程编程系列(四)- 使用线程池C#多线程编程系列(五)- 使用任务并行库 源码下载点击链接 示例源码下载 一、前言 在C#学习过程中,多线程一直都是比较难的部分,因为其中涉及到很多与操作系统相关的知识。比如:如何进行多线程编程、线程同步、线程锁、线程异步、并行编程、并行集合等等的知识。所以笔者在学习过程中也是遇到了重重困难,而且一直没有好的教程。 但是笔者在浏览GitHub时,发现有大佬已经推荐了一本新书,《MULTITHREADING WITH C# COOKBOOK SECOND EDITION》,其中主要就是讲如何在C#中使用多线程的。看到这本书笔者是如获珍宝,终于能有机会系统的学习多线程相关的知识了。 于是便有了这一个开篇,这个更多的是阅读这本书的笔记和一些按照书...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Redis,开启缓存,提高访问速度
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Hadoop3单机部署,实现最简伪集群
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果