Инжектим методы в другое приложение через Dnlib

Тема в разделе "Программирование", создана пользователем Antlion, 27 июн 2019.

  1. Antlion

    Antlion New Member

    Сообщения:
    14
    Симпатии:
    0
    Немного подправил изначальный код Confusera.
    И упростил вызов инжекта для каждого метода ( можно ещё упростить но лень )
    P.S: Комментарии и.т.п вы можете найти в оригинальном проекте Confusera =) Убрал чтобы не мешались.
    Создаём класс InjectContext.cs

    Код:
    namespace ConfuserEx.PackEx.Injectors
    {
    using dnlib.DotNet;
    using System.Collections.Generic;

    internal class InjectContext : ImportResolver, IInjectContext
    {
    public readonly DictionaryIDnlibDef, IDnlibDef> Map = new DictionaryIDnlibDef, IDnlibDef>();
    public readonly ModuleDef OriginModule, TargetModule;
    public readonly Importer importer;

    public InjectContext() { }

    public InjectContext(ModuleDef module, ModuleDef target)
    {
    this.OriginModule = module;
    this.TargetModule = target;
    this.importer = new Importer(target, ImporterOptions.TryToUseTypeDefs)
    {
    Resolver = this
    };
    }

    public InjectContext(DictionaryIDnlibDef, IDnlibDef> map, ModuleDef originModule, ModuleDef targetModule, Importer importer)
    {
    this.Map = map;
    this.OriginModule = originModule;
    this.TargetModule = targetModule;
    this.importer = importer;
    }

    public Importer Importer => this.importer;

    public override TypeDef Resolve(TypeDef typeDef) => this.Map.ContainsKey(typeDef) ? (TypeDef)this.Map[typeDef] : null;

    public override MethodDef Resolve(MethodDef methodDef) => this.Map.ContainsKey(methodDef) ? (MethodDef)this.Map[methodDef] : null;

    public override FieldDef Resolve(FieldDef fieldDef) => this.Map.ContainsKey(fieldDef) ? (FieldDef)this.Map[fieldDef] : null;
    }
    }
    Интерфейс IInjectContext:

    Код:
    namespace ConfuserEx.PackEx.Injectors
    {
    using dnlib.DotNet;

    internal interface IInjectContext
    {
    Importer Importer { get; }
    FieldDef Resolve(FieldDef fieldDef);
    MethodDef Resolve(MethodDef methodDef);
    TypeDef Resolve(TypeDef typeDef);
    }
    }
    Создадим класс InjectHelper.cs

    Код:
    namespace ConfuserEx.PackEx.Injectors
    {
    using dnlib.DotNet;
    using dnlib.DotNet.Emit;
    using System.Collections.Generic;
    using System.Linq;

    internal static partial class InjectHelper
    {
    private static TypeDefUser Clone(TypeDef origin)
    {
    var ret = new TypeDefUser(origin.Namespace, origin.Name)
    {
    Attributes = origin.Attributes
    };

    if (origin.ClassLayout != null)
    {
    ret.ClassLayout = new ClassLayoutUser(origin.ClassLayout.PackingSize, origin.ClassSize);
    }

    foreach (GenericParam genericParam in origin.GenericParameters)
    {
    ret.GenericParameters.Add(new GenericParamUser(genericParam.Number, genericParam.Flags, "-"));
    }

    return ret;
    }

    private static MethodDefUser Clone(MethodDef origin)
    {
    var ret = new MethodDefUser(origin.Name, null, origin.ImplAttributes, origin.Attributes);

    foreach (GenericParam genericParam in origin.GenericParameters)
    {
    ret.GenericParameters.Add(new GenericParamUser(genericParam.Number, genericParam.Flags, "-"));
    }

    return ret;
    }

    private static FieldDefUser Clone(FieldDef origin)
    {
    var fieldDefUser = new FieldDefUser(origin.Name, null, origin.Attributes);
    return fieldDefUser;
    }

    private static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx)
    {
    TypeDef ret;
    if (!ctx.Map.TryGetValue(typeDef, out IDnlibDef existing))
    {
    ret = Clone(typeDef);
    ctx.Map[typeDef] = ret;
    }
    else
    {
    ret = (TypeDef)existing;
    }

    foreach (TypeDef nestedType in typeDef.NestedTypes)
    {
    ret.NestedTypes.Add(PopulateContext(nestedType, ctx));
    }

    foreach (MethodDef method in typeDef.Methods)
    {
    ret.Methods.Add((MethodDef)(ctx.Map[method] = Clone(method)));
    }

    foreach (FieldDef field in typeDef.Fields)
    {
    ret.Fields.Add((FieldDef)(ctx.Map[field] = Clone(field)));
    }

    return ret;
    }

    private static void CopyTypeDef(TypeDef typeDef, InjectContext ctx)
    {
    var newTypeDef = (TypeDef)ctx.Map[typeDef];

    newTypeDef.BaseType = (ITypeDefOrRef)ctx.Importer.Import(typeDef.BaseType);

    foreach (InterfaceImpl iface in typeDef.Interfaces)
    {
    newTypeDef.Interfaces.Add(new InterfaceImplUser((ITypeDefOrRef)ctx.Importer.Import(iface.Interface)));
    }
    }

    private static void CopyMethodDef(MethodDef methodDef, InjectContext ctx)
    {
    var newMethodDef = (MethodDef)ctx.Map[methodDef];

    newMethodDef.Signature = ctx.Importer.Import(methodDef.Signature);
    newMethodDef.Parameters.UpdateParameterTypes();

    if (methodDef.ImplMap != null)
    {
    newMethodDef.ImplMap = new ImplMapUser(new ModuleRefUser(ctx.TargetModule, methodDef.ImplMap.Module.Name), methodDef.ImplMap.Name, methodDef.ImplMap.Attributes);
    }

    foreach (CustomAttribute ca in methodDef.CustomAttributes)
    {
    newMethodDef.CustomAttributes.Add(new CustomAttribute((ICustomAttributeType)ctx.Importer.Import(ca.Constructor)));
    }

    if (methodDef.HasBody)
    {
    newMethodDef.Body = new CilBody(methodDef.Body.InitLocals, new ListInstruction>(), new ListExceptionHandler>(), new ListLocal>());
    newMethodDef.Body.MaxStack = methodDef.Body.MaxStack;

    var bodyMap = new Dictionaryobject, object>();

    foreach (Local local in methodDef.Body.Variables)
    {
    var newLocal = new Local(ctx.Importer.Import(local.Type));
    newMethodDef.Body.Variables.Add(newLocal);
    newLocal.Name = local.Name;
    newLocal.PdbAttributes = local.PdbAttributes;

    bodyMap[local] = newLocal;
    }

    foreach (Instruction instr in methodDef.Body.Instructions)
    {
    var newInstr = new Instruction(instr.OpCode, instr.Operand)
    {
    SequencePoint = instr.SequencePoint
    };

    switch (newInstr.Operand)
    {
    case IType _:
    newInstr.Operand = ctx.Importer.Import((IType)newInstr.Operand);
    break;
    case IMethod _:
    newInstr.Operand = ctx.Importer.Import((IMethod)newInstr.Operand);
    break;
    case IField _:
    newInstr.Operand = ctx.Importer.Import((IField)newInstr.Operand);
    break;
    default:
    break;
    }

    newMethodDef.Body.Instructions.Add(newInstr);
  2. Enzo

    Enzo New Member

    Сообщения:
    753
    Симпатии:
    0
    оказывается все так просто когда ты кодер(или близко)...))
  3. Oliva

    Oliva Member

    Сообщения:
    542
    Симпатии:
    0
    Ни хуя не понятно, но красава!
  4. aivanov

    aivanov New Member

    Сообщения:
    1
    Симпатии:
    0
    Всем привет! Может кто-то знает как програмно в c# при помощи dnlib изменить ссылку в текущей dll на другую dll? Т.е. есть dll у нее ссылки на другие dll и нужно в некоторых изменить версию и public key.

Поделиться этой страницей