public Injector Hook(MethodDefinition hookMethod, HookData hookData = null) { if (TargetMethod == null) { throw new NullReferenceException($"{nameof(TargetMethod)} was null, which must be populated if you want to modify the IL code."); } // TODO: dry coded // TODO: Fix 'PassInvokingInstance' to only execute on target instance types var flags = InjectFlags.PassInvokingInstance; if (TargetMethod.Parameters.Count > 0) { flags |= InjectFlags.PassParametersRef; } if (hookMethod.ReturnType.FullName != TargetAssembly.MainModule.TypeSystem.Void.FullName) { flags |= InjectFlags.ModifyReturn; } hookData ??= new HookData { Flags = flags }; var injector = new InjectionDefinition(TargetMethod, hookMethod, hookData.Flags); injector.Inject(hookData.StartCode, hookData.Token, hookData.Direction); return(this); }
public AdviceAroundProcess(ILogger log, MethodDefinition target, InjectionDefinition injection) : base(log, target, injection) { _entry = target; _wrapperNamePrefix = $"{GetAroundMethodPrefix(_method)}w_"; _unWrapperName = $"{GetAroundMethodPrefix(_method)}u"; _movedOriginalName = $"{GetAroundMethodPrefix(_method)}o"; }
public AfterAsyncWeaveProcess(ILogger log, MethodDefinition target, InjectionDefinition injection) : base(log, target, injection) { var builderField = _stateMachine.Fields.First(f => f.Name == "<>t__builder"); _builder = builderField.FieldType; _asyncResult = (_builder as IGenericInstance)?.GenericArguments.FirstOrDefault(); }
public AdviceWeaveProcessBase(ILogger log, MethodDefinition target, InjectionDefinition injection) { _log = log; _target = target; _effect = (TEffect)injection.Effect; _injection = injection; _aspect = injection.Source; }
public AdviceAfterProcess(ILogger log, MethodDefinition target, InjectionDefinition injection) : base(log, target, injection) { if (_target.ReturnType.FullName != WellKnownTypes.Void && _effect.Arguments.Any(a => a.Source == Source.ReturnValue)) { _retvar = GetOrCreateRetVar(); } }
public AdviceAfterProcess(ILogger log, MethodDefinition target, InjectionDefinition injection) : base(log, target, injection) { if (!_method.ReturnType.Match(StandardTypes.Void) && _effect.Arguments.Any(a => a.Source == Source.ReturnValue)) { _retvar = GetOrCreateRetVar(); } }
public void Weave(InjectionDefinition injection) { var effect = (AdviceEffectBase)injection.Effect; if (injection.Target is EventDefinition) { var target = (EventDefinition)injection.Target; if (target.AddMethod != null && effect.Target.HasFlag(Target.EventAdd)) { WeaveMethod(target.AddMethod, injection); } if (target.RemoveMethod != null && effect.Target.HasFlag(Target.EventRemove)) { WeaveMethod(target.RemoveMethod, injection); } return; } if (injection.Target is PropertyDefinition) { var target = (PropertyDefinition)injection.Target; if (target.SetMethod != null && effect.Target.HasFlag(Target.Setter)) { WeaveMethod(target.SetMethod, injection); } if (target.GetMethod != null && effect.Target.HasFlag(Target.Getter)) { WeaveMethod(target.GetMethod, injection); } return; } if (injection.Target is MethodDefinition) { var target = (MethodDefinition)injection.Target; if (target.IsConstructor && effect.Target.HasFlag(Target.Constructor)) { WeaveMethod(target, injection); } if (!target.IsConstructor && effect.Target.HasFlag(Target.Method)) { WeaveMethod(target, injection); } return; } _log.Log(GeneralRules.UnexpectedCompilerBehaviour, effect.Method, $"Unexpected injection target '{injection.Target.ToString()}'"); }
protected AdviceWeaveProcessBase(ILogger log, MethodDefinition target, InjectionDefinition injection) { _log = log; _method = target; _type = target.DeclaringType; _module = target.Module; _effect = (TEffect)injection.Effect; _injection = injection; _aspect = injection.Source; }
protected override void WeaveMethod(MethodDefinition method, InjectionDefinition injection) { if (injection.Effect is AroundAdviceEffect) { var process = new AdviceAroundProcess(_log, method, injection); process.Execute(); } else { throw new NotSupportedException($"Unknown effect type. {injection.Effect?.GetType().Name}"); } }
protected override void WeaveMethod(MethodDefinition method, InjectionDefinition injection) { if (injection.Effect is AroundAdviceEffect) { var process = new AdviceAroundProcess(_log, method, injection); process.Execute(); } else { throw new Exception("Unknown advice type."); } }
protected override void WeaveMethod(MethodDefinition method, InjectionDefinition injection) { if (method.IsAsync()) { new AfterAsyncWeaveProcess(_log, method, injection).Execute(); } if (method.IsIterator()) { new AfterIteratorWeaveProcess(_log, method, injection).Execute(); } }
/// <summary> /// Inject a hook call into this method. /// </summary> /// <param name="method">This method that is used as a target.</param> /// <param name="injectionMethod">The method the call of which to inject.</param> /// <param name="codeOffset"> /// The index of the instruction from which to start injecting. If positive, will count from the /// beginning of the method. If negative, will count from the end. For instance, -1 is the method's last instruction /// and 0 is the first. /// </param> /// <param name="tag"> /// If <see cref="InjectFlags.PassTag" /> is specified, the value of this parameter will be passed as a /// parameter to the injection method. /// </param> /// <param name="flags">Injection flags that specify what values to pass to the injection method and how to inject it.</param> /// <param name="dir">The direction in which to insert the call: either above the start code or below it.</param> /// <param name="localsID"> /// An array of indicies of local variables to pass to the injection method. Used only if /// <see cref="InjectFlags.PassLocals" /> is specified, otherwise ignored. /// </param> /// <param name="typeFields"> /// An array of class fields from the type the target lies in to pass to the injection method. /// Used only if <see cref="InjectFlags.PassFields" /> is specified, otherwise ignored. /// </param> public static void InjectWith(this MethodDefinition method, MethodDefinition injectionMethod, int codeOffset = 0, int tag = 0, InjectFlags flags = InjectFlags.None, InjectDirection dir = InjectDirection.Before, int[] localsID = null, FieldDefinition[] typeFields = null) { InjectionDefinition id = new InjectionDefinition(method, injectionMethod, flags, localsID, typeFields); id.Inject(codeOffset, tag, dir); }
/// <inheritdoc/> public override void Execute(AddMethodAttribute attribute) { var targetMethod = attribute?.Method ?? Method.Name; var methodDefinition = new MethodDefinition(targetMethod, MethodAttributes.Public, Method.ReturnType) { IsStatic = Type.IsSealed }; Type.Methods.Add(methodDefinition); var flags = GetInjectFlags(methodDefinition, attribute?.Flags); var injector = new InjectionDefinition(methodDefinition, Method, attribute?.Flags ?? flags); injector.Inject(attribute.StartCode, attribute.Token, attribute.Direction); }
protected virtual void WeaveMethod(MethodDefinition method, InjectionDefinition injection) { if (injection.Effect is AfterAdviceEffect) { var process = new AdviceAfterProcess(_log, method, injection); process.Execute(); } else if (injection.Effect is BeforeAdviceEffect) { var process = new AdviceBeforeProcess(_log, method, injection); process.Execute(); } else { throw new System.Exception("Unknown advice type."); } }
public virtual bool CanWeave(InjectionDefinition injection) { var result = (injection.Effect is BeforeAdviceEffect || injection.Effect is AfterAdviceEffect) && (injection.Target is EventDefinition || injection.Target is PropertyDefinition || injection.Target is MethodDefinition); if (result && injection.Target is MethodDefinition && injection.Effect is AfterAdviceEffect) { var md = (MethodDefinition)injection.Target; if (md.IsAsync() || md.IsIterator()) { result = false; } } return(result); }
/// <inheritdoc/> public override void Execute(HookAttribute attribute) { var targetMethod = attribute?.Method ?? Method.Name; MethodDefinition targetMethodDefinition = null; if (!string.IsNullOrWhiteSpace(attribute.FullPath)) { var type = TargetAssembly.MainModule.Types.FirstOrDefault(x => attribute.FullPath.StartsWith(x.FullName) || attribute.FullPath.StartsWith(x.Name)); targetMethodDefinition = type.Methods.FirstOrDefault(x => attribute.FullPath.EndsWith(x.FullName) || attribute.FullPath.EndsWith(x.Name)); } else { targetMethodDefinition = TargetAssembly.MainModule.GetType(attribute.Type.FullName).GetMethod(targetMethod); } var flags = GetInjectFlags(targetMethodDefinition, attribute?.Flags); var injector = new InjectionDefinition(targetMethodDefinition, Method, flags); injector.Inject(attribute.StartCode, attribute.Token, attribute.Direction); }
public override void Patch( PatcherArguments args ) { var PluginLoader = _hookAssembly.MainModule.GetType( "XUnity.AutoTranslator.Plugin.Core.PluginLoader" ); var LoadThroughBootstrapper = PluginLoader.GetMethod( "LoadThroughBootstrapper" ); var entryClasses = args.Assembly.MainModule.GetTypes().Where( x => EntryClasses.Contains( x.Name ) ).ToList(); foreach( var entryClass in entryClasses ) { var staticCtor = entryClass.Methods.FirstOrDefault( x => x.IsStatic && x.IsConstructor ); if( staticCtor != null ) { var injecctor = new InjectionDefinition( staticCtor, LoadThroughBootstrapper, InjectFlags.None ); injecctor.Inject( startCode: 0, direction: InjectDirection.Before ); } } SetPatchedAttribute( args.Assembly, "XUnity.AutoTranslator.Plugin.Core" ); }
internal bool Inject(ReturnData data, AttributeData hook) { try { Program.Chalker.WriteWait($"Injecting method \"{data.TypeDefinition.Name}.{data.MethodDefinition.Name}\".."); var flags = InjectFlags.PassInvokingInstance; if (data.MethodDefinition.Parameters.Count > 0) { flags |= InjectFlags.PassParametersRef; } if (hook.Method.ReturnType != hook.Assembly.MainModule.TypeSystem.Void) { flags |= InjectFlags.ModifyReturn; } var injector = new InjectionDefinition(data.MethodDefinition, hook.Method, flags); if ((bool)hook.Attribute.ConstructorArguments[1].Value) { injector.Inject(-1); } else { injector.Inject(); } Program.Chalker.WriteSuccess($"Injected method \"{data.TypeDefinition.Name}.{data.MethodDefinition.Name}\"."); return(true); } catch (Exception ex) { Program.Chalker.WriteError("Something went wrong while injecting."); Program.Chalker.WriteError($"Message: {ex.Message}"); if (!(ex is InjectionDefinitionException)) { Program.Chalker.WriteError(ex.StackTrace); } } return(false); }
protected virtual void WeaveMethod(MethodDefinition method, InjectionDefinition injection) { switch (injection.Effect) { case AfterAdviceEffect _: { var process = new AdviceAfterProcess(_log, method, injection); process.Execute(); break; } case BeforeAdviceEffect _: { var process = new AdviceBeforeProcess(_log, method, injection); process.Execute(); break; } case null: throw new ArgumentNullException(nameof(injection), "Effect is null."); default: throw new NotSupportedException($"Unknown effect type. {injection.Effect.GetType().Name}"); } }
internal static bool Inject(ReturnData data, HookData hook) { try { InjectionDefinition injector = GetInjectionDefinition(data, hook); if ((bool)hook.Attribute.ConstructorArguments[1].Value) { injector.Inject(-1); } else { injector.Inject(); } return(true); } catch (Exception ex) { Externs.MessageBox(ex.GetType().Name, ex.ToString()); } return(false); }
public override bool CanWeave(InjectionDefinition injection) { var target = injection.Target as MethodDefinition; return(injection.Effect is AfterAdviceEffect && target != null && (target.IsAsync() || target.IsIterator())); }
public static void InjectCallToMethod(AssemblyDefinition _gameAdef, string _injectClass, string _injectMethod, int _entryNr, AssemblyDefinition _modAdef, string _modClass, string _modMethod, InjectFlags _flag) { TypeDefinition gameClass = _gameAdef.MainModule.GetType(_injectClass); MethodDefinition gameMethod = null; if (gameClass != null) { var i = 0; foreach (MethodDefinition method in gameClass.Methods) { if (method.Name == _injectMethod) { if (i == _entryNr) { Console.WriteLine("Selected method to inject into: " + method.FullName); gameMethod = method; break; } else { i++; } } } } else { Console.WriteLine("Could not find game class " + _injectClass); return; } if (gameMethod == null) { Console.WriteLine("Could not find game method " + _injectMethod); return; } MethodDefinition modMethod = null; foreach (ModuleDefinition module in _modAdef.Modules) { foreach (TypeDefinition type in module.Types) { foreach (MethodDefinition method in type.Methods) { //Console.WriteLine(method.Name); if (method.Name == _modMethod) { modMethod = method; } } } } if (modMethod == null) { Console.WriteLine("Could not find mod method " + _modMethod); return; } try { InjectionDefinition injector = new InjectionDefinition(gameMethod, modMethod, _flag); injector.Inject(0, null, InjectDirection.Before); Console.WriteLine("Injection into " + gameMethod.ToString() + " OK "); } catch (Exception ex) { Console.WriteLine(ex); } }
public static void Main(string[] args) { AssemblyDefinition ad = AssemblyLoader.LoadAssembly("Tests.exe"); TypeDefinition testType = ad.MainModule.GetType("Tests.TypeDefinitionTests"); Console.WriteLine($"Loaded type: {testType}"); TypeReference tr = ParamHelper.FromType( typeof(Dictionary <,>).MakeGenericType(ParamHelper.CreateDummyType("T"), ParamHelper.CreateDummyType("T"))); MethodDefinition md = testType.GetMethod( "Test", typeof(List <>).MakeGenericType(ParamHelper.CreateDummyType("T")), typeof(Dictionary <,>).MakeGenericType( typeof(List <>).MakeGenericType(ParamHelper.CreateDummyType("T")), typeof(List <>).MakeGenericType( typeof(Dictionary <,>).MakeGenericType( ParamHelper.CreateDummyType("U"), ParamHelper.CreateDummyType("T"))))); Console.WriteLine($"Type: {tr}"); Console.WriteLine($"Method: {md}"); InjectionDefinition hd = new InjectionDefinition( testType.GetMethod("Test2"), testType.GetMethod("HookTest1"), InjectFlags.ModifyReturn | InjectFlags.PassInvokingInstance | InjectFlags.PassTag | InjectFlags.PassFields | InjectFlags.PassParametersRef, new[] { 0 }, testType.GetField("testMember")); Console.WriteLine($"Hook def: {hd}"); InjectionDefinition hd2 = testType.GetInjectionMethod( "HookTest1", testType.GetMethod("Test2"), InjectFlags.ModifyReturn | InjectFlags.PassInvokingInstance | InjectFlags.PassTag | InjectFlags.PassFields | InjectFlags.PassParametersRef, new[] { 0 }, testType.GetField("testMember")); InjectionDefinition hd3 = testType.GetInjectionMethod("", null, InjectFlags.None, null, null); /* * testType.GetMethod("Test2") * .InjectWith( * testType.GetMethod("HookTest1"), * 0, * 0, * InjectFlags.All_Ref | InjectFlags.ModifyReturn, * InjectDirection.Before, * new[] {0}, * new[] {testType.GetField("testMember")}); */ InjectionDefinition hd4 = new InjectionDefinition( testType.GetMethod(nameof(TestPartialParams)), testType.GetMethod(nameof(HookTest2)), new InjectValues { TagType = InjectValues.PassTagType.Int32, PassInvokingInstance = true, ModifyReturn = true, ParameterType = InjectValues.PassParametersType.ByValue }.GetCombinedFlags()); hd4.Inject(token: 5); InjectionDefinition hd5 = new InjectionDefinition( testType.GetMethod(nameof(TestPartialParams)), testType.GetMethod(nameof(HookTest3)), new InjectValues { TagType = InjectValues.PassTagType.String, PassInvokingInstance = true, ModifyReturn = true, ParameterType = InjectValues.PassParametersType.ByValue }.GetCombinedFlags()); hd5.Inject(token: "test"); MethodDefinition[] matches = testType.MatchMethod("TestMatch", typeof(int), typeof(string)); Console.WriteLine($"Another hookdef: {hd2}"); Console.WriteLine($"Another hookdef3: {hd3}"); testType.ChangeAccess("hidden.*", recursive: true); hd2.Inject(2, 2); ad.Write("Test_patched.exe"); Console.ReadLine(); }
private InjectionDefinition MergeInjections(InjectionDefinition a1, InjectionDefinition a2) { a1.Priority = Enumerable.Max(new[] { a1.Priority, a2.Priority }); a1.Triggers = a1.Triggers.Concat(a2.Triggers).Distinct().ToList(); return(a1); }
public override bool CanWeave(InjectionDefinition injection) { return(injection.Effect is AroundAdviceEffect && (injection.Target is EventDefinition || injection.Target is PropertyDefinition || injection.Target is MethodDefinition)); }
public AfterIteratorWeaveProcess(ILogger log, MethodDefinition target, InjectionDefinition injection) : base(log, target, injection) { }
public AdviceBeforeProcess(ILogger log, MethodDefinition target, InjectionDefinition injection) : base(log, target, injection) { }
public AfterStateMachineWeaveProcessBase(ILogger log, MethodDefinition target, InjectionDefinition injection) : base(log, target, injection) { _stateMachineRef = GetStateMachine(); _stateMachine = _stateMachineRef.Resolve(); _originalThis = _target.IsStatic ? (Func <FieldDefinition>)null : () => GetThisField(); }
public AfterStateMachineWeaveProcessBase(ILogger log, MethodDefinition target, InjectionDefinition injection) : base(log, target, injection) { _stateMachine = GetStateMachine(); _originalThis = _target.IsStatic ? null : GetThisField(); }
public void Inject() { Console.WriteLine("Beginning inject\n"); var gameAssembly = AssemblyDefinition.ReadAssembly(_backupGameAssemblyFile.FullName, new ReaderParameters() { AssemblyResolver = _resolver }); foreach (var mod in _modManager) { Console.WriteLine($"\t_______________________________________________\n"); Console.Write($"\tInjecting {Path.GetFileNameWithoutExtension(mod.ModAssemblyFile.Name)}..."); var modAssembly = AssemblyDefinition.ReadAssembly(mod.ModAssemblyFile.FullName, new ReaderParameters() { AssemblyResolver = _resolver }); foreach (var methodInjection in mod.ModMethodInjections) { var toInject = modAssembly .MainModule .GetType(methodInjection.SourceMethod.InjectionType) .Methods .Single(m => m.Name == methodInjection.SourceMethod.InjectionMethod); if (methodInjection.InjectionAssembly != null) { var injectPath = new FileInfo(Path.Combine(_gameAssemblyFile.Directory.FullName, methodInjection.InjectionAssembly)); var tempFil = new FileInfo(Path.Combine(injectPath.DirectoryName, injectPath.Name + "_temp.dll")); var tempFil2 = new FileInfo(Path.Combine(injectPath.DirectoryName, injectPath.Name + "_temp2.dll")); File.Copy(injectPath.FullName, tempFil.FullName, true); var injectTargetAssembly = AssemblyDefinition.ReadAssembly(tempFil.FullName, new ReaderParameters { AssemblyResolver = _resolver }); var injectionLocation = injectTargetAssembly .MainModule .GetType(methodInjection.TargetMethod.InjectionType) .GetMethod(methodInjection.TargetMethod.InjectionMethod); var injector = new InjectionDefinition(injectionLocation, toInject, methodInjection.InjectFlags); injector .Inject(methodInjection.InjectionLocation == MethodInjectionInfo.MethodInjectionLocation.Top ? injectionLocation.Body.Instructions.First() : injectionLocation.Body.Instructions.Last()); injectTargetAssembly.Write(tempFil2.FullName); } else { var injectionLocation = gameAssembly .MainModule .GetType(methodInjection.TargetMethod.InjectionType) .GetMethod(methodInjection.TargetMethod.InjectionMethod); var injector = new InjectionDefinition(injectionLocation, toInject, methodInjection.InjectFlags); injector .Inject(methodInjection.InjectionLocation == MethodInjectionInfo.MethodInjectionLocation.Top ? injectionLocation.Body.Instructions.First() : injectionLocation.Body.Instructions.Last()); } } Console.WriteLine($"Done.\n\tCopying Dependencies"); File.Copy(mod.ModAssemblyFile.FullName, Path.Combine(_gameDirectory.FullName, mod.ModAssemblyFile.Name), true); File.Copy(mod.ModAssemblyFile.FullName, Path.Combine(_gameAssemblyDirectory.FullName, mod.ModAssemblyFile.Name), true); if (mod.ModDependencyDirectory != null) { foreach (var file in mod.ModDependencyDirectory.GetFiles()) { try { File.Copy(file.FullName, Path.Combine(_gameDirectory.FullName, file.Name), true); File.Copy(file.FullName, Path.Combine(_gameAssemblyDirectory.FullName, file.Name), true); } catch (Exception e) { Console.WriteLine($"\t\tUnable to copy {file.Name}, probally already there. Skipping..."); } } } Console.WriteLine($"\t_______________________________________________\n"); } Console.WriteLine($"***************************************"); Console.WriteLine($"Done injecting. Ready to write modified assembly"); Console.WriteLine($"***************************************"); gameAssembly.Write(_gameAssemblyFile.FullName); }