Beispiel #1
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 #2
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 #3
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 #4
0
        static void Main(string[] args)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            AppDomain.CurrentDomain.AssemblyResolve += (sender, args1) =>
            {
                String resourceName = "OxidePatcher.Dependencies." +
                   new AssemblyName(args1.Name).Name + ".dll";
                if (resourceName.Contains("resources.dll"))
                {
                    return null;
                }
                using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
                {
                    Byte[] assemblyData = new Byte[stream.Length];

                    stream.Read(assemblyData, 0, assemblyData.Length);

                    return Assembly.Load(assemblyData);

                }

            };

            if (args.Length == 0)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new PatcherForm());
            }
            else
            {
                bool console = false;
                string filename = "RustExperimental.opj";
                bool unflagAll = false;
                string targetOverride = "";
                string error = "";
                int n = 0;

                while (n < args.Length)
                {

                    if (args[n].Contains("-unflag"))
                    {
                        unflagAll = true;
                    }
                    else if (!args[n].StartsWith("-") && args[n].EndsWith(".opj"))
                    {
                        filename = args[n];
                    }
                    else if (args[n].Contains("-c"))
                    {
                        console = true;
                    }
                    else if (args[n].Contains("-p"))
                    {
                        try
                        {
                            if (!args[n + 1].StartsWith("-") && !(args[n + 1].EndsWith(".opj")))
                            {
                                targetOverride = args[n + 1];
                                n++;
                            }
                            else if (args[n + 1].StartsWith("-"))
                            {
                                error = "-p requires a file path.";
                            }
                        }
                        catch (IndexOutOfRangeException)
                        {
                            error = "-p requires a file path.";
                        }
                    }
                    else
                    {
                        error = "Unknown or invalid option: " + args[n];
                    }
                    n++;
                }
                if (console)
                {
                    // redirect console output to parent process;
                    // must be before any calls to Console.WriteLine()
                    AttachConsole(ATTACH_PARENT_PROCESS);
                }
                if (error != "" && console)
                {
                    Console.WriteLine("ERROR: " + error);
                    return;
                }
                else if (error != "")
                {
                    MessageBox.Show(error, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                if (console && !Directory.Exists(targetOverride) && targetOverride != "")
                {
                    Console.WriteLine(targetOverride + " does not exist!");
                    return;
                }
                else if (!Directory.Exists(targetOverride) && targetOverride != "")
                {
                    MessageBox.Show(targetOverride + " does not exist!", "File Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                if (console && !System.IO.File.Exists(filename))
                {
                    Console.WriteLine(filename + " does not exist!");
                    return;
                }
                else if (!System.IO.File.Exists(filename))
                {
                    MessageBox.Show(filename + " does not exist!", "File Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                Project PatchProject = null;
                if (targetOverride == "")
                {
                    PatchProject = Project.Load(filename);
                }
                else
                {
                    PatchProject = Project.Load(filename, targetOverride);
                }
                if (unflagAll)
                {
                    unflag(PatchProject, filename, console);
                }
                if (!console)
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new PatcherForm(filename));
                }
                else
                {
                    Patcher patcher = new Patcher(PatchProject);
                    patcher.Patch(true);
                    Console.WriteLine("Press Enter to continue...");
                }
            }
        }
Beispiel #5
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 #6
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;
 }
Beispiel #7
0
 protected void ShowMsg(string msg, string header, Patcher patcher)
 {
     if (patcher != null)
         patcher.Log(msg);
     else
         MessageBox.Show(msg, header, MessageBoxButtons.OK, MessageBoxIcon.Error);
 }
Beispiel #8
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 #9
0
 private TypeDefinition GetType(string assemblyName, string typeName, Patcher patcher)
 {
     var targetDir = patcher != null ? patcher.PatchProject.TargetDirectory : PatcherForm.MainForm.CurrentProject.TargetDirectory;
     var resolver = new DefaultAssemblyResolver();
     resolver.AddSearchDirectory(targetDir);
     string filename = Path.Combine(targetDir, assemblyName.Replace(".dll", "") + ".dll");
     var assem = AssemblyDefinition.ReadAssembly(filename, new ReaderParameters { AssemblyResolver = resolver });
     if (assem == null)
     {
         ShowMsg(string.Format("The Assembly '{0}' for '{1}' could not be found!", assemblyName, Name), "Missing Assembly", patcher);
         return null;
     }
     var type = assem.MainModule.GetType(typeName);
     if (type == null)
     {
         ShowMsg(string.Format("The Type '{0}' for '{1}' could not be found!", typeName, Name), "Missing Type", patcher);
         return null;
     }
     return type;
 }
 private void Worker()
 {
     WorkerWriteLog("Started patching.");
     try
     {
         Patcher patcher = new Patcher(PatchProject);
         patcher.OnLogMessage += (msg) => WorkerWriteLog(msg);
         patcher.Patch();
     }
     catch (Exception ex)
     {
         WorkerWriteLog("ERROR: {0}", ex.Message);
     }
     WorkerWriteLog("Patch complete.");
     WorkerCompleteWork();
 }
Beispiel #11
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 #12
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];*/
                            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
                            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));
                            }

                            if (!GetFieldOrProperty(weaver, method, vdef.VariableType.Resolve(), target, patcher) && 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;
        }