private void applybutton_Click(object sender, EventArgs e)
        {
            if (nametextbox.TextLength < 3)
            {
                MessageBox.Show(MainForm, "Name is too short!", "Oxide Patcher", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (hooknametextbox.TextLength < 3)
            {
                MessageBox.Show(MainForm, "Hook name is too short!", "Oxide Patcher", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            Hook.Name     = nametextbox.Text;
            Hook.HookName = hooknametextbox.Text;

            MainForm.UpdateHook(Hook);

            if (msilbefore != null && msilafter != null)
            {
                ILWeaver weaver = new ILWeaver(methoddef.Body);
                weaver.Module = methoddef.Module;

                msilbefore.Text = weaver.ToString();
                Hook.ApplyPatch(methoddef, weaver, MainForm.OxideAssembly);
                msilafter.Text = weaver.ToString();
            }

            applybutton.Enabled = false;
        }
Beispiel #2
0
 /// <summary>
 /// Process current assembly
 /// </summary>
 public void Process()
 {
     ILWeaver.Weave(moduleDefinition);
     moduleDefinition.Write(fileName, new WriterParameters {
         WriteSymbols = hasPDB
     });
 }
Beispiel #3
0
        private bool GetFieldOrProperty(ILWeaver weaver, MethodDefinition originalMethod, TypeDefinition currentArg, string[] target, Patcher patcher)
        {
            if (currentArg == null || target == null || target.Length == 0)
            {
                return(false);
            }

            int i;
            var arg = currentArg;

            for (i = 0; i < target.Length; i++)
            {
                if (GetFieldOrProperty(weaver, originalMethod, ref arg, target[i], patcher))
                {
                    continue;
                }
                ShowMsg($"Could not find the field or property `{target[i]}` in any of the base classes or interfaces of `{currentArg.Name}`.", "Invalid field or property", patcher);
                return(false);
            }

            if (arg.IsValueType || arg.IsByReference)
            {
                weaver.Add(arg.Module == originalMethod.Module
                    ? Instruction.Create(OpCodes.Box, arg.Resolve())
                    : Instruction.Create(OpCodes.Box, originalMethod.Module.Import(arg.Resolve())));
            }

            return(i >= 1);
        }
Beispiel #4
0
        public override bool ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxideassembly, Patching.Patcher patcher = null)
        {
            // Get the call hook method (only grab object parameters: ignore the object[] hook)
            List <MethodDefinition> callhookmethods = oxideassembly.MainModule.Types
                                                      .Single(t => t.FullName == "Oxide.Core.Interface")
                                                      .Methods.Where(m => m.IsStatic && m.Name == "CallHook" && m.HasParameters && m.Parameters.Any(p => p.ParameterType.IsArray) == false)
                                                      .OrderBy(x => x.Parameters.Count)
                                                      .ToList();

            // Start injecting where requested
            weaver.Pointer = InjectionIndex;

            // Get the existing instruction we're going to inject behind
            Instruction existing;

            try
            {
                existing = weaver.Instructions[weaver.Pointer];
            }
            catch (ArgumentOutOfRangeException)
            {
                ShowMsg($"The injection index specified for {Name} is invalid!", "Invalid Index", patcher);
                return(false);
            }

            // Load the hook name
            Instruction hookname = weaver.Add(Instruction.Create(OpCodes.Ldstr, HookName));

            // Push the arguments array to the stack and make the call
            //VariableDefinition argsvar; //This is the object array

            // Create an object array and load all arguments into it
            Instruction firstinjected = PushArgsArray(original, weaver, out int argCount, patcher) ?? hookname;

            /*if (argsvar != null)
             * weaver.Ldloc(argsvar);
             * else
             * weaver.Add(Instruction.Create(OpCodes.Ldnull));*/
            weaver.Add(Instruction.Create(OpCodes.Call, original.Module.Import(callhookmethods[argCount])));

            // Deal with the return value
            DealWithReturnValue(original, null, weaver);
            //DealWithReturnValue(original, argsvar, weaver);

            // Find all instructions which pointed to the existing and redirect them
            for (int i = 0; i < weaver.Instructions.Count; i++)
            {
                Instruction ins = weaver.Instructions[i];
                if (ins.Operand != null && ins.Operand.Equals(existing))
                {
                    // Check if the instruction lies within our injection range
                    // If it does, it's an instruction we just injected so we don't want to edit it
                    if (i < InjectionIndex || i > weaver.Pointer)
                    {
                        ins.Operand = firstinjected;
                    }
                }
            }
            return(true);
        }
Beispiel #5
0
        private async void applybutton_Click(object sender, EventArgs e)
        {
            Hook.Name     = nametextbox.Text;
            Hook.HookName = hooknametextbox.Text;

            MainForm.UpdateHook(Hook, false);

            if (msilbefore != null && msilafter != null)
            {
                ILWeaver weaver = new ILWeaver(methoddef.Body)
                {
                    Module = methoddef.Module
                };

                Hook.PreparePatch(assembly, methoddef, weaver, MainForm.OxideAssembly);
                msilbefore.Text = weaver.ToString();
                codebefore.Text = await Decompiler.GetSourceCode(methoddef, weaver);

                Hook.ApplyPatch(assembly, methoddef, weaver, MainForm.OxideAssembly);
                msilafter.Text = weaver.ToString();
                codeafter.Text = await Decompiler.GetSourceCode(methoddef, weaver);
            }

            applybutton.Enabled = false;
        }
 public static async Task<string> GetSourceCode(MethodDefinition methodDefinition, ILWeaver weaver = null)
 {
     return await Task.Run(() =>
     {
         try
         {
             if (weaver != null) weaver.Apply(methodDefinition.Body);
             var settings = new DecompilerSettings { UsingDeclarations = false };
             var context = new DecompilerContext(methodDefinition.Module)
             {
                 CurrentType = methodDefinition.DeclaringType,
                 Settings = settings
             };
             var astBuilder = new AstBuilder(context);
             astBuilder.AddMethod(methodDefinition);
             var textOutput = new PlainTextOutput();
             astBuilder.GenerateCode(textOutput);
             return textOutput.ToString();
         }
         catch (Exception ex)
         {
             return "Error in creating source code from IL: " + ex.Message + Environment.NewLine + ex.StackTrace;
         }
         finally
         {
             if (weaver != null) methodDefinition.Body = null;
         }
     });
 }
Beispiel #7
0
 /// <summary>
 /// PrePatches this hook into the target weaver
 /// </summary>
 /// <param name="weaver"></param>
 /// <param name="oxidemodule"></param>
 /// <param name="original"></param>
 /// <param name="console"></param>
 public bool PreparePatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxidemodule, bool console)
 {
     if (BaseHook != null)
     {
         return(BaseHook.PreparePatch(original, weaver, oxidemodule, console) && BaseHook.ApplyPatch(original, weaver, oxidemodule, console));
     }
     return(true);
 }
Beispiel #8
0
 /// <summary>
 /// PrePatches this hook into the target weaver
 /// </summary>
 /// <param name="weaver"></param>
 /// <param name="oxidemodule"></param>
 /// <param name="original"></param>
 /// <param name="patcher"></param>
 public bool PreparePatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxidemodule, Patching.Patcher patcher = null)
 {
     if (BaseHook != null)
     {
         return(BaseHook.PreparePatch(original, weaver, oxidemodule, patcher) && BaseHook.ApplyPatch(original, weaver, oxidemodule, patcher));
     }
     return(true);
 }
Beispiel #9
0
 static PatternTest()
 {
     ILWeaver.Weave <FrozenObject>();
     ILWeaver.Weave <PatternModel>();
     ILWeaver.Weave <ImmutableObject>();
     ILWeaver.Weave <ReaderWriterObject>();
     ILWeaver.Weave <LoggingObject>();
     //ILWeaver.SaveAssembly();
 }
Beispiel #10
0
        public override void ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxideassembly)
        {
            MethodDefinition initoxidemethod = oxideassembly.MainModule.Types
                                               .Single((t) => t.FullName == "Oxide.Core.Interface")
                                               .Methods.Single((m) => m.IsStatic && m.Name == "Initialise");

            weaver.Pointer = 0;
            weaver.Add(Instruction.Create(OpCodes.Call, weaver.Module.Import(initoxidemethod)));
        }
Beispiel #11
0
        public override bool ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxideassembly, bool console)
        {
            // Get the call hook method
            MethodDefinition callhookmethod = oxideassembly.MainModule.Types
                .Single((t) => t.FullName == "Oxide.Core.Interface")
                .Methods.Single((m) => m.IsStatic && m.Name == "CallHook");

            // Start injecting where requested
            weaver.Pointer = InjectionIndex;

            // Get the existing instruction we're going to inject behind
            Instruction existing;
            try
            {
                existing = weaver.Instructions[weaver.Pointer];
            }
            catch (ArgumentOutOfRangeException)
            {
                if (console == false)
                {
                    MessageBox.Show(string.Format("The injection index specified for {0} is invalid!", this.Name), "Invalid Index", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                return false;
            }

            // Load the hook name

            // Push the arguments array to the stack and make the call
            VariableDefinition argsvar;
            var firstinjected = PushArgsArray(original, weaver, out argsvar);
            var hookname = weaver.Add(Instruction.Create(OpCodes.Ldstr, HookName));
            if (firstinjected == null) firstinjected = hookname;
            if (argsvar != null)
                weaver.Ldloc(argsvar);
            else
                weaver.Add(Instruction.Create(OpCodes.Ldnull));
            weaver.Add(Instruction.Create(OpCodes.Call, original.Module.Import(callhookmethod)));

            // Deal with the return value
            DealWithReturnValue(original, argsvar, weaver);

            // Find all instructions which pointed to the existing and redirect them
            for (int i = 0; i < weaver.Instructions.Count; i++)
            {
                Instruction ins = weaver.Instructions[i];
                if (ins.Operand != null && ins.Operand.Equals(existing))
                {
                    // Check if the instruction lies within our injection range
                    // If it does, it's an instruction we just injected so we don't want to edit it
                    if (i < InjectionIndex || i > weaver.Pointer)
                        ins.Operand = firstinjected;
                }
            }
            return true;
        }
        /// <summary>
        /// Weave field into current aspect
        /// </summary>
        /// <param name="il">IL Generator</param>
        /// <param name="field">Field</param>
        /// <param name="fieldMethod">Field Method</param>
        private void BlockField(Mono.Cecil.Cil.ILProcessor il, Mono.Cecil.FieldDefinition field, MethodInfo fieldMethod)
        {
            var fieldName = field.Name;

            // Return if it is a backing field
            if (fieldName.IndexOf("k__BackingField") >= 0)
            {
                return;
            }

            var aspect = field.GetCustomAttribute <MemberInterceptionAspect>() ?? field.DeclaringType.GetCustomAttribute <MemberInterceptionAspect>()
                         ?? field.DeclaringType.Module.Assembly.GetCustomAttribute <MemberInterceptionAspect>();

            if (!ILWeaver.IsValidAspectFor(field, aspect))
            {
                return;
            }

            var fieldType   = field.FieldType;
            var isStatic    = field.IsStatic;
            var fieldLocal  = il.DeclareLocal(fieldType);
            var memberLocal = il.DeclareLocal(typeof(MemberContext));
            var aspectField = ILWeaver.TypeFieldAspects[field.DeclaringType.FullName][aspect.GetType().FullName];

            // Store current get field value
            il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, fieldLocal);

            // MemberContext(object instance, string locationName, object value)
            il.Emit(isStatic ? Mono.Cecil.Cil.OpCodes.Ldnull : Mono.Cecil.Cil.OpCodes.Ldarg_0);
            il.Emit(Mono.Cecil.Cil.OpCodes.Ldstr, fieldName);
            il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, fieldLocal);

            if (fieldType.IsValueType)
            {
                il.Emit(Mono.Cecil.Cil.OpCodes.Box, fieldType);
            }

            il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, MemberContextCtor);
            il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, memberLocal);

            il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, aspectField);
            il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, memberLocal);
            il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, fieldMethod);

            // Load value back to stack and reflect changes if any
            il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, memberLocal);
            il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, MemberContextValueMethod);

            // Convert to expected type
            il.Emit(fieldType.IsValueType ? Mono.Cecil.Cil.OpCodes.Unbox_Any : Mono.Cecil.Cil.OpCodes.Isinst, fieldType);
        }
Beispiel #13
0
        public void TestWeave()
        {
            using (FileStream input = new FileStream(_executable, FileMode.Open, FileAccess.Read))
                using (FileStream output = new FileStream(_executableWeaved, FileMode.Create, FileAccess.Write))
                {
                    var weaver             = new ILWeaver();
                    var assemblyDefinition = weaver.Weave(input, new string[0], false);
                    assemblyDefinition.Write(output);
                }

            string weavedOutput = this.GetWeavedOutput();

            Assert.That(weavedOutput, Is.Not.StringContaining("Original Void2"), "Execution of AnnotatedClass.Void2 should have been skipped");
        }
Beispiel #14
0
        public override bool ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxidemodule, Patcher patcher = null)
        {
            var insts = new List<Instruction>();
            foreach (var instructionData in Instructions)
            {
                var instruction = CreateInstruction(original, weaver, instructionData, insts, patcher);
                if (instruction == null) return false;
                insts.Add(instruction);
            }
            // Start injecting where requested
            weaver.Pointer = InjectionIndex;

            if (!weaver.RemoveAfter(RemoveCount))
            {
                ShowMsg(string.Format("The remove count specified for {0} is invalid!", Name), "Invalid Remove Count", patcher);
                return false;
            }
            if (Instructions.Count == 0) return true;

            // Get the existing instruction we're going to inject behind
            Instruction existing;
            try
            {
                existing = weaver.Instructions[weaver.Pointer];
            }
            catch (ArgumentOutOfRangeException)
            {
                ShowMsg(string.Format("The injection index specified for {0} is invalid!", Name), "Invalid Index", patcher);
                return false;
            }
            foreach (var inst in insts)
                weaver.Add(inst);
            // Find all instructions which pointed to the existing and redirect them
            for (int i = 0; i < weaver.Instructions.Count; i++)
            {
                Instruction ins = weaver.Instructions[i];
                if (ins.Operand != null && ins.Operand.Equals(existing))
                {
                    // Check if the instruction lies within our injection range
                    // If it does, it's an instruction we just injected so we don't want to edit it
                    if (i < InjectionIndex || i > weaver.Pointer)
                        ins.Operand = insts[0];
                }
            }
            return true;
        }
Beispiel #15
0
        public override bool ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxideassembly, bool console)
        {
            MethodDefinition initoxidemethod = oxideassembly.MainModule.Types
                                               .Single((t) => t.FullName == "Oxide.Core.Interface")
                                               .Methods.Single((m) => m.IsStatic && m.Name == "Initialize");

            // Start injecting where requested
            weaver.Pointer = InjectionIndex;

            // Get the existing instruction we're going to inject behind
            Instruction existing;

            try
            {
                existing = weaver.Instructions[weaver.Pointer];
            }
            catch (ArgumentOutOfRangeException)
            {
                if (console == false)
                {
                    MessageBox.Show(string.Format("The injection index specified for {0} is invalid!", this.Name), "Invalid Index", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                return(false);
            }

            // Load the hook name
            Instruction firstinjected = weaver.Add(Instruction.Create(OpCodes.Call, weaver.Module.Import(initoxidemethod)));

            // Find all instructions which pointed to the existing and redirect them
            for (int i = 0; i < weaver.Instructions.Count; i++)
            {
                Instruction ins = weaver.Instructions[i];
                if (ins.Operand != null && ins.Operand.Equals(existing))
                {
                    // Check if the instruction lies within our injection range
                    // If it does, it's an instruction we just injected so we don't want to edit it
                    if (i < InjectionIndex || i > weaver.Pointer)
                    {
                        ins.Operand = firstinjected;
                    }
                }
            }
            return(true);
        }
Beispiel #16
0
        private TypeDefinition GetFieldOrProperty(ILWeaver weaver, MethodDefinition originalMethod, TypeDefinition currentArg, string[] target, Patcher patcher, bool boxed = true)
        {
            if (resolver == null)
            {
                resolver = new DefaultAssemblyResolver();
                resolver.AddSearchDirectory(patcher != null ? patcher.PatchProject.TargetDirectory : PatcherForm.MainForm.CurrentProject.TargetDirectory);
            }

            if (currentArg == null || target == null || target.Length == 0)
            {
                return(null);
            }

            int i;
            var arg = currentArg;

            for (i = 0; i < target.Length; i++)
            {
                if (GetFieldOrProperty(weaver, originalMethod, ref arg, target[i]))
                {
                    continue;
                }
                ShowMsg($"Could not find the field or property `{target[i]}` in any of the base classes or interfaces of `{currentArg.Name}`.", "Invalid field or property", patcher);
                break;
            }

            if (boxed && (arg.IsValueType || arg.IsByReference))
            {
                var type_reference = arg.Module == originalMethod.Module ? arg.Resolve() : originalMethod.Module.Import(arg.Resolve());
                weaver?.Add(Instruction.Create(OpCodes.Box, type_reference));
            }

            if (i >= 1)
            {
                return(arg);
            }
            return(null);
        }
Beispiel #17
0
        public override void ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxideassembly)
        {
            // Get the call hook method
            MethodDefinition callhookmethod = oxideassembly.MainModule.Types
                                              .Single((t) => t.FullName == "Oxide.Core.Interface")
                                              .Methods.Single((m) => m.IsStatic && m.Name == "CallHook");

            // Start injecting where requested
            weaver.Pointer = InjectionIndex;

            // Get the existing instruction we're going to inject behind
            Instruction existing = weaver.Instructions[weaver.Pointer];

            // Load the hook name
            Instruction firstinjected = weaver.Add(Instruction.Create(OpCodes.Ldstr, HookName));

            // Push the arguments array to the stack and make the call
            PushArgsArray(original, weaver);
            weaver.Add(Instruction.Create(OpCodes.Call, original.Module.Import(callhookmethod)));

            // Deal with the return value
            DealWithReturnValue(original, weaver);

            // Find all instructions which pointed to the existing and redirect them
            for (int i = 0; i < weaver.Instructions.Count; i++)
            {
                Instruction ins = weaver.Instructions[i];
                if (ins.Operand != null && ins.Operand.Equals(existing))
                {
                    // Check if the instruction lies within our injection range
                    // If it does, it's an instruction we just injected so we don't want to edit it
                    if (i < InjectionIndex || i > weaver.Pointer)
                    {
                        ins.Operand = firstinjected;
                    }
                }
            }
        }
Beispiel #18
0
        public override bool ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxideassembly, Patcher patcher = null)
        {
            MethodDefinition initoxidemethod = oxideassembly.MainModule.Types
                .Single((t) => t.FullName == "Oxide.Core.Interface")
                .Methods.Single((m) => m.IsStatic && m.Name == "Initialize");

            // Start injecting where requested
            weaver.Pointer = InjectionIndex;

            // Get the existing instruction we're going to inject behind
            Instruction existing;
            try
            {
                existing = weaver.Instructions[weaver.Pointer];
            }
            catch (ArgumentOutOfRangeException)
            {
                ShowMsg(string.Format("The injection index specified for {0} is invalid!", Name), "Invalid Index", patcher);
                return false;
            }

            // Load the hook name
            Instruction firstinjected = weaver.Add(Instruction.Create(OpCodes.Call, weaver.Module.Import(initoxidemethod)));

            // Find all instructions which pointed to the existing and redirect them
            for (int i = 0; i < weaver.Instructions.Count; i++)
            {
                Instruction ins = weaver.Instructions[i];
                if (ins.Operand != null && ins.Operand.Equals(existing))
                {
                    // Check if the instruction lies within our injection range
                    // If it does, it's an instruction we just injected so we don't want to edit it
                    if (i < InjectionIndex || i > weaver.Pointer)
                        ins.Operand = firstinjected;
                }
            }
            return true;
        }
Beispiel #19
0
        /// <summary>
        /// Performs the patch process
        /// </summary>
        public void Patch(bool console)
        {
            // Load oxide assembly
            string oxidefilename = Path.Combine(System.Windows.Forms.Application.StartupPath, "Oxide.Core.dll");
            if (!File.Exists(oxidefilename)) throw new FileNotFoundException(string.Format("Failed to locate Oxide.dll assembly"));
            AssemblyDefinition oxideassembly = AssemblyDefinition.ReadAssembly(oxidefilename);
            if (PatchProject == null)
            {
                return;
            }
            // CReate reader params
            ReaderParameters readerparams = new ReaderParameters();
            readerparams.AssemblyResolver = new AssemblyResolver { TargetDirectory = PatchProject.TargetDirectory };
            DateTime now = DateTime.Now;
            WriteToLog("----------------------------------------");
            WriteToLog(now.ToShortDateString() + " " + now.ToString("hh:mm:ss tt zzz"));
            WriteToLog("----------------------------------------");
            // Loop each manifest
            foreach (var manifest in PatchProject.Manifests)
            {
                // Get the assembly filename
                string filename;
                if (!console)
                {
                    filename = GetAssemblyFilename(manifest.AssemblyName, true);
                    if (!File.Exists(filename))
                    {
                        WriteToLog(string.Format("Failed to locate target assembly {0}", manifest.AssemblyName));
                        throw new FileNotFoundException(string.Format("Failed to locate target assembly {0}", manifest.AssemblyName), filename);
                    }
                }
                else
                {
                    filename = GetAssemblyFilename(manifest.AssemblyName, true);
                    if (!File.Exists(filename))
                    {
                        filename = GetAssemblyFilename(manifest.AssemblyName, false);
                        if (!File.Exists(filename))
                        {
                            WriteToLog(string.Format("Failed to locate target assembly {0}", manifest.AssemblyName));
                            throw new FileNotFoundException(string.Format("Failed to locate target assembly {0}", manifest.AssemblyName), filename);
                        }
                        else
                        {
                            System.IO.File.Copy(filename, Path.GetFileNameWithoutExtension(filename) + "_Original" + Path.GetExtension(filename), true);
                            filename = Path.GetFileNameWithoutExtension(filename) + "_Original" + Path.GetExtension(filename);
                        }
                    }
                }

                // Load it
                if (console)
                {
                    Console.WriteLine(string.Format("Loading assembly {0}", manifest.AssemblyName));
                }
                else
                {
                    Log("Loading assembly {0}", manifest.AssemblyName);
                }
                WriteToLog(string.Format("Loading assembly {0}", manifest.AssemblyName));
                AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(filename, readerparams);

                var baseHooks = (from hook in manifest.Hooks where hook.BaseHook != null select hook.BaseHook).ToList();

                // Loop each hook
                foreach (var hook in manifest.Hooks)
                {
                    if (baseHooks.Contains(hook)) continue;
                    // Check if it's flagged
                    if (hook.Flagged)
                    {
                        // Log
                        if (console)
                        {
                            Console.WriteLine(string.Format("Ignored hook {0} as it is flagged", hook.Name));
                        }
                        else
                        {
                            Log("Ignored hook {0} as it is flagged", hook.Name);
                        }
                        WriteToLog(string.Format("Ignored hook {0} as it is flagged", hook.Name));
                    }
                    else
                    {
                        // Locate the method
                        MethodDefinition method;
                        try
                        {
                            var type = assembly.Modules
                                .SelectMany((m) => m.GetTypes())
                                .Single((t) => t.FullName == hook.TypeName);

                            method = type.Methods
                                .Single((m) => Utility.GetMethodSignature(m).Equals(hook.Signature));
                        }
                        catch (Exception)
                        {
                            WriteToLog(string.Format("Failed to locate method {0}::{1} in assembly {2}", hook.TypeName, hook.Signature.Name, manifest.AssemblyName));
                            throw new Exception(string.Format("Failed to locate method {0}::{1} in assembly {2}", hook.TypeName, hook.Signature.Name, manifest.AssemblyName));
                        }

                        // Let the hook do it's work
                        var weaver = new ILWeaver(method.Body) {Module = method.Module};
                        try
                        {
                            // Apply
                            bool patchApplied = hook.PreparePatch(method, weaver, oxideassembly, console) && hook.ApplyPatch(method, weaver, oxideassembly, console);
                            if (patchApplied)
                            {
                                weaver.Apply(method.Body);
                            }
                            else
                            {
                                if (console)
                                {
                                    Console.WriteLine(string.Format("The injection index specified for {0} is invalid!", hook.Name));
                                }
                                WriteToLog(string.Format("The injection index specified for {0} is invalid!", hook.Name));
                                hook.Flagged = true;
                            }

                            // Log
                            if (console)
                            {
                                if (patchApplied)
                                {
                                    Console.WriteLine(string.Format("Applied hook {0} to {1}::{2}", hook.Name, hook.TypeName, hook.Signature.Name));
                                    WriteToLog(string.Format("Applied hook {0} to {1}::{2}", hook.Name, hook.TypeName, hook.Signature.Name));
                                }
                                else
                                {
                                    Console.WriteLine(string.Format("Failed to apply hook {0}", hook.Name));
                                    WriteToLog(string.Format("Failed to apply hook {0}", hook.Name));
                                }
                            }
                            else
                            {
                                if (patchApplied)
                                {
                                    Log("Applied hook {0} to {1}::{2}", hook.Name, hook.TypeName, hook.Signature.Name);
                                    WriteToLog(string.Format("Applied hook {0} to {1}::{2}", hook.Name, hook.TypeName, hook.Signature.Name));
                                }
                                else
                                {
                                    Log("Failed to apply hook {0}", hook.Name);
                                    WriteToLog(string.Format("Failed to apply hook {0}", hook.Name));
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (console)
                            {
                                Console.WriteLine(string.Format("Failed to apply hook {0}", hook.Name));
                                Console.WriteLine(ex.ToString());
                            }
                            else
                            {
                                Log("Failed to apply hook {0}", hook.Name);
                                Log("{0}", ex.ToString());
                            }
                            WriteToLog(string.Format("Failed to apply hook {0}", hook.Name));
                            WriteToLog(ex.ToString());
                        }
                    }
                }

                // Save it
                if (console)
                {
                    Console.WriteLine(string.Format("Saving assembly {0}", manifest.AssemblyName));
                }
                else
                {
                    Log("Saving assembly {0}", manifest.AssemblyName);
                }
                WriteToLog(string.Format("Saving assembly {0}", manifest.AssemblyName));
                filename = GetAssemblyFilename(manifest.AssemblyName, false);
                assembly.Write(filename);
            }
        }
Beispiel #20
0
        private Instruction PushArgsArray(MethodDefinition method, ILWeaver weaver, out VariableDefinition argsvar)
        {
            // Are we going to use arguments?
            if (ArgumentBehavior == Hooks.ArgumentBehavior.None)
            {
                // Push null and we're done
                argsvar = null;
                return null;
            }

            // Create array variable
            Instruction firstInstruction;
            // Are we using the argument string?
            if (ArgumentBehavior == Hooks.ArgumentBehavior.UseArgumentString)
            {
                string retvalue;
                string[] args = ParseArgumentString(out retvalue);
                if (args == null)
                {
                    // Silently fail, but at least produce valid IL
                    argsvar = null;
                    return null;
                }

                // Create the array
                argsvar = weaver.AddVariable(new ArrayType(method.Module.TypeSystem.Object), "args");
                firstInstruction = weaver.Add(ILWeaver.Ldc_I4_n(args.Length));
                weaver.Add(Instruction.Create(OpCodes.Newarr, method.Module.TypeSystem.Object));
                weaver.Stloc(argsvar);

                // Populate it
                for (int i = 0; i < args.Length; i++)
                {
                    weaver.Ldloc(argsvar);
                    string arg = args[i].ToLowerInvariant();
                    weaver.Add(ILWeaver.Ldc_I4_n(i));
                    if (string.IsNullOrEmpty(arg))
                        weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    else if (arg == "this")
                    {
                        if (method.IsStatic)
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        else
                            weaver.Add(ILWeaver.Ldarg(null));
                    }
                    else if (arg[0] == 'p' || arg[0] == 'a')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            ParameterDefinition pdef;

                            /*if (method.IsStatic)
                                pdef = method.Parameters[index];
                            else
                                pdef = method.Parameters[index + 1];*/
                            pdef = method.Parameters[index];

                            weaver.Add(ILWeaver.Ldarg(pdef));
                            if (pdef.ParameterType.IsByReference)
                            {
                                weaver.Add(Instruction.Create(OpCodes.Ldobj, pdef.ParameterType));
                                weaver.Add(Instruction.Create(OpCodes.Box, pdef.ParameterType));
                            }
                            else if (pdef.ParameterType.IsValueType)
                                weaver.Add(Instruction.Create(OpCodes.Box, pdef.ParameterType));
                        }
                        else
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    }
                    else if (arg[0] == 'l' || arg[0] == 'v')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            VariableDefinition vdef = weaver.Variables[index];
                            weaver.Ldloc(vdef);

                            if (vdef.VariableType.IsByReference)
                            {
                                weaver.Add(Instruction.Create(OpCodes.Ldobj, vdef.VariableType));
                                weaver.Add(Instruction.Create(OpCodes.Box, vdef.VariableType));
                            }
                            else if (vdef.VariableType.IsValueType)
                                weaver.Add(Instruction.Create(OpCodes.Box, vdef.VariableType));
                        }
                        else
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    }
                    else
                        weaver.Add(Instruction.Create(OpCodes.Ldnull));

                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }
            }
            else
            {
                // Figure out what we're doing
                bool includeargs = ArgumentBehavior == Hooks.ArgumentBehavior.All || ArgumentBehavior == Hooks.ArgumentBehavior.JustParams;
                bool includethis = ArgumentBehavior == Hooks.ArgumentBehavior.All || ArgumentBehavior == Hooks.ArgumentBehavior.JustThis;
                if (method.IsStatic) includethis = false;

                // Work out what arguments we're going to transmit
                List<ParameterDefinition> args = new List<ParameterDefinition>();
                if (includeargs)
                {
                    for (int i = 0; i < method.Parameters.Count; i++)
                    {
                        ParameterDefinition arg = method.Parameters[i];
                        if (!arg.IsOut)
                            args.Add(arg);
                    }
                }

                argsvar = weaver.AddVariable(new ArrayType(method.Module.TypeSystem.Object), "args");

                // Load arg count, create array, store
                if (includethis)
                    firstInstruction = weaver.Add(ILWeaver.Ldc_I4_n(args.Count + 1));
                else
                    firstInstruction = weaver.Add(ILWeaver.Ldc_I4_n(args.Count));
                weaver.Add(Instruction.Create(OpCodes.Newarr, method.Module.TypeSystem.Object));
                weaver.Stloc(argsvar);

                // Include this
                if (includethis)
                {
                    weaver.Ldloc(argsvar);
                    weaver.Add(ILWeaver.Ldc_I4_n(0));
                    weaver.Add(ILWeaver.Ldarg(null));
                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }

                // Loop each argument
                for (int i = 0; i < args.Count; i++)
                {
                    // Load array, load index load arg, store in array
                    ParameterDefinition arg = args[i];
                    weaver.Ldloc(argsvar);
                    if (includethis)
                        weaver.Add(ILWeaver.Ldc_I4_n(i + 1));
                    else
                        weaver.Add(ILWeaver.Ldc_I4_n(i));
                    weaver.Add(ILWeaver.Ldarg(args[i]));
                    if (arg.ParameterType.IsByReference)
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldobj, arg.ParameterType));
                        weaver.Add(Instruction.Create(OpCodes.Box, arg.ParameterType));
                    }
                    else if (arg.ParameterType.IsValueType)
                        weaver.Add(Instruction.Create(OpCodes.Box, arg.ParameterType));
                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }
            }
            return firstInstruction;
        }
Beispiel #21
0
 /// <summary>
 /// Patches this hook into the target weaver
 /// </summary>
 /// <param name="weaver"></param>
 /// <param name="oxidemodule"></param>
 /// <param name="original"></param>
 /// <param name="console"></param>
 public abstract bool ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxidemodule, bool console);
Beispiel #22
0
        private bool GetFieldOrProperty(ILWeaver weaver, MethodDefinition originalMethod, TypeDefinition currentArg, string[] target, Patcher patcher)
        {
            if (resolver == null)
            {
                resolver = new DefaultAssemblyResolver();
                resolver.AddSearchDirectory(patcher != null ? patcher.PatchProject.TargetDirectory : PatcherForm.MainForm.CurrentProject.TargetDirectory);
            }

            if (currentArg == null || target == null || target.Length == 0) return false;

            int i;
            var arg = currentArg;
            for (i = 0; i < target.Length; i++)
            {
                if (GetFieldOrProperty(weaver, originalMethod, ref arg, target[i])) continue;
                ShowMsg($"Could not find the field or property `{target[i]}` in any of the base classes or interfaces of `{currentArg.Name}`.", "Invalid field or property", patcher);
                break;
            }

            if (arg.IsValueType || arg.IsByReference)
                weaver.Add(arg.Module == originalMethod.Module
                    ? Instruction.Create(OpCodes.Box, arg.Resolve())
                    : Instruction.Create(OpCodes.Box, originalMethod.Module.Import(arg.Resolve())));

            return i >= 1;
        }
Beispiel #23
0
        private VariableDefinition LoadDispatchArgs(MethodDefinition method, ILWeaver weaver, Patcher patcher, out Instruction first_instruction)
        {
            // Are we going to use arguments?
            if (ArgumentBehavior == ArgumentBehavior.None)
            {
                first_instruction = null;
                return(null);
            }

            VariableDefinition ret_var = null;

            // Are we using the argument string?
            if (ArgumentBehavior == ArgumentBehavior.UseArgumentString)
            {
                string   retvalue;
                string[] args = ParseArgumentString(out retvalue);
                if (args == null)
                {
                    // Silently fail, but at least produce valid IL
                    first_instruction = null;
                    return(null);
                }

                ret_var = weaver.AddVariable(method.Module.Import(method.ReturnType), "return_value");

                // Load the ret local variable by reference onto the stack first
                first_instruction = weaver.Ldloc(ret_var);
                weaver.Add(Instruction.Create(OpCodes.Ldobj, ret_var.VariableType));

                // Load all arguments on the stack
                for (int i = 0; i < args.Length; i++)
                {
                    var arg    = args[i];
                    var target = ParseTargetString(ref arg);

                    if (string.IsNullOrEmpty(arg))
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    }
                    else if (arg == "this")
                    {
                        if (method.IsStatic)
                        {
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        }
                        else
                        {
                            weaver.Add(ILWeaver.Ldarg(null));
                        }

                        GetFieldOrProperty(weaver, method, method.DeclaringType.Resolve(), target, patcher);
                    }
                    else if (arg[0] == 'p' || arg[0] == 'a')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            ParameterDefinition pdef;

                            /*if (method.IsStatic)
                             *  pdef = method.Parameters[index];
                             * else
                             *  pdef = method.Parameters[index + 1];*/
                            pdef = method.Parameters[index];

                            weaver.Add(ILWeaver.Ldarg(pdef));
                            if (pdef.ParameterType.IsByReference)
                            {
                                weaver.Add(Instruction.Create(OpCodes.Ldobj, pdef.ParameterType));
                                //weaver.Add(Instruction.Create(OpCodes.Box, pdef.ParameterType));
                            }

                            GetFieldOrProperty(weaver, method, pdef.ParameterType.Resolve(), target, patcher);
                        }
                        else
                        {
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        }
                    }
                    else if (arg[0] == 'l' || arg[0] == 'v')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            VariableDefinition vdef = weaver.Variables[index];
                            weaver.Ldloc(vdef);

                            if (vdef.VariableType.IsByReference)
                            {
                                weaver.Add(Instruction.Create(OpCodes.Ldobj, vdef.VariableType));
                                //weaver.Add(Instruction.Create(OpCodes.Box, vdef.VariableType));
                            }

                            GetFieldOrProperty(weaver, method, vdef.VariableType.Resolve(), target, patcher);
                        }
                        else
                        {
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        }
                    }
                    else
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    }
                }
            }
            else
            {
                ret_var = weaver.AddVariable(method.Module.Import(method.ReturnType), "return_value");

                // Load the ret local variable by reference onto the stack first
                first_instruction = weaver.Ldloc(ret_var);
                weaver.Add(Instruction.Create(OpCodes.Ldobj, ret_var.VariableType));

                // Figure out what we're doing
                var has_params = ArgumentBehavior == ArgumentBehavior.All || ArgumentBehavior == ArgumentBehavior.JustParams;
                var has_this   = ArgumentBehavior == ArgumentBehavior.All || ArgumentBehavior == ArgumentBehavior.JustThis;
                if (method.IsStatic)
                {
                    has_this = false;
                }

                // Work out what arguments we're going to include
                var parameters = new List <ParameterDefinition>();
                if (has_params)
                {
                    for (int i = 0; i < method.Parameters.Count; i++)
                    {
                        var parameter = method.Parameters[i];
                        if (!parameter.IsOut)
                        {
                            parameters.Add(parameter);
                        }
                    }
                }

                if (has_this)
                {
                    first_instruction = weaver.Add(ILWeaver.Ldarg(null));
                }

                foreach (var arg in parameters)
                {
                    var instruction = weaver.Add(ILWeaver.Ldarg(arg));
                    if (first_instruction == null)
                    {
                        first_instruction = instruction;
                    }
                    if (arg.ParameterType.IsByReference)
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldobj, arg.ParameterType));
                        //if (arg.ParameterType.Full?Name == "System.Object") weaver.Add(Instruction.Create(OpCodes.Box, arg.ParameterType));
                    }
                }
            }

            return(ret_var);
        }
Beispiel #24
0
        public override bool ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxideassembly, Patcher patcher = null)
        {
            // Get the call hook method
            MethodDefinition callhookmethod = oxideassembly.MainModule.Types
                                              .Single((t) => t.FullName == "Oxide.Core.Interface")
                                              .Methods.Single((m) => m.IsStatic && m.Name == "CallHook");

            // Start injecting where requested
            weaver.Pointer = InjectionIndex;

            // Get the existing instruction we're going to inject behind
            Instruction existing;

            try
            {
                existing = weaver.Instructions[weaver.Pointer];
            }
            catch (ArgumentOutOfRangeException)
            {
                ShowMsg(string.Format("The injection index specified for {0} is invalid!", Name), "Invalid Index", patcher);
                return(false);
            }

            // Load the hook name

            // Push the arguments array to the stack and make the call
            VariableDefinition argsvar;
            var firstinjected = PushArgsArray(original, weaver, out argsvar, patcher);
            var hookname      = weaver.Add(Instruction.Create(OpCodes.Ldstr, HookName));

            if (firstinjected == null)
            {
                firstinjected = hookname;
            }
            if (argsvar != null)
            {
                weaver.Ldloc(argsvar);
            }
            else
            {
                weaver.Add(Instruction.Create(OpCodes.Ldnull));
            }
            weaver.Add(Instruction.Create(OpCodes.Call, original.Module.Import(callhookmethod)));

            // Deal with the return value
            DealWithReturnValue(original, argsvar, weaver);

            // Find all instructions which pointed to the existing and redirect them
            for (int i = 0; i < weaver.Instructions.Count; i++)
            {
                Instruction ins = weaver.Instructions[i];
                if (ins.Operand != null && ins.Operand.Equals(existing))
                {
                    // Check if the instruction lies within our injection range
                    // If it does, it's an instruction we just injected so we don't want to edit it
                    if (i < InjectionIndex || i > weaver.Pointer)
                    {
                        ins.Operand = firstinjected;
                    }
                }
            }
            return(true);
        }
Beispiel #25
0
        private bool GetFieldOrProperty(ILWeaver weaver, MethodDefinition originalMethod, ref TypeDefinition currentArg, string target, Patcher patcher)
        {
            if (currentArg == null || string.IsNullOrEmpty(target))
            {
                return(false);
            }

            while (currentArg != null)
            {
                if (currentArg.IsClass)
                {
                    if (currentArg.HasFields)
                    {
                        foreach (var field in currentArg.Fields)
                        {
                            if (!string.Equals(field.Name, target, StringComparison.CurrentCultureIgnoreCase))
                            {
                                continue;
                            }

                            weaver.Add(field.Module == originalMethod.Module
                                ? Instruction.Create(OpCodes.Ldfld, field)
                                : Instruction.Create(OpCodes.Ldfld, originalMethod.Module.Import(field)));
                            currentArg = field.FieldType.Resolve();

                            return(true);
                        }
                    }
                }

                if (currentArg.HasProperties)
                {
                    foreach (var property in currentArg.Properties)
                    {
                        if (!string.Equals(property.Name, target, StringComparison.CurrentCultureIgnoreCase))
                        {
                            continue;
                        }

                        weaver.Add(property.GetMethod.Module == originalMethod.Module
                            ? Instruction.Create(OpCodes.Callvirt, property.GetMethod)
                            : Instruction.Create(OpCodes.Callvirt, originalMethod.Module.Import(property.GetMethod)));
                        currentArg = property.PropertyType.Resolve();

                        return(true);
                    }
                }

                if (currentArg.HasInterfaces)
                {
                    foreach (var intf in currentArg.Interfaces)
                    {
                        var previousArg = currentArg;
                        currentArg = intf.Resolve();
                        if (GetFieldOrProperty(weaver, originalMethod, ref currentArg, target, patcher))
                        {
                            return(true);
                        }
                        currentArg = previousArg;
                    }
                }

                if (currentArg.BaseType != null && originalMethod.Module.Assembly != currentArg.BaseType.Module.Assembly)
                {
                    var baseType         = currentArg.BaseType;
                    var baseTypeAssembly = AssemblyDefinition.ReadAssembly($"{(patcher != null ? patcher.PatchProject.TargetDirectory : PatcherForm.MainForm.CurrentProject.TargetDirectory)}\\{baseType.Scope.Name}{(baseType.Scope.Name.EndsWith(".dll") ? "" : ".dll")}");
                    currentArg = baseTypeAssembly.MainModule.Types.Single(x => x.FullName == baseType.FullName);
                }
                else
                {
                    currentArg = currentArg.BaseType?.Resolve();
                }
            }

            return(false);
        }
        private async void applybutton_Click(object sender, EventArgs e)
        {
            if (nametextbox.TextLength < 3)
            {
                MessageBox.Show(MainForm, "Name is too short!", "Oxide Patcher", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (hooknametextbox.TextLength < 3)
            {
                MessageBox.Show(MainForm, "Hook name is too short!", "Oxide Patcher", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            Hook.Name = nametextbox.Text;
            Hook.HookName = hooknametextbox.Text;

            MainForm.UpdateHook(Hook, false);

            if (msilbefore != null && msilafter != null)
            {
                var weaver = new ILWeaver(methoddef.Body) {Module = methoddef.Module};

                Hook.PreparePatch(methoddef, weaver, MainForm.OxideAssembly);
                msilbefore.Text = weaver.ToString();
                codebefore.Text = await Decompiler.GetSourceCode(methoddef, weaver);

                Hook.ApplyPatch(methoddef, weaver, MainForm.OxideAssembly);
                msilafter.Text = weaver.ToString();
                codeafter.Text = await Decompiler.GetSourceCode(methoddef, weaver);
            }

            applybutton.Enabled = false;
        }
Beispiel #27
0
        private Instruction PushArgsArray(MethodDefinition method, ILWeaver weaver, out VariableDefinition argsvar, Patcher patcher)
        {
            // Are we going to use arguments?
            if (ArgumentBehavior == Hooks.ArgumentBehavior.None)
            {
                // Push null and we're done
                argsvar = null;
                return(null);
            }

            // Create array variable
            Instruction firstInstruction;

            // Are we using the argument string?
            if (ArgumentBehavior == Hooks.ArgumentBehavior.UseArgumentString)
            {
                string   retvalue;
                string[] args = ParseArgumentString(out retvalue);
                if (args == null)
                {
                    // Silently fail, but at least produce valid IL
                    argsvar = null;
                    return(null);
                }

                // Create the array
                argsvar          = weaver.AddVariable(new ArrayType(method.Module.TypeSystem.Object), "args");
                firstInstruction = weaver.Add(ILWeaver.Ldc_I4_n(args.Length));
                weaver.Add(Instruction.Create(OpCodes.Newarr, method.Module.TypeSystem.Object));
                weaver.Stloc(argsvar);

                // Populate it
                for (int i = 0; i < args.Length; i++)
                {
                    string   arg    = args[i].ToLowerInvariant();
                    string[] target = null;
                    if (!string.IsNullOrEmpty(arg) && args[i].Contains("."))
                    {
                        string[] split = args[i].Split('.');
                        arg    = split[0];
                        target = split.Skip(1).ToArray();
                    }

                    weaver.Ldloc(argsvar);
                    weaver.Add(ILWeaver.Ldc_I4_n(i));
                    if (string.IsNullOrEmpty(arg))
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    }
                    else if (arg == "this")
                    {
                        if (method.IsStatic)
                        {
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        }
                        else
                        {
                            weaver.Add(ILWeaver.Ldarg(null));
                        }

                        GetFieldOrProperty(weaver, method, method.DeclaringType.Resolve(), target, patcher);
                    }
                    else if (arg[0] == 'p' || arg[0] == 'a')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            ParameterDefinition pdef;

                            /*if (method.IsStatic)
                             *  pdef = method.Parameters[index];
                             * else
                             *  pdef = method.Parameters[index + 1];*/
                            if (index < method.Parameters.Count)
                            {
                                pdef = method.Parameters[index];

                                weaver.Add(ILWeaver.Ldarg(pdef));
                                if (pdef.ParameterType.IsByReference)
                                {
                                    weaver.Add(Instruction.Create(OpCodes.Ldobj, pdef.ParameterType));
                                    weaver.Add(Instruction.Create(OpCodes.Box, pdef.ParameterType));
                                }

                                if (
                                    !GetFieldOrProperty(weaver, method, pdef.ParameterType.Resolve(), target, patcher) &&
                                    pdef.ParameterType.IsValueType)
                                {
                                    weaver.Add(Instruction.Create(OpCodes.Box, pdef.ParameterType));
                                }
                            }
                            else
                            {
                                ShowMsg($"Invalid argument `{arg}` supplied for {HookName}", "Invalid argument supplied", patcher);
                            }
                        }
                        else
                        {
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        }
                    }
                    else if (arg[0] == 'l' || arg[0] == 'v')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            if (index < method.Body.Variables.Count)
                            {
                                VariableDefinition vdef = weaver.Variables[index];

                                weaver.Ldloc(vdef);
                                if (vdef.VariableType.IsByReference)
                                {
                                    weaver.Add(Instruction.Create(OpCodes.Ldobj, vdef.VariableType));
                                    weaver.Add(Instruction.Create(OpCodes.Box, vdef.VariableType));
                                }

                                if (!GetFieldOrProperty(weaver, method, vdef.VariableType.Resolve(), target, patcher) && vdef.VariableType.IsValueType)
                                {
                                    weaver.Add(Instruction.Create(OpCodes.Box, vdef.VariableType));
                                }
                            }
                            else
                            {
                                ShowMsg($"Invalid variable `{arg}` supplied for {HookName}", "Invalid variable supplied", patcher);
                            }
                        }
                        else
                        {
                            weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        }
                    }
                    else
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    }

                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }
            }
            else
            {
                // Figure out what we're doing
                bool includeargs = ArgumentBehavior == Hooks.ArgumentBehavior.All || ArgumentBehavior == Hooks.ArgumentBehavior.JustParams;
                bool includethis = ArgumentBehavior == Hooks.ArgumentBehavior.All || ArgumentBehavior == Hooks.ArgumentBehavior.JustThis;
                if (method.IsStatic)
                {
                    includethis = false;
                }

                // Work out what arguments we're going to transmit
                List <ParameterDefinition> args = new List <ParameterDefinition>();
                if (includeargs)
                {
                    for (int i = 0; i < method.Parameters.Count; i++)
                    {
                        ParameterDefinition arg = method.Parameters[i];
                        if (!arg.IsOut)
                        {
                            args.Add(arg);
                        }
                    }
                }

                argsvar = weaver.AddVariable(new ArrayType(method.Module.TypeSystem.Object), "args");

                // Load arg count, create array, store
                if (includethis)
                {
                    firstInstruction = weaver.Add(ILWeaver.Ldc_I4_n(args.Count + 1));
                }
                else
                {
                    firstInstruction = weaver.Add(ILWeaver.Ldc_I4_n(args.Count));
                }
                weaver.Add(Instruction.Create(OpCodes.Newarr, method.Module.TypeSystem.Object));
                weaver.Stloc(argsvar);

                // Include this
                if (includethis)
                {
                    weaver.Ldloc(argsvar);
                    weaver.Add(ILWeaver.Ldc_I4_n(0));
                    weaver.Add(ILWeaver.Ldarg(null));
                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }

                // Loop each argument
                for (int i = 0; i < args.Count; i++)
                {
                    // Load array, load index load arg, store in array
                    ParameterDefinition arg = args[i];
                    weaver.Ldloc(argsvar);
                    if (includethis)
                    {
                        weaver.Add(ILWeaver.Ldc_I4_n(i + 1));
                    }
                    else
                    {
                        weaver.Add(ILWeaver.Ldc_I4_n(i));
                    }
                    weaver.Add(ILWeaver.Ldarg(args[i]));
                    if (arg.ParameterType.IsByReference)
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldobj, arg.ParameterType));
                        weaver.Add(Instruction.Create(OpCodes.Box, arg.ParameterType));
                    }
                    else if (arg.ParameterType.IsValueType)
                    {
                        weaver.Add(Instruction.Create(OpCodes.Box, arg.ParameterType));
                    }
                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }
            }
            return(firstInstruction);
        }
Beispiel #28
0
        private bool GetFieldOrProperty(ILWeaver weaver, MethodDefinition originalMethod, ref TypeDefinition currentArg, string target)
        {
            if (currentArg == null || string.IsNullOrEmpty(target))
            {
                return(false);
            }

            while (currentArg != null)
            {
                if (currentArg.IsClass)
                {
                    if (currentArg.HasFields)
                    {
                        foreach (var field in currentArg.Fields)
                        {
                            if (!string.Equals(field.Name, target, StringComparison.CurrentCultureIgnoreCase))
                            {
                                continue;
                            }

                            weaver?.Add(field.Module == originalMethod.Module
                                ? Instruction.Create(OpCodes.Ldfld, field)
                                : Instruction.Create(OpCodes.Ldfld, originalMethod.Module.Import(field)));
                            currentArg = field.FieldType.Resolve();

                            return(true);
                        }
                    }
                }

                if (currentArg.HasProperties)
                {
                    foreach (var property in currentArg.Properties)
                    {
                        if (!string.Equals(property.Name, target, StringComparison.CurrentCultureIgnoreCase))
                        {
                            continue;
                        }

                        weaver?.Add(property.GetMethod.Module == originalMethod.Module
                            ? Instruction.Create(OpCodes.Callvirt, property.GetMethod)
                            : Instruction.Create(OpCodes.Callvirt, originalMethod.Module.Import(property.GetMethod)));
                        currentArg = property.PropertyType.Resolve();

                        return(true);
                    }
                }

                if (currentArg.HasInterfaces)
                {
                    foreach (var intf in currentArg.Interfaces)
                    {
                        var previousArg = currentArg;
                        currentArg = intf.Resolve();
                        if (GetFieldOrProperty(weaver, originalMethod, ref currentArg, target))
                        {
                            return(true);
                        }
                        currentArg = previousArg;
                    }
                }

                currentArg = currentArg.BaseType?.Resolve();
            }

            return(false);
        }
Beispiel #29
0
        /// <summary>
        /// Attempts to deobfuscate the specified type
        /// </summary>
        /// <param name="typedef"></param>
        protected virtual void DeobfuscateType(TypeDefinition typedef)
        {
            // Deal with method parameters
            foreach (MethodDefinition method in typedef.Methods
                     .Where(m => m.HasParameters)
                     )
            {
                for (int i = 0; i < method.Parameters.Count; i++)
                {
                    ParameterDefinition paramdef = method.Parameters[i];
                    if (IdentifyObfuscatedName(paramdef.Name))
                    {
                        string name = $"arg{i}";
                        paramdef.Name = name;
                    }
                }
            }

            // Deal with field names
            FieldDefinition[] fields = typedef.Fields
                                       .Where(f => IdentifyObfuscatedName(f.Name))
                                       .ToArray();
            Array.Sort(fields, (a, b) =>
            {
                // Sort firstly by type
                // Then sort by offset
                // Finally, sort by obfuscated name
                int tmp = Comparer <string> .Default.Compare(a.FieldType.FullName, b.FieldType.FullName);
                if (tmp != 0)
                {
                    return(tmp);
                }

                tmp = Comparer <int> .Default.Compare(a.Offset, b.Offset);
                if (tmp != 0)
                {
                    return(tmp);
                }

                return(Comparer <string> .Default.Compare(a.Name, b.Name));
            });
            for (int i = 0; i < fields.Length; i++)
            {
                FieldDefinition field = fields[i];
                string          name;
                if (field.IsPublic)
                {
                    name = $"Field{i + 1}";
                }
                else
                {
                    name = $"field{i + 1}";
                }

                field.Name = name;
            }

            // Deal with property names
            PropertyDefinition[] properties = typedef.Properties
                                              .Where(f => IdentifyObfuscatedName(f.Name))
                                              .ToArray();
            Array.Sort(properties, (a, b) =>
            {
                // Sort firstly by type, then by obfuscated name
                int tmp = Comparer <string> .Default.Compare(a.PropertyType.FullName, b.PropertyType.FullName);
                if (tmp != 0)
                {
                    return(tmp);
                }

                return(Comparer <string> .Default.Compare(a.Name, b.Name));
            });
            for (int i = 0; i < properties.Length; i++)
            {
                PropertyDefinition property = properties[i];
                string             name     = $"property{i + 1}";
                // NOTE: Do we need to rename the get and set methods too?
                property.Name = name;
            }

            // Deal with method names
            MethodDefinition[] methods = typedef.Methods
                                         .Where(f => IdentifyObfuscatedName(f.Name))
                                         .ToArray();
            Array.Sort(methods, (a, b) =>
            {
                // Sort by the following in order: return type, parameter count, parameter types, obfuscated name
                int tmp = Comparer <string> .Default.Compare(a.ReturnType.FullName, b.ReturnType.FullName);
                if (tmp != 0)
                {
                    return(tmp);
                }

                tmp = Comparer <int> .Default.Compare(a.Parameters.Count, b.Parameters.Count);
                if (tmp != 0)
                {
                    return(tmp);
                }
                // TODO: Sort by parameter types
                return(Comparer <string> .Default.Compare(a.Name, b.Name));
            });
            for (int i = 0; i < methods.Length; i++)
            {
                MethodDefinition method = methods[i];
                string           name;
                if (method.IsPublic)
                {
                    name = $"Method{i + 1}";
                }
                else
                {
                    name = $"method{i + 1}";
                }

                method.Name = name;
            }

            // Deal with proxy methods
            HashSet <MethodDefinition> toremove = new HashSet <MethodDefinition>();

            foreach (MethodDefinition method in typedef.Methods
                     .Where(m => m.HasBody)
                     )
            {
                // Identify a proxy call via IL
                Collection <Instruction> instructions = method.Body.Instructions;
                if (instructions.Count != 3)
                {
                    continue;
                }

                if (instructions[0].OpCode.Code != Code.Ldarg_0)
                {
                    continue;
                }

                if (instructions[1].OpCode.Code != Code.Callvirt)
                {
                    continue;
                }

                if (instructions[2].OpCode.Code != Code.Ret)
                {
                    continue;
                }

                // Check that it's calling an obfuscated method in our type
                MethodReference proxymethod = instructions[1].Operand as MethodReference;
                if (proxymethod.DeclaringType.FullName != typedef.FullName)
                {
                    continue;
                }

                if (!methods.Any(m => m.FullName == proxymethod.FullName))
                {
                    continue;
                }

                // Check that the target method is not referenced by anything else
                if (!refcounts.TryGetValue(proxymethod, out int refcount))
                {
                    refcount = 0;
                }

                if (refcount > 1)
                {
                    continue;
                }

                // Resolve it
                MethodDefinition proxymethoddef = proxymethod.Resolve();
                if (!proxymethoddef.HasBody)
                {
                    continue;
                }

                // It passed, collapse the proxy method's IL into this method and remove it
                ILWeaver weaver = new ILWeaver(proxymethoddef.Body);
                weaver.Apply(method.Body);
                toremove.Add(proxymethoddef);
            }

            // Remove any proxy methods
            foreach (MethodDefinition method in toremove)
            {
                typedef.Methods.Remove(method);
            }
        }
Beispiel #30
0
        /// <summary>
        /// Weave event invoke
        /// </summary>
        /// <param name="il">IL Generator</param>
        /// <param name="method">Method</param>
        /// <param name="field">Field</param>
        private void BlockInvokeEvent(Mono.Cecil.Cil.ILProcessor il, Mono.Cecil.MethodDefinition method, Mono.Cecil.FieldDefinition field)
        {
            var isStatic        = method.IsStatic;
            var eventContext    = il.DeclareLocal(typeof(EventContext));
            var locals          = new List <Mono.Cecil.Cil.VariableDefinition>();
            var objLocal        = il.DeclareLocal(typeof(object[]));
            var parameters      = method.Parameters;
            var parameterLength = parameters.Count;

            var fieldDeclaringType = field.DeclaringType;
            var aspect             = field.GetCustomAttribute <EventInterceptionAspect>() ?? fieldDeclaringType.GetCustomAttribute <EventInterceptionAspect>()
                                     ?? fieldDeclaringType.Module.Assembly.GetCustomAttribute <EventInterceptionAspect>();

            if (!ILWeaver.IsValidAspectFor(field, aspect, allowEvents: true))
            {
                return;
            }

            var aspectField = ILWeaver.TypeFieldAspects[fieldDeclaringType.FullName][aspect.GetType().FullName];

            il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, parameterLength);
            il.Emit(Mono.Cecil.Cil.OpCodes.Newarr, typeof(object));
            il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, objLocal);

            for (var i = 0; i < parameterLength; i++)
            {
                var parameter     = parameters[i];
                var parameterType = parameter.ParameterType;
                var local         = il.DeclareLocal(parameterType);

                il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, local);
                il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, objLocal);
                il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, parameterLength - i - 1);
                il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, local);
                if (parameterType.IsValueType)
                {
                    il.Emit(Mono.Cecil.Cil.OpCodes.Box, parameterType);
                }
                il.Emit(Mono.Cecil.Cil.OpCodes.Stelem_Ref);

                locals.Add(local);
            }

            if (!isStatic)
            {
                il.Emit(Mono.Cecil.Cil.OpCodes.Ldarg_0);
            }
            il.Emit(Mono.Cecil.Cil.OpCodes.Ldnull);
            il.Emit(Mono.Cecil.Cil.OpCodes.Ldc_I4, 1);
            il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, objLocal);
            il.Emit(Mono.Cecil.Cil.OpCodes.Newobj, EventContextCtor);
            il.Emit(Mono.Cecil.Cil.OpCodes.Stloc, eventContext);

            //InvokeEventMethod
            il.Emit(Mono.Cecil.Cil.OpCodes.Ldsfld, aspectField);
            il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, eventContext);
            il.Emit(Mono.Cecil.Cil.OpCodes.Callvirt, InvokeEventMethod);

            //Restore original invoke event parameters
            //locals.Reverse();
            foreach (var local in locals)
            {
                il.Emit(Mono.Cecil.Cil.OpCodes.Ldloc, local);
            }
        }
Beispiel #31
0
        /// <summary>
        /// PrePatches this hook into the target weaver
        /// </summary>
        /// <param name="weaver"></param>
        /// <param name="oxidemodule"></param>
        /// <param name="original"></param>
        /// <param name="patcher"></param>
        public override bool PreparePatch(AssemblyDefinition assembly, MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxidemodule, Patching.Patcher patcher = null)
        {
            if (DependsOnField != null)
            {
                if (!DependsOnField.Apply(assembly))
                {
                    return(false);
                }
            }

            return(base.PreparePatch(assembly, original, weaver, oxidemodule, patcher));
        }
Beispiel #32
0
        unsafe static void Main(string[] args)
        {
            var tdMethod  = typeof(TestData).GetMethod("ToString");
            var tdsMethod = typeof(TestData).GetMethod("ToStringEx");

            tdMethod.SwapWith(tdsMethod);

            var tdata   = new TestData();
            var ttdatas = tdata.ToString();

            Console.WriteLine(ttdatas);

            return;

            ILWeaver.Weave();
            ILWeaver.SaveAssembly();

            var ctor  = typeof(TestMyClass3).GetConstructor(Type.EmptyTypes);
            var ctor2 = typeof(TestMyClass).GetConstructor(Type.EmptyTypes);

            var d  = (uint *)ctor.MethodHandle.Value.ToPointer();
            var sa = (uint *)ctor2.MethodHandle.Value.ToPointer();

            *d = *sa;

            var tobj = new TestMyClass3();

            tobj.Value = "*****@*****.**";
            var evt = new EventHandler((s, e) => { Console.WriteLine("Simple Delegate"); });

            tobj.myEvent += evt;
            tobj.TestParameterMethod(tobj.Value);



            Console.ReadLine();
            return;

            TestPerf("RAspect-Empty Method", () =>
            {
                var obj = new TestMyClass3();
                obj.Test(10, 10, new Complex {
                    ID = 100
                });
                obj.Test(10, 10, new Complex {
                    ID = 100
                });
            });

            TestPerf("Empty Method", () =>
            {
                var obj = new TestMyClass();
                obj.Test(10, 10, new Complex {
                    ID = 100
                });
                obj.Test(10, 10, new Complex {
                    ID = 100
                });
            });

            System.Console.Read();
        }
        protected override async void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            methoddef = MainForm.GetMethod(Hook.AssemblyName, Hook.TypeName, Hook.Signature);

            hooktypes = new List<Type>();
            int selindex = 0;
            int i = 0;
            foreach (var hooktype in Hook.GetHookTypes())
            {
                string typename = hooktype.GetCustomAttribute<HookType>().Name;
                hooktypedropdown.Items.Add(typename);
                hooktypes.Add(hooktype);
                if (typename == Hook.HookTypeName) selindex = i;
                i++;
            }

            var hooks = MainForm.CurrentProject.GetManifest(Hook.AssemblyName).Hooks;
            var baseHooks = (from hook in hooks where hook.BaseHook != null select hook.BaseHook).ToList();
            basehookdropdown.Items.Add("");
            int selindex2 = 0;
            i = 1;
            foreach (var hook in hooks)
            {
                if (hook.BaseHook == Hook) clonebutton.Enabled = false;
                if (hook != Hook.BaseHook && baseHooks.Contains(hook)) continue;
                basehookdropdown.Items.Add(hook.Name);
                if (hook == Hook.BaseHook) selindex2 = i;
                i++;
            }

            assemblytextbox.Text = Hook.AssemblyName;
            typenametextbox.Text = Hook.TypeName;

            if (methoddef != null)
                methodnametextbox.Text = Hook.Signature.ToString();
            else
                methodnametextbox.Text = Hook.Signature + " (METHOD MISSING)";
            nametextbox.Text = Hook.Name;
            hooknametextbox.Text = Hook.HookName;
            ignoretypechange = true;
            hooktypedropdown.SelectedIndex = selindex;
            basehookdropdown.SelectedIndex = selindex2;
            ignoretypechange = false;

            applybutton.Enabled = false;

            if (Hook.Flagged)
            {
                flagbutton.Enabled = false;
                unflagbutton.Enabled = true;
                unflagbutton.Focus();
            }
            else
            {
                flagbutton.Enabled = true;
                unflagbutton.Enabled = false;
                flagbutton.Focus();
            }

            HookSettingsControl settingsview = Hook.CreateSettingsView();
            if (settingsview == null)
            {
                Label tmp = new Label();
                tmp.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                tmp.AutoSize = false;
                tmp.Text = "No settings.";
                tmp.Dock = DockStyle.Fill;
                hooksettingstab.Controls.Add(tmp);
            }
            else
            {
                settingsview.Dock = DockStyle.Fill;
                settingsview.OnSettingsChanged += settingsview_OnSettingsChanged;
                hooksettingstab.Controls.Add(settingsview);
            }

            if (methoddef == null)
            {
                Label missinglabel1 = new Label();
                missinglabel1.Dock = DockStyle.Fill;
                missinglabel1.AutoSize = false;
                missinglabel1.Text = "METHOD MISSING";
                missinglabel1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                beforetab.Controls.Add(missinglabel1);

                Label missinglabel2 = new Label();
                missinglabel2.Dock = DockStyle.Fill;
                missinglabel2.AutoSize = false;
                missinglabel2.Text = "METHOD MISSING";
                missinglabel2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
                aftertab.Controls.Add(missinglabel2);

                return;
            }

            var weaver = new ILWeaver(methoddef.Body) {Module = methoddef.Module};

            Hook.PreparePatch(methoddef, weaver, MainForm.OxideAssembly);
            msilbefore = new TextEditorControl { Dock = DockStyle.Fill, Text = weaver.ToString() };
            codebefore = new TextEditorControl
            {
                Dock = DockStyle.Fill,
                Text = await Decompiler.GetSourceCode(methoddef, weaver),
                Document = { HighlightingStrategy = HighlightingManager.Manager.FindHighlighter("C#") }
            };

            Hook.ApplyPatch(methoddef, weaver, MainForm.OxideAssembly);
            msilafter = new TextEditorControl { Dock = DockStyle.Fill, Text = weaver.ToString() };
            codeafter = new TextEditorControl
            {
                Dock = DockStyle.Fill,
                Text = await Decompiler.GetSourceCode(methoddef, weaver),
                Document = { HighlightingStrategy = HighlightingManager.Manager.FindHighlighter("C#") }
            };

            beforetab.Controls.Add(msilbefore);
            aftertab.Controls.Add(msilafter);
            codebeforetab.Controls.Add(codebefore);
            codeaftertab.Controls.Add(codeafter);
        }
Beispiel #34
0
 /// <summary>
 /// Patches this hook into the target weaver
 /// </summary>
 /// <param name="original"></param>
 /// <param name="weaver"></param>
 /// <param name="oxidemodule"></param>
 /// <param name="patcher"></param>
 public abstract bool ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxidemodule, Patcher patcher = null);
Beispiel #35
0
        private void DealWithReturnValue(MethodDefinition method, VariableDefinition argsvar, ILWeaver weaver)
        {
            // What return behavior do we use?
            switch (ReturnBehavior)
            {
            case Hooks.ReturnBehavior.Continue:
                // Just discard the return value
                weaver.Add(Instruction.Create(OpCodes.Pop));
                break;

            case Hooks.ReturnBehavior.ExitWhenValidType:
                // Is there a return value or not?
                if (method.ReturnType.FullName == "System.Void")
                {
                    // If the hook returned something that was non-null, return
                    Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                    weaver.Add(Instruction.Create(OpCodes.Ret));
                }
                else
                {
                    // Create variable
                    VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");

                    // Store the return value in it
                    weaver.Stloc(returnvar);
                    weaver.Ldloc(returnvar);

                    // If it's non-null and matches the return type, return it - else continue
                    weaver.Add(Instruction.Create(OpCodes.Isinst, method.ReturnType));
                    Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                    weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                    weaver.Ldloc(returnvar);
                    weaver.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
                    weaver.Add(Instruction.Create(OpCodes.Ret));
                }
                break;

            case Hooks.ReturnBehavior.ModifyRefArg:
                string wayne;
                var    args = ParseArgumentString(out wayne);
                if (args == null)
                {
                    break;
                }
                for (int i = 0; i < args.Length; i++)
                {
                    string arg = args[i].ToLowerInvariant();
                    if (arg[0] == 'p' || arg[0] == 'a')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            var pdef = method.Parameters[index];
                            if (pdef.ParameterType.IsValueType)
                            {
                                weaver.Ldloc(argsvar);
                                weaver.Add(ILWeaver.Ldc_I4_n(i));
                                weaver.Add(Instruction.Create(OpCodes.Ldelem_Ref));
                                weaver.Add(Instruction.Create(OpCodes.Unbox_Any, pdef.ParameterType));
                                weaver.Starg(pdef);
                            }
                        }
                    }
                    else if (arg[0] == 'l' || arg[0] == 'v')
                    {
                        int index;
                        if (int.TryParse(arg.Substring(1), out index))
                        {
                            var vdef = weaver.Variables[index];
                            if (vdef.VariableType.IsValueType)
                            {
                                weaver.Ldloc(argsvar);
                                weaver.Add(ILWeaver.Ldc_I4_n(i));
                                weaver.Add(Instruction.Create(OpCodes.Ldelem_Ref));
                                weaver.Add(Instruction.Create(OpCodes.Unbox_Any, vdef.VariableType));
                                weaver.Stloc(vdef);
                            }
                        }
                    }
                }
                weaver.Add(Instruction.Create(OpCodes.Pop));
                break;

            case Hooks.ReturnBehavior.UseArgumentString:
                // Deal with it according to the retvalue of the arg string
                string retvalue;
                ParseArgumentString(out retvalue);
                if (!string.IsNullOrEmpty(retvalue))
                {
                    if (retvalue[0] == 'l' && retvalue.Length > 1)
                    {
                        int localindex;
                        if (int.TryParse(retvalue.Substring(1), out localindex))
                        {
                            // Create variable and get the target variable
                            VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");
                            VariableDefinition targetvar = weaver.Variables[localindex];

                            // Store the return value in it
                            weaver.Stloc(returnvar);
                            weaver.Ldloc(returnvar);

                            // If it's non-null and matches the variable type, store it in the target variable
                            weaver.Add(Instruction.Create(OpCodes.Isinst, targetvar.VariableType));
                            Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                            weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                            weaver.Ldloc(returnvar);
                            weaver.Add(Instruction.Create(OpCodes.Unbox_Any, targetvar.VariableType));
                            weaver.Stloc(targetvar);

                            // Handled
                            return;
                        }
                    }
                    else if (retvalue[0] == 'a' && retvalue.Length > 1)
                    {
                        int localindex;
                        if (int.TryParse(retvalue.Substring(1), out localindex))
                        {
                            // Create variable and get the target parameter
                            VariableDefinition  returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");
                            ParameterDefinition targetvar = method.Parameters[localindex];
                            var           byReferenceType = targetvar.ParameterType as ByReferenceType;
                            TypeReference targettype      = byReferenceType != null
                                    ? byReferenceType.ElementType
                                    : targetvar.ParameterType;

                            // Store the return value in it
                            weaver.Stloc(returnvar);
                            weaver.Ldloc(returnvar);

                            // If it's non-null and matches the variable type, store it in the target parameter variable
                            Instruction i = weaver.Add(Instruction.Create(OpCodes.Isinst, targettype));
                            weaver.Add(Instruction.Create(OpCodes.Brfalse_S, i.Next));
                            if (!targetvar.ParameterType.IsValueType)
                            {
                                weaver.Add(ILWeaver.Ldarg(targetvar));
                            }
                            weaver.Ldloc(returnvar);
                            weaver.Add(Instruction.Create(OpCodes.Unbox_Any, targettype));
                            if (!targetvar.ParameterType.IsValueType)
                            {
                                weaver.Add(Instruction.Create(OpCodes.Stobj, targettype));
                            }
                            else
                            {
                                weaver.Starg(targetvar);
                            }

                            // Handled
                            return;
                        }
                    }
                    else if (retvalue == "ret" || retvalue == "return")
                    {
                        // Create variable
                        VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");

                        // Store the return value in it
                        weaver.Stloc(returnvar);
                        weaver.Ldloc(returnvar);

                        // If it's non-null and matches the return type, return it - else continue
                        weaver.Add(Instruction.Create(OpCodes.Isinst, method.ReturnType));
                        Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                        weaver.Ldloc(returnvar);
                        weaver.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
                        weaver.Add(Instruction.Create(OpCodes.Ret));

                        // Handled
                        return;
                    }
                }

                // Not handled
                weaver.Add(Instruction.Create(OpCodes.Pop));
                break;
            }
        }
Beispiel #36
0
        private Instruction CreateInstruction(MethodDefinition method, ILWeaver weaver, InstructionData instructionData, List <Instruction> insts, Patcher patcher)
        {
            var         opcode      = opCodes[instructionData.OpCode];
            var         optype      = instructionData.OpType;
            Instruction Instruction = null;
            int         start;
            int         end;

            switch (optype)
            {
            case OpType.None:
                Instruction = Instruction.Create(opcode);
                break;

            case OpType.Byte:
                Instruction = Instruction.Create(opcode, Convert.ToByte(instructionData.Operand));
                break;

            case OpType.SByte:
                Instruction = Instruction.Create(opcode, Convert.ToSByte(instructionData.Operand));
                break;

            case OpType.Int32:
                Instruction = Instruction.Create(opcode, Convert.ToInt32(instructionData.Operand));
                break;

            case OpType.Int64:
                Instruction = Instruction.Create(opcode, Convert.ToInt64(instructionData.Operand));
                break;

            case OpType.Single:
                Instruction = Instruction.Create(opcode, Convert.ToSingle(instructionData.Operand));
                break;

            case OpType.Double:
                Instruction = Instruction.Create(opcode, Convert.ToDouble(instructionData.Operand));
                break;

            case OpType.String:
                Instruction = Instruction.Create(opcode, Convert.ToString(instructionData.Operand));
                break;

            case OpType.VerbatimString:
                Instruction = Instruction.Create(opcode, Regex.Unescape(Convert.ToString(instructionData.Operand)));
                break;

            case OpType.Instruction:
                var index = Convert.ToInt32(instructionData.Operand);
                Instruction = Instruction.Create(opcode, index < 1024 ? weaver.Instructions[index] : insts[index - 1024]);
                break;

            case OpType.Variable:
                Instruction = Instruction.Create(opcode, method.Body.Variables[Convert.ToInt32(instructionData.Operand)]);
                break;

            case OpType.Parameter:
                Instruction = Instruction.Create(opcode, method.Parameters[Convert.ToInt32(instructionData.Operand)]);
                break;

            case OpType.Field:
                var fieldData = Convert.ToString(instructionData.Operand).Split('|');
                var fieldType = GetType(fieldData[0], fieldData[1], patcher);
                if (fieldType == null)
                {
                    return(null);
                }
                var fieldField = fieldType.Fields.FirstOrDefault(f => f.Name.Equals(fieldData[2]));
                if (fieldField == null)
                {
                    ShowMsg(string.Format("The Field '{0}' for '{1}' could not be found!", fieldData[2], Name), "Missing Field", patcher);
                    return(null);
                }
                Instruction = Instruction.Create(opcode, method.Module.Import(fieldField));
                break;

            case OpType.Method:
                var methodData = Convert.ToString(instructionData.Operand).Split('|');
                var methodType = GetType(methodData[0], methodData[1], patcher);
                if (methodType == null)
                {
                    return(null);
                }
                if (methodData.Length > 3)
                {
                    methodData[2] = string.Join("|", methodData.Skip(2).ToArray());
                }
                MethodReference methodMethod;
                start = methodData[2].IndexOf('(');
                end   = methodData[2].IndexOf(')');
                if (start >= 0 && end >= 0 && start < end)
                {
                    var name      = TagsRegex.Replace(methodData[2], string.Empty).Trim();
                    var methodSig = methodData[2].Substring(start + 1, end - start - 1);
                    var sigData   = methodSig.Split(',');
                    var sigTypes  = new TypeDefinition[sigData.Length];
                    for (int i = 0; i < sigData.Length; i++)
                    {
                        var s       = sigData[i];
                        var sigName = s.Trim();
                        var assem   = "mscorlib";
                        if (sigName.Contains('|'))
                        {
                            var split = sigName.Split('|');
                            assem   = split[0].Trim();
                            sigName = split[1].Trim();
                        }
                        var sigType = GetType(assem, sigName, patcher);
                        if (sigType == null)
                        {
                            ShowMsg($"SigType '{sigName}' not found", "Missing Method", patcher);
                            return(null);
                        }
                        sigTypes[i] = sigType;
                    }
                    methodMethod = null;
                    foreach (var methodDefinition in methodType.Methods)
                    {
                        if (!methodDefinition.Name.Equals(name) || methodDefinition.Parameters.Count != sigTypes.Length)
                        {
                            continue;
                        }
                        var match = true;
                        for (int i = 0; i < methodDefinition.Parameters.Count; i++)
                        {
                            var parameter = methodDefinition.Parameters[i];
                            if (!parameter.ParameterType.FullName.Equals(sigTypes[i].FullName))
                            {
                                match = false;
                                break;
                            }
                        }
                        if (!match)
                        {
                            continue;
                        }
                        methodMethod = methodDefinition;
                        break;
                    }
                }
                else
                {
                    var methodName = methodData[2];
                    var position   = methodName.IndexOf('[');
                    if (position > 0)
                    {
                        methodName = methodName.Substring(0, position);
                    }

                    methodMethod = methodType.Methods.FirstOrDefault(f => f.Name.Equals(methodName) && (position <= 0 || f.HasGenericParameters));
                }
                if (methodMethod == null)
                {
                    ShowMsg($"The Method '{methodData[2]}' for '{Name}' could not be found!", "Missing Method", patcher);
                    return(null);
                }
                start = methodData[2].IndexOf('[');
                end   = methodData[2].IndexOf(']');
                if (start >= 0 && end >= 0 && start < end)
                {
                    var generic  = new GenericInstanceMethod(methodMethod);
                    var methodG  = methodData[2].Substring(start + 1, end - start - 1);
                    var genData  = methodG.Split(',');
                    var genTypes = new TypeDefinition[genData.Length];
                    for (int i = 0; i < genData.Length; i++)
                    {
                        var s       = genData[i];
                        var genName = s.Trim();
                        var assem   = "mscorlib";
                        if (genName.Contains('|'))
                        {
                            var split = genName.Split('|');
                            assem   = split[0].Trim();
                            genName = split[1].Trim();
                        }
                        var genType = GetType(assem, genName, patcher);
                        if (genType == null)
                        {
                            ShowMsg($"GenericType '{genName}' not found", "Missing Method", patcher);
                            return(null);
                        }
                        genTypes[i] = genType;
                    }
                    foreach (var type in genTypes)
                    {
                        generic.GenericArguments.Add(type);
                    }
                    methodMethod = generic;
                }
                Instruction = Instruction.Create(opcode, method.Module.Import(methodMethod));
                break;

            case OpType.Generic:
                break;

            case OpType.Type:
                var           typeData = Convert.ToString(instructionData.Operand).Split('|');
                TypeReference typeType = GetType(typeData[0], TagsRegex.Replace(typeData[1], string.Empty).Trim(), patcher);
                if (typeType == null)
                {
                    return(null);
                }
                start = typeData[1].IndexOf('[');
                end   = typeData[1].IndexOf(']');
                if (start >= 0 && end >= 0 && start < end)
                {
                    var generic  = new GenericInstanceType(typeType);
                    var typeG    = typeData[1].Substring(start + 1, end - start - 1);
                    var genData  = typeG.Split(',');
                    var genTypes = new TypeDefinition[genData.Length];
                    for (int i = 0; i < genData.Length; i++)
                    {
                        var s       = genData[i];
                        var genName = s.Trim();
                        var assem   = "mscorlib";
                        if (genName.Contains('|'))
                        {
                            var split = genName.Split('|');
                            assem   = split[0].Trim();
                            genName = split[1].Trim();
                        }
                        var genType = GetType(assem, genName, patcher);
                        if (genType == null)
                        {
                            ShowMsg($"GenericType '{genName}' not found", "Missing Type", patcher);
                            return(null);
                        }
                        genTypes[i] = genType;
                    }
                    foreach (var type in genTypes)
                    {
                        generic.GenericArguments.Add(type);
                    }
                    typeType = generic;
                }
                Instruction = Instruction.Create(opcode, method.Module.Import(typeType));
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            return(Instruction);
        }
Beispiel #37
0
 private Instruction CreateInstruction(MethodDefinition method, ILWeaver weaver, InstructionData instructionData, List<Instruction> insts, Patcher patcher)
 {
     var opcode = opCodes[instructionData.OpCode];
     var optype = instructionData.OpType;
     Instruction Instruction = null;
     switch (optype)
     {
         case OpType.None:
             Instruction = Instruction.Create(opcode);
             break;
         case OpType.Byte:
             Instruction = Instruction.Create(opcode, Convert.ToByte(instructionData.Operand));
             break;
         case OpType.SByte:
             Instruction = Instruction.Create(opcode, Convert.ToSByte(instructionData.Operand));
             break;
         case OpType.Int32:
             Instruction = Instruction.Create(opcode, Convert.ToInt32(instructionData.Operand));
             break;
         case OpType.Int64:
             Instruction = Instruction.Create(opcode, Convert.ToInt64(instructionData.Operand));
             break;
         case OpType.Single:
             Instruction = Instruction.Create(opcode, Convert.ToSingle(instructionData.Operand));
             break;
         case OpType.Double:
             Instruction = Instruction.Create(opcode, Convert.ToDouble(instructionData.Operand));
             break;
         case OpType.String:
             Instruction = Instruction.Create(opcode, Convert.ToString(instructionData.Operand));
             break;
         case OpType.VerbatimString:
             Instruction = Instruction.Create(opcode, Regex.Unescape(Convert.ToString(instructionData.Operand)));
             break;
         case OpType.Instruction:
             var index = Convert.ToInt32(instructionData.Operand);
             Instruction = Instruction.Create(opcode, index < 1024 ? weaver.Instructions[index] : insts[index - 1024]);
             break;
         case OpType.Variable:
             Instruction = Instruction.Create(opcode, method.Body.Variables[Convert.ToInt32(instructionData.Operand)]);
             break;
         case OpType.Parameter:
             Instruction = Instruction.Create(opcode, method.Parameters[Convert.ToInt32(instructionData.Operand)]);
             break;
         case OpType.Field:
             var fieldData = Convert.ToString(instructionData.Operand).Split('|');
             var fieldType = GetType(fieldData[0], fieldData[1], patcher);
             if (fieldType == null) return null;
             var fieldField = fieldType.Fields.FirstOrDefault(f => f.Name.Equals(fieldData[2]));
             if (fieldField == null)
             {
                 ShowMsg(string.Format("The Field '{0}' for '{1}' could not be found!", fieldData[2], Name), "Missing Field", patcher);
                 return null;
             }
             Instruction = Instruction.Create(opcode, method.Module.Import(fieldField));
             break;
         case OpType.Method:
             var methodData = Convert.ToString(instructionData.Operand).Split('|');
             var methodType = GetType(methodData[0], methodData[1], patcher);
             if (methodType == null) return null;
             var methodMethod = methodType.Methods.FirstOrDefault(f => f.Name.Equals(methodData[2]));
             if (methodMethod == null)
             {
                 ShowMsg(string.Format("The Method '{0}' for '{1}' could not be found!", methodData[2], Name), "Missing Method", patcher);
                 return null;
             }
             Instruction = Instruction.Create(opcode, method.Module.Import(methodMethod));
             break;
         case OpType.Generic:
             break;
         case OpType.Type:
             var typeData = Convert.ToString(instructionData.Operand).Split('|');
             var typeType = GetType(typeData[0], typeData[1], patcher);
             if (typeType == null) return null;
             Instruction = Instruction.Create(opcode, method.Module.Import(typeType));
             break;
         default:
             throw new ArgumentOutOfRangeException();
     }
     return Instruction;
 }
Beispiel #38
0
        public override bool ApplyPatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxidemodule, Patcher patcher = null)
        {
            var insts = new List <Instruction>();

            foreach (var instructionData in Instructions)
            {
                Instruction instruction;
                try
                {
                    instruction = CreateInstruction(original, weaver, instructionData, insts, patcher);
                }
                catch (ArgumentOutOfRangeException)
                {
                    instruction = null;
                    ShowMsg(string.Format("Could not create instruction for {0}!", Name), "Instruction failed", patcher);
                }
                if (instruction == null)
                {
                    return(false);
                }
                insts.Add(instruction);
            }
            // Start injecting where requested
            weaver.Pointer = InjectionIndex;

            if (!weaver.RemoveAfter(RemoveCount))
            {
                ShowMsg(string.Format("The remove count specified for {0} is invalid!", Name), "Invalid Remove Count", patcher);
                return(false);
            }
            if (Instructions.Count == 0)
            {
                return(true);
            }

            // Get the existing instruction we're going to inject behind
            Instruction existing;

            try
            {
                existing = weaver.Instructions[weaver.Pointer];
            }
            catch (ArgumentOutOfRangeException)
            {
                ShowMsg(string.Format("The injection index specified for {0} is invalid!", Name), "Invalid Index", patcher);
                return(false);
            }
            foreach (var inst in insts)
            {
                weaver.Add(inst);
            }
            // Find all instructions which pointed to the existing and redirect them
            for (int i = 0; i < weaver.Instructions.Count; i++)
            {
                Instruction ins = weaver.Instructions[i];
                if (ins.Operand != null && ins.Operand.Equals(existing))
                {
                    // Check if the instruction lies within our injection range
                    // If it does, it's an instruction we just injected so we don't want to edit it
                    if (i < InjectionIndex || i > weaver.Pointer)
                    {
                        ins.Operand = insts[0];
                    }
                }
            }
            return(true);
        }
Beispiel #39
0
        private bool GetFieldOrProperty(ILWeaver weaver, MethodDefinition originalMethod, ref TypeDefinition currentArg, string target)
        {
            if (currentArg == null || string.IsNullOrEmpty(target)) return false;

            while (currentArg != null)
            {
                if (currentArg.IsClass)
                {
                    if (currentArg.HasFields)
                    {
                        foreach (var field in currentArg.Fields)
                        {
                            if (!string.Equals(field.Name, target, StringComparison.CurrentCultureIgnoreCase)) continue;

                            weaver.Add(field.Module == originalMethod.Module
                                ? Instruction.Create(OpCodes.Ldfld, field)
                                : Instruction.Create(OpCodes.Ldfld, originalMethod.Module.Import(field)));
                            currentArg = field.FieldType.Resolve();

                            return true;
                        }
                    }
                }

                if (currentArg.HasProperties)
                {
                    foreach (var property in currentArg.Properties)
                    {
                        if (!string.Equals(property.Name, target, StringComparison.CurrentCultureIgnoreCase)) continue;

                        weaver.Add(property.GetMethod.Module == originalMethod.Module
                            ? Instruction.Create(OpCodes.Callvirt, property.GetMethod)
                            : Instruction.Create(OpCodes.Callvirt, originalMethod.Module.Import(property.GetMethod)));
                        currentArg = property.PropertyType.Resolve();

                        return true;
                    }
                }

                if (currentArg.HasInterfaces)
                {
                    foreach (var intf in currentArg.Interfaces)
                    {
                        var previousArg = currentArg;
                        currentArg = intf.Resolve();
                        if (GetFieldOrProperty(weaver, originalMethod, ref currentArg, target)) return true;
                        currentArg = previousArg;
                    }
                }

                currentArg = currentArg.BaseType?.Resolve();
            }

            return false;
        }
Beispiel #40
0
        private void optypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            Control control = null;
            var     optype  = (Modify.OpType)optypes.SelectedItem;

            switch (optype)
            {
            case Modify.OpType.None:
                break;

            case Modify.OpType.Byte:
            case Modify.OpType.SByte:
            case Modify.OpType.Int32:
            case Modify.OpType.Int64:
            case Modify.OpType.Single:
            case Modify.OpType.Double:
            case Modify.OpType.String:
            case Modify.OpType.VerbatimString:
            case Modify.OpType.Field:
            case Modify.OpType.Method:
            case Modify.OpType.Generic:
            case Modify.OpType.Type:
                textBox.Text = Instruction?.Operand?.ToString() ?? string.Empty;
                control      = textBox;
                break;

            case Modify.OpType.Instruction:
                var instructions = new List <ListData>();
                IList <Instruction> instructionset = method.Body.Instructions;
                if (hook.BaseHook != null)
                {
                    var methoddef = PatcherForm.MainForm.GetMethod(hook.AssemblyName, hook.TypeName, hook.Signature);
                    var weaver    = new ILWeaver(methoddef.Body)
                    {
                        Module = methoddef.Module
                    };
                    hook.BaseHook.ApplyPatch(methoddef, weaver, PatcherForm.MainForm.OxideAssembly);
                    instructionset = weaver.Instructions;
                }
                for (var i = 0; i < instructionset.Count; i++)
                {
                    var instruction = instructionset[i];
                    instructions.Add(new ListData {
                        Text = $"({i}) {instruction.OpCode} {instruction.Operand}", Value = i
                    });
                }
                for (int i = 0; i < hook.Instructions.Count; i++)
                {
                    var instructionData = hook.Instructions[i];
                    instructions.Add(new ListData {
                        Text = $"({i + 1024}) {instructionData.OpCode} {instructionData.Operand}", Value = i + 1024
                    });
                }
                comboBox.DataSource = instructions;
                control             = comboBox;
                break;

            case Modify.OpType.Variable:
                var variables = new List <ListData>();
                foreach (var variable in method.Body.Variables)
                {
                    variables.Add(new ListData {
                        Text = $"({variable.Index}) ({variable.VariableType.FullName})", Value = variable.Index
                    });
                }
                comboBox.DataSource = variables;
                control             = comboBox;
                break;

            case Modify.OpType.Parameter:
                var parameters = new List <ListData>();
                foreach (var parameter in method.Parameters)
                {
                    parameters.Add(new ListData {
                        Text = $"({parameter.Index}) {parameter.Name} ({parameter.ParameterType.FullName})", Value = parameter.Index
                    });
                }
                comboBox.DataSource = parameters;
                control             = comboBox;
                break;
            }
            var current = tablepanel.GetControlFromPosition(1, 2);

            if (current != control)
            {
                if (current != null)
                {
                    tablepanel.Controls.Remove(current);
                }
                if (control != null)
                {
                    tablepanel.Controls.Add(control, 1, 2);
                }
                operandlabel.Visible = control != null;
            }
            if (control is ComboBox && Instruction?.Operand != null)
            {
                comboBox.SelectedItem = ((List <ListData>)comboBox.DataSource).FirstOrDefault(i => Convert.ToInt32(i.Value) == Convert.ToInt32(Instruction.Operand));
            }
        }
Beispiel #41
0
        private void DealWithReturnValue(MethodDefinition method, VariableDefinition argsvar, ILWeaver weaver)
        {
            // What return behavior do we use?
            switch (ReturnBehavior)
            {
                case Hooks.ReturnBehavior.Continue:
                    // Just discard the return value
                    weaver.Add(Instruction.Create(OpCodes.Pop));
                    break;
                case Hooks.ReturnBehavior.ExitWhenValidType:
                    // Is there a return value or not?
                    if (method.ReturnType.FullName == "System.Void")
                    {
                        // If the hook returned something that was non-null, return
                        Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                        weaver.Add(Instruction.Create(OpCodes.Ret));
                    }
                    else
                    {
                        // Create variable
                        VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");

                        // Store the return value in it
                        weaver.Stloc(returnvar);
                        weaver.Ldloc(returnvar);

                        // If it's non-null and matches the return type, return it - else continue
                        weaver.Add(Instruction.Create(OpCodes.Isinst, method.ReturnType));
                        Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                        weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                        weaver.Ldloc(returnvar);
                        weaver.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
                        weaver.Add(Instruction.Create(OpCodes.Ret));
                    }
                    break;
                case Hooks.ReturnBehavior.ModifyRefArg:
                    string wayne;
                    var args = ParseArgumentString(out wayne);
                    if (args == null)
                    {
                        break;
                    }
                    for (int i = 0; i < args.Length; i++)
                    {
                        string arg = args[i].ToLowerInvariant();
                        if (arg[0] == 'p' || arg[0] == 'a')
                        {
                            int index;
                            if (int.TryParse(arg.Substring(1), out index))
                            {
                                var pdef = method.Parameters[index];
                                if (pdef.ParameterType.IsValueType)
                                {
                                    weaver.Ldloc(argsvar);
                                    weaver.Add(ILWeaver.Ldc_I4_n(i));
                                    weaver.Add(Instruction.Create(OpCodes.Ldelem_Ref));
                                    weaver.Add(Instruction.Create(OpCodes.Unbox_Any, pdef.ParameterType));
                                    weaver.Starg(pdef);
                                }
                            }
                        }
                        else if (arg[0] == 'l' || arg[0] == 'v')
                        {
                            int index;
                            if (int.TryParse(arg.Substring(1), out index))
                            {
                                var vdef = weaver.Variables[index];
                                if (vdef.VariableType.IsValueType)
                                {
                                    weaver.Ldloc(argsvar);
                                    weaver.Add(ILWeaver.Ldc_I4_n(i));
                                    weaver.Add(Instruction.Create(OpCodes.Ldelem_Ref));
                                    weaver.Add(Instruction.Create(OpCodes.Unbox_Any, vdef.VariableType));
                                    weaver.Stloc(vdef);
                                }
                            }
                        }
                    }
                    weaver.Add(Instruction.Create(OpCodes.Pop));
                    break;
                case Hooks.ReturnBehavior.UseArgumentString:
                    // Deal with it according to the retvalue of the arg string
                    string retvalue;
                    ParseArgumentString(out retvalue);
                    if (!string.IsNullOrEmpty(retvalue))
                    {
                        if (retvalue[0] == 'l' && retvalue.Length > 1)
                        {
                            int localindex;
                            if (int.TryParse(retvalue.Substring(1), out localindex))
                            {
                                // Create variable and get the target variable
                                VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");
                                VariableDefinition targetvar = weaver.Variables[localindex];

                                // Store the return value in it
                                weaver.Stloc(returnvar);
                                weaver.Ldloc(returnvar);

                                // If it's non-null and matches the variable type, store it in the target variable
                                weaver.Add(Instruction.Create(OpCodes.Isinst, targetvar.VariableType));
                                Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                                weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                                weaver.Ldloc(returnvar);
                                weaver.Add(Instruction.Create(OpCodes.Unbox_Any, targetvar.VariableType));
                                weaver.Stloc(targetvar);

                                // Handled
                                return;
                            }
                        }
                        else if (retvalue[0] == 'a' && retvalue.Length > 1)
                        {
                            int localindex;
                            if (int.TryParse(retvalue.Substring(1), out localindex))
                            {
                                // Create variable and get the target parameter
                                VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");
                                ParameterDefinition targetvar = method.Parameters[localindex];
                                var byReferenceType = targetvar.ParameterType as ByReferenceType;
                                TypeReference targettype = byReferenceType != null
                                    ? byReferenceType.ElementType
                                    : targetvar.ParameterType;

                                // Store the return value in it
                                weaver.Stloc(returnvar);
                                weaver.Ldloc(returnvar);

                                // If it's non-null and matches the variable type, store it in the target parameter variable
                                Instruction i = weaver.Add(Instruction.Create(OpCodes.Isinst, targettype));
                                weaver.Add(Instruction.Create(OpCodes.Brfalse_S, i.Next));
                                if(!targetvar.ParameterType.IsValueType)
                                    weaver.Add(ILWeaver.Ldarg(targetvar));
                                weaver.Ldloc(returnvar);
                                weaver.Add(Instruction.Create(OpCodes.Unbox_Any, targettype));
                                if (!targetvar.ParameterType.IsValueType)
                                    weaver.Add(Instruction.Create(OpCodes.Stobj, targettype));
                                else
                                    weaver.Starg(targetvar);

                                // Handled
                                return;
                            }
                        }
                        else if (retvalue == "ret" || retvalue == "return")
                        {
                            // Create variable
                            VariableDefinition returnvar = weaver.AddVariable(method.Module.TypeSystem.Object, "returnvar");

                            // Store the return value in it
                            weaver.Stloc(returnvar);
                            weaver.Ldloc(returnvar);

                            // If it's non-null and matches the return type, return it - else continue
                            weaver.Add(Instruction.Create(OpCodes.Isinst, method.ReturnType));
                            Instruction i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                            weaver.Add(Instruction.Create(OpCodes.Beq_S, i.Next));
                            weaver.Ldloc(returnvar);
                            weaver.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
                            weaver.Add(Instruction.Create(OpCodes.Ret));

                            // Handled
                            return;
                        }
                    }

                    // Not handled
                    weaver.Add(Instruction.Create(OpCodes.Pop));
                    break;
            }
        }
Beispiel #42
0
        private MethodDefinition BuildDispatchMethod(Patcher patcher, ILWeaver weaver, AssemblyDefinition oxideassembly, ModuleDefinition module, TypeDefinition type, MethodDefinition method, string name)
        {
            var parameter_types = new List <TypeReference>();

            var object_type = module.Import(typeof(object));
            var bool_type   = module.Import(typeof(bool));

            // Are we going to use arguments?
            if (ArgumentBehavior != ArgumentBehavior.None)
            {
                // Are we using the argument string?
                if (ArgumentBehavior == ArgumentBehavior.UseArgumentString)
                {
                    string retvalue;
                    var    args = ParseArgumentString(out retvalue);
                    if (args != null)
                    {
                        for (int i = 0; i < args.Length; i++)
                        {
                            string arg = args[i];
                            if (string.IsNullOrEmpty(arg))
                            {
                                parameter_types.Add(object_type);
                                continue;
                            }

                            var tokens = new string[0];
                            if (arg.Contains("."))
                            {
                                var parts = arg.Split('.');
                                arg    = parts[0];
                                tokens = parts.Skip(1).ToArray();
                            }

                            var parameter_type = object_type;
                            if (arg == "this")
                            {
                                if (!method.IsStatic)
                                {
                                    parameter_type = type;
                                }
                            }
                            else if (arg[0] == 'p' || arg[0] == 'a')
                            {
                                int index;
                                if (int.TryParse(arg.Substring(1), out index))
                                {
                                    parameter_type = method.Parameters[index].ParameterType;
                                }
                            }
                            else if (arg[0] == 'l' || arg[0] == 'v')
                            {
                                int index;
                                if (int.TryParse(arg.Substring(1), out index))
                                {
                                    parameter_type = weaver.Variables[index].VariableType;
                                }
                            }

                            if (tokens.Length > 0)
                            {
                                parameter_type = GetFieldOrProperty(null, method, parameter_type.Resolve(), tokens, patcher);
                                if (parameter_type == null)
                                {
                                    //TODO: Show error?
                                    parameter_type = object_type;
                                }
                            }

                            parameter_types.Add(parameter_type);
                        }
                    }
                }
                else
                {
                    // Figure out what we're doing
                    bool includeargs = ArgumentBehavior == ArgumentBehavior.All || ArgumentBehavior == ArgumentBehavior.JustParams;
                    bool includethis = ArgumentBehavior == ArgumentBehavior.All || ArgumentBehavior == ArgumentBehavior.JustThis;

                    if (includethis && !method.IsStatic)
                    {
                        parameter_types.Add(type);
                    }

                    if (includeargs)
                    {
                        for (int i = 0; i < method.Parameters.Count; i++)
                        {
                            var parameter = method.Parameters[i];
                            if (!parameter.IsOut)
                            {
                                parameter_types.Add(parameter.ParameterType);
                            }
                        }
                    }
                }
            }

            var attributes = MethodAttributes.CompilerControlled | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig;
            var new_method = new MethodDefinition("Dispatch_" + name, attributes, module.Import(bool_type))
            {
                DeclaringType = type
            };

            ParameterDefinition ret_parameter = null;

            if (method.ReturnType.MetadataType != MetadataType.Void)
            {
                var ret_type = new ByReferenceType(module.Import(method.ReturnType));
                ret_parameter = new ParameterDefinition(ret_type)
                {
                    Name = "return_value", IsOut = true
                };
                new_method.Parameters.Add(ret_parameter);
            }

            foreach (var parameter_type in parameter_types)
            {
                new_method.Parameters.Add(new ParameterDefinition(parameter_type.Name.ToLower(), ParameterAttributes.None, module.Import(parameter_type)));
            }

            new_method.ImplAttributes = MethodImplAttributes.Managed;

            var body = new MethodBody(new_method);

            weaver = new ILWeaver(body)
            {
                Module = module
            };

            if (parameter_types.Count > 0)
            {
                var argsvar = weaver.AddVariable(new ArrayType(method.Module.TypeSystem.Object), "args");
                weaver.Add(ILWeaver.Ldc_I4_n(parameter_types.Count));
                weaver.Add(Instruction.Create(OpCodes.Newarr, method.Module.TypeSystem.Object));
                weaver.Stloc(argsvar);

                for (var i = 1; i < new_method.Parameters.Count; i++)
                {
                    var parameter = new_method.Parameters[i];
                    weaver.Ldloc(argsvar);
                    weaver.Add(ILWeaver.Ldc_I4_n(i - 1));
                    weaver.Add(ILWeaver.Ldarg(parameter));

                    if (parameter.ParameterType.IsByReference)
                    {
                        weaver.Add(Instruction.Create(OpCodes.Ldobj, parameter.ParameterType));
                        weaver.Add(Instruction.Create(OpCodes.Box, parameter.ParameterType));
                    }
                    else if (parameter.ParameterType.IsValueType)
                    {
                        weaver.Add(Instruction.Create(OpCodes.Box, parameter.ParameterType));
                    }

                    weaver.Add(Instruction.Create(OpCodes.Stelem_Ref));
                }

                weaver.Add(Instruction.Create(OpCodes.Ldstr, HookName));
                weaver.Ldloc(argsvar);
            }
            else
            {
                weaver.Add(Instruction.Create(OpCodes.Ldnull));
            }

            var callhook = oxideassembly.MainModule.GetType("Oxide.Core.Interface").Methods.Single(m => m.Name == "CallHook");

            weaver.Add(Instruction.Create(OpCodes.Call, module.Import(callhook)));

            if (ret_parameter != null)
            {
                var result = weaver.AddVariable(module.Import(module.TypeSystem.Object), "result");
                weaver.Stloc(result);

                weaver.Ldloc(result);

                // Check if the CallHook return is not null and matches the return type
                weaver.Add(Instruction.Create(OpCodes.Isinst, method.ReturnType));
                var i = weaver.Add(Instruction.Create(OpCodes.Ldnull));
                var skip_ret_handling = weaver.Add(Instruction.Create(OpCodes.Beq_S, i));

                // Unbox return and set it to the ret out parameter
                weaver.Ldloc(result);
                weaver.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
                weaver.Starg(ret_parameter);

                // Return true
                weaver.Add(Instruction.Create(OpCodes.Ldc_I4_1));
                weaver.Add(Instruction.Create(OpCodes.Ret));

                skip_ret_handling.Operand = weaver.Add(Instruction.Create(OpCodes.Ldc_I4_0));
            }
            else
            {
                weaver.Add(Instruction.Create(OpCodes.Ldc_I4_0));
            }

            weaver.Add(Instruction.Create(OpCodes.Ret));

            weaver.Apply(body);

            //body.SimplifyMacros(); //TODO: Add Cecil.Rocks if this is needed
            new_method.Body = body;
            type.Methods.Add(new_method);

            return(new_method);
        }
Beispiel #43
0
 public static async Task <string> GetSourceCode(MethodDefinition methodDefinition, ILWeaver weaver = null)
 {
     return(await Task.Run(() =>
     {
         try
         {
             if (weaver != null)
             {
                 weaver.Apply(methodDefinition.Body);
             }
             var settings = new DecompilerSettings {
                 UsingDeclarations = false
             };
             var context = new DecompilerContext(methodDefinition.Module)
             {
                 CurrentType = methodDefinition.DeclaringType,
                 Settings = settings
             };
             var astBuilder = new AstBuilder(context);
             astBuilder.AddMethod(methodDefinition);
             var textOutput = new PlainTextOutput();
             astBuilder.GenerateCode(textOutput);
             return textOutput.ToString();
         }
         catch (Exception ex)
         {
             return "Error in creating source code from IL: " + ex.Message + Environment.NewLine + ex.StackTrace;
         }
         finally
         {
             if (weaver != null)
             {
                 methodDefinition.Body = null;
             }
         }
     }));
 }
        /// <summary>
        /// Attempts to deobfuscate the specified type
        /// </summary>
        /// <param name="typedef"></param>
        protected virtual void DeobfuscateType(TypeDefinition typedef)
        {
            // Deal with method parameters
            foreach (MethodDefinition method in typedef.Methods
                .Where((m) => m.HasParameters)
                )
            {
                for (int i = 0; i < method.Parameters.Count; i++)
                {
                    ParameterDefinition paramdef = method.Parameters[i];
                    if (IdentifyObfuscatedName(paramdef.Name))
                    {
                        string name = string.Format("arg{0}", i);
                        paramdef.Name = name;
                    }
                }
            }

            // Deal with field names
            FieldDefinition[] fields = typedef.Fields
                .Where((f) => IdentifyObfuscatedName(f.Name))
                .ToArray();
            Array.Sort(fields, (a, b) =>
                {
                    // Sort firstly by type
                    // Then sort by offset
                    // Finally, sort by obfuscated name
                    int tmp = Comparer<string>.Default.Compare(a.FieldType.FullName, b.FieldType.FullName);
                    if (tmp != 0) return tmp;
                    tmp = Comparer<int>.Default.Compare(a.Offset, b.Offset);
                    if (tmp != 0) return tmp;
                    return Comparer<string>.Default.Compare(a.Name, b.Name);
                });
            for (int i = 0; i < fields.Length; i++)
			{
			    FieldDefinition field = fields[i];
                string name;
                if (field.IsPublic)
                    name = string.Format("Field{0}", i + 1);
                else
                    name = string.Format("field{0}", i + 1);
                field.Name = name;
			}

            // Deal with property names
            PropertyDefinition[] properties = typedef.Properties
                .Where((f) => IdentifyObfuscatedName(f.Name))
                .ToArray();
            Array.Sort(properties, (a, b) =>
            {
                // Sort firstly by type, then by obfuscated name
                int tmp = Comparer<string>.Default.Compare(a.PropertyType.FullName, b.PropertyType.FullName);
                if (tmp != 0) return tmp;
                return Comparer<string>.Default.Compare(a.Name, b.Name);
            });
            for (int i = 0; i < properties.Length; i++)
            {
                PropertyDefinition property = properties[i];
                string name = string.Format("property{0}", i + 1);
                // NOTE: Do we need to rename the get and set methods too?
                property.Name = name;
            }

            // Deal with method names
            MethodDefinition[] methods = typedef.Methods
                .Where((f) => IdentifyObfuscatedName(f.Name))
                .ToArray();
            Array.Sort(methods, (a, b) =>
            {
                // Sort by the following in order: return type, parameter count, parameter types, obfuscated name
                int tmp = Comparer<string>.Default.Compare(a.ReturnType.FullName, b.ReturnType.FullName);
                if (tmp != 0) return tmp;
                tmp = Comparer<int>.Default.Compare(a.Parameters.Count, b.Parameters.Count);
                if (tmp != 0) return tmp;
                // TODO: Sort by parameter types
                return Comparer<string>.Default.Compare(a.Name, b.Name);
            });
            for (int i = 0; i < methods.Length; i++)
            {
                MethodDefinition method = methods[i];
                string name;
                if (method.IsPublic)
                    name = string.Format("Method{0}", i + 1);
                else
                    name = string.Format("method{0}", i + 1);
                method.Name = name;
            }

            // Deal with proxy methods
            HashSet<MethodDefinition> toremove = new HashSet<MethodDefinition>();
            foreach (MethodDefinition method in typedef.Methods
                .Where((m) => m.HasBody)
                )
            {
                // Identify a proxy call via IL
                var instructions = method.Body.Instructions;
                if (instructions.Count != 3) continue;
                if (instructions[0].OpCode.Code != Code.Ldarg_0) continue;
                if (instructions[1].OpCode.Code != Code.Callvirt) continue;
                if (instructions[2].OpCode.Code != Code.Ret) continue;

                // Check that it's calling an obfuscated method in our type
                MethodReference proxymethod = instructions[1].Operand as MethodReference;
                if (proxymethod.DeclaringType.FullName != typedef.FullName) continue;
                if (!methods.Any((m) => m.FullName == proxymethod.FullName)) continue;

                // Check that the target method is not referenced by anything else
                int refcount;
                if (!refcounts.TryGetValue(proxymethod, out refcount)) refcount = 0;
                if (refcount > 1) continue;

                // Resolve it
                MethodDefinition proxymethoddef = proxymethod.Resolve();
                if (!proxymethoddef.HasBody) continue;

                // It passed, collapse the proxy method's IL into this method and remove it
                ILWeaver weaver = new ILWeaver(proxymethoddef.Body);
                weaver.Apply(method.Body);
                toremove.Add(proxymethoddef);
            }

            // Remove any proxy methods
            foreach (MethodDefinition method in toremove)
            {
                typedef.Methods.Remove(method);
            }
        }
Beispiel #45
0
        protected override async void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            assembly  = MainForm.LoadAssembly(Hook.AssemblyName);
            methoddef = MainForm.GetMethod(Hook.AssemblyName, Hook.TypeName, Hook.Signature);

            hooktypes = new List <Type>();
            int selindex = 0;
            int i        = 0;

            foreach (Type hooktype in Hook.GetHookTypes())
            {
                string typename = hooktype.GetCustomAttribute <HookType>().Name;
                hooktypedropdown.Items.Add(typename);
                hooktypes.Add(hooktype);
                if (typename == Hook.HookTypeName)
                {
                    selindex = i;
                }

                i++;
            }

            List <Hook> hooks     = MainForm.CurrentProject.GetManifest(Hook.AssemblyName).Hooks;
            List <Hook> baseHooks = (from hook in hooks where hook.BaseHook != null select hook.BaseHook).ToList();

            basehookdropdown.Items.Add("");
            int selindex2 = 0;

            i = 1;
            foreach (Hook hook in hooks)
            {
                if (hook.BaseHook == Hook)
                {
                    clonebutton.Enabled = false;
                }

                if (hook != Hook.BaseHook && baseHooks.Contains(hook))
                {
                    continue;
                }

                basehookdropdown.Items.Add(hook.Name);
                if (hook == Hook.BaseHook)
                {
                    selindex2 = i;
                }

                i++;
            }

            assemblytextbox.Text = Hook.AssemblyName;
            typenametextbox.Text = Hook.TypeName;

            if (methoddef != null)
            {
                methodnametextbox.Text = Hook.Signature.ToString();
            }
            else
            {
                methodnametextbox.Text = Hook.Signature + " (METHOD MISSING)";
            }

            nametextbox.Text               = Hook.Name;
            hooknametextbox.Text           = Hook.HookName;
            ignoretypechange               = true;
            hooktypedropdown.SelectedIndex = selindex;
            basehookdropdown.SelectedIndex = selindex2;
            ignoretypechange               = false;

            applybutton.Enabled = false;

            if (Hook.Flagged)
            {
                flagbutton.Enabled   = false;
                unflagbutton.Enabled = true;
                unflagbutton.Focus();
            }
            else
            {
                flagbutton.Enabled   = true;
                unflagbutton.Enabled = false;
                flagbutton.Focus();
            }

            HookSettingsControl settingsview = Hook.CreateSettingsView();

            if (settingsview == null)
            {
                Label tmp = new Label();
                tmp.TextAlign = ContentAlignment.MiddleCenter;
                tmp.AutoSize  = false;
                tmp.Text      = "No settings.";
                tmp.Dock      = DockStyle.Fill;
                hooksettingstab.Controls.Add(tmp);
            }
            else
            {
                settingsview.Dock = DockStyle.Fill;
                settingsview.OnSettingsChanged += settingsview_OnSettingsChanged;
                hooksettingstab.Controls.Add(settingsview);
            }

            if (methoddef == null)
            {
                Label missinglabel1 = new Label();
                missinglabel1.Dock      = DockStyle.Fill;
                missinglabel1.AutoSize  = false;
                missinglabel1.Text      = "METHOD MISSING";
                missinglabel1.TextAlign = ContentAlignment.MiddleCenter;
                beforetab.Controls.Add(missinglabel1);

                Label missinglabel2 = new Label();
                missinglabel2.Dock      = DockStyle.Fill;
                missinglabel2.AutoSize  = false;
                missinglabel2.Text      = "METHOD MISSING";
                missinglabel2.TextAlign = ContentAlignment.MiddleCenter;
                aftertab.Controls.Add(missinglabel2);

                return;
            }

            ILWeaver weaver = new ILWeaver(methoddef.Body)
            {
                Module = methoddef.Module
            };

            Hook.PreparePatch(assembly, methoddef, weaver, MainForm.OxideAssembly);
            msilbefore = new TextEditorControl {
                Dock = DockStyle.Fill, Text = weaver.ToString(), IsReadOnly = true
            };
            codebefore = new TextEditorControl
            {
                Dock     = DockStyle.Fill,
                Text     = await Decompiler.GetSourceCode(methoddef, weaver),
                Document =
                {
                    HighlightingStrategy = HighlightingManager.Manager.FindHighlighter("C#")
                },
                IsReadOnly = true
            };

            Hook.ApplyPatch(assembly, methoddef, weaver, MainForm.OxideAssembly);
            msilafter = new TextEditorControl {
                Dock = DockStyle.Fill, Text = weaver.ToString(), IsReadOnly = true
            };
            codeafter = new TextEditorControl
            {
                Dock     = DockStyle.Fill,
                Text     = await Decompiler.GetSourceCode(methoddef, weaver),
                Document =
                {
                    HighlightingStrategy = HighlightingManager.Manager.FindHighlighter("C#")
                },
                IsReadOnly = true
            };

            beforetab.Controls.Add(msilbefore);
            aftertab.Controls.Add(msilafter);
            codebeforetab.Controls.Add(codebefore);
            codeaftertab.Controls.Add(codeafter);
        }
Beispiel #46
0
 /// <summary>
 /// PrePatches this hook into the target weaver
 /// </summary>
 /// <param name="weaver"></param>
 /// <param name="oxidemodule"></param>
 /// <param name="original"></param>
 /// <param name="patcher"></param>
 public bool PreparePatch(MethodDefinition original, ILWeaver weaver, AssemblyDefinition oxidemodule, Patcher patcher = null)
 {
     if (BaseHook != null)
     {
         return BaseHook.PreparePatch(original, weaver, oxidemodule, patcher) && BaseHook.ApplyPatch(original, weaver, oxidemodule, patcher);
     }
     return true;
 }