C# 动态修改dll的签名 以及修改引用该dll文件的签名

原文: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程序的重新签名,重新链接相关库的引用

原文地址:https://www.cnblogs.com/lonelyxmas/p/9452916.html

时间: 2024-10-24 02:45:36

C# 动态修改dll的签名 以及修改引用该dll文件的签名的相关文章

动态映射objective-c的对象方法修改空指针

背景:目前iOS工程较多将json数据转换成一个对象来储存.假设这个对象有一个Attributes为NSString类型叫myName,这个Attributes一直是nil,创建这对象后忘记对它赋值.现在要通过一个函数来检测他出来,再将他赋值为@"": 另外,我不知道有多少个Attributes,只要是NSString类型而且Attributes是nil就赋值为@"". 代码如下: // //  GMCommonHelper.h #import <Founda

通过修改EIP寄存器实现32位程序的DLL注入

功能:通过修改EIP寄存器实现32位程序的DLL注入 <如果是64位 记得自己对应修改汇编代码部分> 原理:挂起目标进程,停止目标进程EIP的变换,在目标进程开启空间,然后把相关的指令机器码和数据拷贝到里面去,然后修改目标进程EIP使其强行跳转到我们拷贝进去的相关机器码位置,执行相关,然后跳转回来.下面的例子是实现DLL注入,但是和平时说的远程代码注入在注入的逻辑上不同,但是同时都是用到了一个重要的结论就是:很多系统dll的导出函数地址在不同进程中,是一样的. 思路 : 修改EID实现代码注入

[00030]-[2015-09-26]-[00]-[DLL注入应用案例---修改任务管理器的实现]

案例需求: 学习了DLL注入的基础知识,需要通过一个简单的应用案例,来真正的实现DLL注入(注:为什么提倡使用DLL来实现远程进程的控制呢?因为DLL文件的编写相对规范和比较容易 操作,相对于纯粹的代码注入,因为纯粹的代码注入,需要考虑远程代码内存空间和本地进程 内存空间,这两个如果不好好思忖,就很容易出现,内存访问错误):本案例实现在任务管理 器上ListView添加两列显示: 实现策略:[1]需要spy++工具来获取 任务对话框的标题以获取应用程序的句柄 获取任务管理器指定控 件的ID,以获

Android逆向之旅---应用的&quot;反调试&quot;方案解析(附加修改IDA调试端口和修改内核信息)

一.前言 在前一篇文章中详细介绍了Android现阶段可以采用的几种反调试方案策略,我们在破解逆向应用的时候,一般现在第一步都回去解决反调试,不然后续步骤无法进行,当然如果你是静态分析的话获取就没必要了.但是有时候必须要借助动态调试方可破解,就需要进行操作了.现阶段反调试策略主要包括以下几种方式: 第一.自己附加进程,先占坑,ptrace(PTRACE_TRACEME, 0, 0, 0)!第二.签名校验不可或缺的一个选择,本地校验和服务端校验双管齐下!第三.借助系统api判断应用调试状态和调试属

Linux Tomcat安装,Linux配置Tomcat,Linux Tomcat修改内存,Linux tomcat修改端口

Linux Tomcat安装,Linux配置Tomcat,Linux Tomcat修改内存,Linux tomcat修改端口 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ?Copyright 蕃薯耀 2017年3月1日 http://www.cnblogs.com/fanshuyao/ JDK安

如何防止网卡名被修改和还原已被修改的网卡名

防止网卡名被修改的方法: 1.  修改/etc/grub.conf,添加biosdevname=0.修改之后,执行reboot,设备重启之后会生成/etc/udev/rules.d/70-persistent-net.rules文件. # grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE: You have a

整理 PHPstorm实用个人配置,修改调整个性化快捷键,修改使用phpstorm创建的模板的默认注释:

对你有助请点赞,请顶------送人玫瑰,手留余香! 1:58 2016/3/12 整理PHPstorm实用个人配置,修改调整个性化快捷键,修改使用phpstorm创建的模板的默认注释: PHPstorm配置:修改使用phpstorm创建的模板的默认注释 注意:我的也是phpstorm 10,但是配置的位置与下面参见的文章中描述的有所不同: 位置: 主要在一下两个路径: File | Settings | Appearance & Behavior | Appearance File | Set

VBS自编写脚本。(实现批量修改文件名且在执行前,备份原有文件夹中的文件)

'=========================================================================='' VBScript Source File -- Created with SAPIEN Technologies PrimalScript 4.0'' NAME: '' AUTHOR: Microsoft , Microsoft' DATE : 2014/7/9'' COMMENT: '批量修改文件夹下对应的所有文件名''==========

Ubuntu14.04 如何修改/etc/sudoers 和错误修改权限的解决办法

开始学习hadoop啦!!! 在Ubuntu14.04上新建了一个名为hadoop的用户,但总是遇到各种权限问题,于是就想干脆把这个账户变成root账户. 网上查到说是直接修改/etc/sudoers,修改时提示read-only,修改不了,自然而然想到去修改文件的权限, sudo chown u+w /etc/sudoers,修改好了后发现sudo su要报错. 解决的办法是进入到Ubuntu的recovery mode中的root shell进行修改,遇到了和http://www.cnblo