.net(C#)类库(dll) 动态修改(不改变签名) Mono.Cecil 依赖注入代码

描述

对C#的类库可以动态编辑,并在保证不更改类库签名的情况下输出dll文件

操作类如下

using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace ModifyAssemblyDemo
{
    internal class ILA
    {
        AssemblyDefinition currentASM;
        TypeDefinition currentType;
        MethodDefinition currentMethod;
        ILProcessor ilPro;
        Instruction currentIns;

        public AssemblyDefinition CurrentASM { get => currentASM; set => currentASM = value; }
        public TypeDefinition CurrentType { get => currentType; set => currentType = value; }
        public MethodDefinition CurrentMethod { get => currentMethod; set => currentMethod = value; }
        public ILProcessor IlPro { get => ilPro; set => ilPro = value; }
        public Instruction CurrentIns { get => currentIns; set => currentIns = value; }

       static List<AssemblyDefinition> assemblies = new List<AssemblyDefinition>();

        private class CustomResolver : BaseAssemblyResolver
        {
            private DefaultAssemblyResolver _defaultResolver;

            public CustomResolver()
            {
                _defaultResolver = new DefaultAssemblyResolver();
            }

            public override AssemblyDefinition Resolve(AssemblyNameReference name)
            {
                AssemblyDefinition assembly;
                try
                {
                    assembly = _defaultResolver.Resolve(name);
                }
                catch (AssemblyResolutionException ex)
                {
                    assembly = assemblies.FirstOrDefault(u=>u.FullName.Equals(name.FullName));
                }
                return assembly;
            }
        }

        public ILA(string path)
        {
            
            if (File.Exists(path))
            {
                currentASM = AssemblyDefinition.ReadAssembly(path,new ReaderParameters() { AssemblyResolver=new CustomResolver() });

                string[] files = Directory.GetFiles(Path.GetDirectoryName(path));
                //Task.Run(() =>
                //{

                //});
                for (int i = 0; i < files.Length; i++)
                {
                    try
                    {
                        var f = files[i];
                        var ex = Path.GetExtension(f);
                        if (!string.IsNullOrWhiteSpace(ex) && (ex.ToLower().Equals(".exe") || ex.ToLower().Equals(".dll")))
                            assemblies.Add(AssemblyDefinition.ReadAssembly(files[i]));
                    }
                    catch (Exception exception)
                    {
                    }
                }


            }
        }

        public ILA FM(Func<TypeDefinition, bool> typeWhere, Func<MethodDefinition, bool> methodType)
        {
            if (currentASM != null)
            {
                currentType = currentASM.MainModule.Types.First(typeWhere);
                if (currentType != null)
                {
                    currentMethod = currentType.GetMethods().First(methodType);
                    if (currentMethod != null)
                        ilPro = currentMethod.Body.GetILProcessor();
                }
            }
            return this;
        }

        public ILA FI(Func<Instruction, bool> where)
        {
            if (currentMethod != null)
                currentIns = currentMethod.Body.Instructions.First(where);
            return this;
        }

        public ILA InsertAfter(OpCode codes)
        {
            if (ilPro != null)
            {
                var ins = ilPro.Create(codes);
                ilPro.InsertAfter(currentIns, ins);
                currentIns = ins;
            }
            return this;
        }

        public ILA InsertBefore(OpCode codes)
        {
            if (ilPro != null)
            {
                var ins = ilPro.Create(codes);
                ilPro.InsertBefore(currentIns, ins);
                currentIns = ins;
            }
            return this;
        }

        public ILA InsertAfter(OpCode codes, Func<ILA, object> func)
        {
            if (ilPro != null)
            {
                var obj = func(this);
                if (obj != null)
                {
                    var method = ilPro.GetType().GetMethod("Create", new Type[] { typeof(OpCode), obj.GetType() });
                    var ins = (Instruction)method.Invoke(ilPro, new object[] { codes, obj });
                    ilPro.InsertAfter(currentIns, ins);
                    currentIns = ins;
                }
            }
            return this;
        }

        public ILA InsertBefore(OpCode codes, Func<ILA, object> func)
        {
            if (ilPro != null)
            {
                var obj = func(this);
                if (obj != null)
                {
                    var method = ilPro.GetType().GetMethod("Create", new Type[] { typeof(OpCode), obj.GetType() });
                    var ins = (Instruction)method.Invoke(ilPro, new object[] { codes, obj });
                    ilPro.InsertBefore(currentIns, ins);
                    currentIns = ins;
                }
            }
            return this;
        }


        public TypeDefinition FT(Func<AssemblyDefinition, bool> assWhere, Func<TypeDefinition, bool> typeWhere)
        {
            var ass = assemblies.FirstOrDefault(assWhere);
            if (ass != null)
            {
                return ass.MainModule.Types.FirstOrDefault(typeWhere);
            }
            return null;
        }

        //public ILA InsertAfter(params object[] paramList)
        //{
        //    if (ilPro != null)
        //    {
        //        var types = Array.ConvertAll<object, Type>(paramList, new Converter<object, Type>(u => u.GetType()));
        //        var method = ilPro.GetType().GetMethod("Create", types);
        //        var ins = (Instruction)method.Invoke(ilPro, paramList);
        //        ilPro.InsertAfter(currentIns, ins);
        //        currentIns = ins;
        //    }
        //    return this;
        //}

        //public ILA InsertBefore(params object[] paramList)
        //{
        //    if (ilPro != null)
        //    {
        //        var types = Array.ConvertAll<object, Type>(paramList, new Converter<object, Type>(u => u.GetType()));
        //        var method = ilPro.GetType().GetMethod("Create", types);
        //        var ins = (Instruction)method.Invoke(ilPro, paramList);
        //        ilPro.InsertBefore(currentIns, ins);
        //        currentIns = ins;
        //    }
        //    return this;
        //}

        public ILA Save(string path)
        {
            if (currentASM != null)
                currentASM.Write(path);
            return this;
        }
    }
}

调用代码

string path = AppDomain.CurrentDomain.BaseDirectory+ "Runtime\\";
            string importDllPath = path+"test.dll";
            string saveDllPath ="test_new.dll";
            string className = "TConnection";
            string methodName = "TExecute";
            new ILA(importDllPath).
                FM(u => u.Name.Equals(className), m => m.Name.Equals(methodName)).
                FI(u => u.Offset == 0xC5).
                InsertAfter(OpCodes.Ldsfld, asm => asm.CurrentType.Fields.Where(u => u.Name.Equals("Log")).First()).
                InsertAfter(OpCodes.Ldstr, asm => "sqliteconnect:").
                InsertAfter(OpCodes.Ldarg_0).
                InsertAfter(OpCodes.Ldfld, asm=> asm.CurrentType.Fields.Where(u => u.Name.Equals("_connection")).First()).
                InsertAfter(OpCodes.Callvirt, asm => asm.CurrentASM.MainModule.ImportReference(asm.FT(u=>u.FullName.Contains("System.Data.SQLite"),t=>t.Name.Equals("SQLiteConnection")).Properties.FirstOrDefault(p=>p.Name.Equals("ConnectionString")).GetMethod)).
                //InsertAfter(OpCodes.Ldarg_0).
                InsertAfter(OpCodes.Call, asm => asm.CurrentASM.MainModule.ImportReference(typeof(String).GetMethod("Concat", new Type[] { typeof(string), typeof(string) }))).
                InsertAfter(OpCodes.Callvirt, asm => asm.CurrentASM.MainModule.ImportReference(asm.FT(u => u.FullName.Contains("OFX.Core.Contracts"), t => t.Name.Equals("ILog")).Methods.FirstOrDefault(m => m.Name.Equals("Debug") && m.Parameters != null && m.Parameters.Count == 1&&m.Parameters[0].ParameterType.FullName.Equals(typeof(object).FullName)))).
                //InsertAfter(OpCodes.Ldarg_2).
                InsertAfter(OpCodes.Nop).
            Save(saveDllPath);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值