Ejemplo n.º 1
0
        public void Patch()
        {
            System.Reflection.Assembly ownAssembly = System.Reflection.Assembly.GetCallingAssembly();
            Stream      xmlStream = ownAssembly.GetManifestResourceStream("SKPatcher.xmlpatchers.xml");
            XmlDocument xml       = new XmlDocument();

            xml.Load(xmlStream);
            XmlElement document = xml.DocumentElement;

            XmlNode[] hookNodes = document.ChildNodes.Items("hook");
            foreach (XmlNode hookNode in hookNodes)
            {
                if (hookNode.Attributes["type"] == null || hookNode.Attributes["name"] == null || hookNode.Attributes["insertAt"] == null)
                {
                    logger.Error("Error in xmlpatchers.xml : Unable to find one of the necessary attributes!");
                    break;
                }
                if (hookNode.Attributes["type"].Value.ToLower().Equals("event"))
                {
                    string eventName     = hookNode.Attributes["name"].Value;
                    bool   isCancellable = (hookNode.Attributes["cancellable"] != null) && (hookNode.Attributes["cancellable"].Value.ToLower().Equals("true"));
                    int    insertAt;
                    if (!Int32.TryParse(hookNode.Attributes["insertAt"].Value, out insertAt))
                    {
                        logger.Error("Error in xmlpatchers.xml : Unable to parse the insertAt value!");
                        continue;
                    }
                    XmlNode typeNode       = hookNode.ChildNodes.Item("type");
                    XmlNode methodNode     = hookNode.ChildNodes.Item("method");
                    XmlNode parametersNode = hookNode.ChildNodes.Item("parameters");
                    if (typeNode == null || methodNode == null || parametersNode == null)
                    {
                        logger.Error("Error in xmlpatchers.xml : ChildNodes missing for event (name = \"" + eventName + "\")!");
                        continue;
                    }
                    string         typeName         = typeNode.Attributes["name"].Value;
                    XmlAttribute   methodName       = methodNode.Attributes["name"];
                    XmlAttribute   methodParameters = methodNode.Attributes["parameters"];
                    XmlAttribute   methodReturn     = methodNode.Attributes["return"];
                    TypeDefinition targetType       = module.GetType(typeName);
                    if (targetType == null)
                    {
                        logger.Error("Error in xmlpatchers.xml : Unable to find type \"" + typeName + "\"!");
                        continue;
                    }

                    //I don't always use 'var' but when I do, it would be odd not to.
                    var methodComparers = new List <HelperClass.GenericFuncContainer <MethodDefinition, bool> >(3);
                    if (methodName != null)
                    {
                        methodComparers.Add(HelperClass.MemberNameComparer <MethodDefinition>(methodName.Value));
                    }
                    if (methodParameters != null)
                    {
                        methodComparers.Add(HelperClass.MethodParametersComparer(methodParameters.Value.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)));
                    }
                    if (methodReturn != null)
                    {
                        methodComparers.Add(HelperClass.MethodReturnTypeComparer(methodReturn.Value));
                    }
                    methodComparers.Add(new HelperClass.GenericFuncContainer <MethodDefinition, bool>(method => Matches(method, methodNode)));
                    MethodDefinition targetMethod = HelperClass.findMember <MethodDefinition>(module, targetType, false,
                                                                                              methodComparers.ToArray());

                    int parameterId = (isCancellable ? 0 : -1);
                    if (targetMethod != null)
                    {
                        MethodBody           body       = targetMethod.Body;
                        ILProcessor          proc       = body.GetILProcessor();
                        List <Instruction[]> argLoaders = new List <Instruction[]>(parametersNode.ChildNodes.Count + (isCancellable ? 1 : 0));
                        if (isCancellable)
                        {
                            argLoaders.Add(new Instruction[] { proc.Create(OpCodes.Ldc_I4_0), proc.Create(OpCodes.Box, module.Import(mscorlibModule.GetType("System.Boolean"))) });
                        }
                        List <Instruction[]> argWriters = new List <Instruction[]>(parametersNode.ChildNodes.Count);
                        if (isCancellable)
                        {
                            Instruction[] cancelInstr = new Instruction[8];
                            cancelInstr[0] = proc.Create(OpCodes.Dup);
                            cancelInstr[1] = proc.Create(OpCodes.Ldc_I4_0);
                            cancelInstr[2] = proc.Create(OpCodes.Ldelem_Ref);
                            cancelInstr[3] = proc.Create(OpCodes.Unbox_Any, module.Import(mscorlibModule.GetType("System.Boolean")));

                            cancelInstr[5] = proc.Create(OpCodes.Pop);
                            cancelInstr[6] = proc.Create(OpCodes.Ret);
                            cancelInstr[7] = proc.Create(OpCodes.Nop);

                            cancelInstr[4] = proc.Create(OpCodes.Brfalse, cancelInstr[7]);
                            argWriters.Add(cancelInstr);
                        }


                        foreach (XmlNode parNode in parametersNode.ChildNodes.Items("parameter"))
                        {
                            parameterId++;
                            XmlAttribute   _typeAttr  = parNode.Attributes["type"];
                            string         parType    = (_typeAttr == null) ? "System.Object" : _typeAttr.Value;
                            TypeDefinition parTypeDef = findType(parType);
                            if (parTypeDef == null)
                            {
                                logger.Error("Error in xmlpatchers.xml : Unable to find type \"" + parType + "\"!");
                                continue;
                            }
                            bool    isCustom  = parNode.Attributes.ValueOf("isCustom").ToLower().Equals("true");
                            XmlNode loadNode  = parNode.ChildNodes.Item("load");
                            XmlNode writeNode = parNode.ChildNodes.Item("write");
                            if (loadNode != null)
                            {
                                List <Instruction> loadInstr = new List <Instruction>(ParseInstructions(loadNode, proc));
                                if (parTypeDef.IsValueType)
                                {
                                    loadInstr.Add(proc.Create(OpCodes.Box, module.Import(parTypeDef)));
                                }
                                argLoaders.Add(loadInstr.ToArray());
                            }
                            if (writeNode != null)
                            {
                                List <Instruction> writeInstr = new List <Instruction> ();
                                if (!isCustom)
                                {
                                    writeInstr.Add(proc.Create(OpCodes.Dup));
                                    writeInstr.Add(proc.Create(OpCodes.Ldc_I4, parameterId));
                                    writeInstr.Add(proc.Create(OpCodes.Ldelem_Ref));
                                    if (parTypeDef.IsValueType)
                                    {
                                        writeInstr.Add(proc.Create(OpCodes.Unbox_Any, module.Import(parTypeDef)));
                                    }
                                    else
                                    {
                                        writeInstr.Add(proc.Create(OpCodes.Castclass, module.Import(parTypeDef)));
                                    }
                                }
                                writeInstr.AddRange(ParseInstructions(writeNode, proc));

                                argWriters.Add(writeInstr.ToArray());
                            }
                        }
                        List <Instruction> hook = HookHelper.Instance.prepareEventHook(targetMethod, eventName, argLoaders.ToArray());
                        for (int i = 0; i < argWriters.Count; i++)
                        {
                            hook.AddRange(argWriters[i]);
                        }
                        hook.Add(proc.Create(OpCodes.Pop));
                        HookHelper.insertAt(body, insertAt, hook.ToArray());
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public void Patch()
        {
            HelperClass.SetLogger(null);             //HelperClass.OnError would otherwise show errors if a NetPackage class doesn't override Process,Read or Write
            TypeDefinition[] netPackageTypes = HelperClass.findTypes(module,
                                                                     HelperClass.CombinedComparer <MethodDefinition>(
                                                                         HelperClass.MemberNameComparer <MethodDefinition>("GetPackageType"),
                                                                         HelperClass.MethodReturnTypeComparer("PackageType"),
                                                                         HelperClass.MethodNegAttributeComparer(MethodAttributes.Abstract))
                                                                     );
            if (netPackageTypes == null || netPackageTypes.Length == 0)
            {
                logger.Error("Unable to find any NetPackage classes!");
                return;
            }

            foreach (TypeDefinition curPackageType in netPackageTypes)
            {
                MethodDefinition processMethod = HelperClass.findMember <MethodDefinition>(module, curPackageType, false,
                                                                                           HelperClass.MemberNameComparer <MethodDefinition>("Process"),
                                                                                           HelperClass.MethodReturnTypeComparer("System.Void"),
                                                                                           HelperClass.MethodParametersComparer("World", "INetConnectionCallbacks"));
                if (processMethod != null)
                {
                    MethodBody body = processMethod.Body;
                    if (body != null)
                    {
                        ILProcessor        proc      = body.GetILProcessor();
                        List <Instruction> eventHook = HookHelper.Instance.prepareEventHook(processMethod, "ProcessPacketEvent",
                                                                                            new Instruction[][] {
                            new Instruction[] {
                                proc.Create(OpCodes.Ldarg_0),
                            },
                            new Instruction[] {
                                proc.Create(OpCodes.Ldc_I4_0),
                                proc.Create(OpCodes.Box, module.Import(mscorlibModule.GetType("System.Boolean"))),
                            },
                            new Instruction[] {
                                proc.Create(OpCodes.Ldarg_1),
                            },
                            new Instruction[] {
                                proc.Create(OpCodes.Ldarg_2),
                            },
                        }
                                                                                            );
                        eventHook.Add(proc.Create(OpCodes.Ldc_I4_1));
                        eventHook.Add(proc.Create(OpCodes.Ldelem_Ref));
                        eventHook.Add(proc.Create(OpCodes.Unbox_Any, module.Import(mscorlibModule.GetType("System.Boolean"))));
                        eventHook.Add(proc.Create(OpCodes.Brfalse, body.Instructions[0]));
                        eventHook.Add(proc.Create(OpCodes.Ret));
                        HookHelper.insertAt(body, 0, eventHook.ToArray());
                    }
                }
                MethodDefinition readMethod = HelperClass.findMember <MethodDefinition>(module, curPackageType, false,
                                                                                        HelperClass.MemberNameComparer <MethodDefinition>("Read"),
                                                                                        HelperClass.MethodReturnTypeComparer("System.Void"),
                                                                                        HelperClass.MethodParametersComparer("System.IO.BinaryReader"));
                if (readMethod != null)
                {
                    MethodBody body = readMethod.Body;
                    if (body != null)
                    {
                        ILProcessor        proc      = body.GetILProcessor();
                        List <Instruction> eventHook = HookHelper.Instance.prepareEventHook(readMethod, "ReadPacketFromBufEvent",
                                                                                            new Instruction[][] {
                            new Instruction[] {
                                proc.Create(OpCodes.Ldarg_0),
                            },
                        }
                                                                                            );
                        eventHook.Add(proc.Create(OpCodes.Pop));
                        HookHelper.insertAt(body, body.Instructions.Count - 1, eventHook.ToArray());
                    }
                }
                MethodDefinition writeMethod = HelperClass.findMember <MethodDefinition>(module, curPackageType, false,
                                                                                         HelperClass.MemberNameComparer <MethodDefinition>("Write"),
                                                                                         HelperClass.MethodReturnTypeComparer("System.Void"),
                                                                                         HelperClass.MethodParametersComparer("System.IO.BinaryWriter"));
                if (writeMethod != null)
                {
                    MethodBody body = writeMethod.Body;
                    if (body != null)
                    {
                        ILProcessor        proc      = body.GetILProcessor();
                        List <Instruction> eventHook = HookHelper.Instance.prepareEventHook(writeMethod, "WritePacketToBufEvent",
                                                                                            new Instruction[][] {
                            new Instruction[] {
                                proc.Create(OpCodes.Ldarg_0),
                            },
                            new Instruction[] {
                                proc.Create(OpCodes.Ldc_I4_0),
                                proc.Create(OpCodes.Box, module.Import(mscorlibModule.GetType("System.Boolean"))),
                            },
                        }
                                                                                            );
                        eventHook.Add(proc.Create(OpCodes.Ldc_I4_1));
                        eventHook.Add(proc.Create(OpCodes.Ldelem_Ref));
                        eventHook.Add(proc.Create(OpCodes.Unbox_Any, module.Import(mscorlibModule.GetType("System.Boolean"))));
                        eventHook.Add(proc.Create(OpCodes.Brfalse, body.Instructions[0]));
                        eventHook.Add(proc.Create(OpCodes.Ret));
                        HookHelper.insertAt(body, 0, eventHook.ToArray());
                    }
                }
            }
        }