source: binary-improvements/assembly-patcher/Main.cs @ 83

Last change on this file since 83 was 83, checked in by alloc, 6 years ago

server fixes

File size: 4.0 KB
Line 
1using System;
2using System.Reflection;
3using Mono.Cecil;
4using Mono.Cecil.Cil;
5
6namespace dtdfixer
7{
8        class MainClass
9        {
10                public static void Main (string[] args)
11                {
12                        ModuleDefinition module = ModuleDefinition.ReadModule ("Assembly-CSharp.dll");
13                        telnetPatch (module);
14                        connectLogPatch (module);
15                        executionLogPatch( module);
16                        module.Write ("Assembly-CSharp.dll");
17                        Console.WriteLine ("Done");
18                }
19
20                private static void connectLogPatch (ModuleDefinition module)
21                {
22                        TypeDefinition type = module.GetType ("GameManager");
23
24                        if (isPatched (type)) {
25                                return;
26                        }
27
28                        markTypePatched (module, type);
29                        addHook (type, "RequestToSpawnPlayer", true, 5, true, typeof(AllocsLogFunctions).GetMethod ("RequestToSpawnPlayer"));
30                }
31
32                private static void executionLogPatch (ModuleDefinition module)
33                {
34                        TypeDefinition type = module.GetType ("ConsoleSdtd");
35
36                        if (isPatched (type)) {
37                                return;
38                        }
39
40                        markTypePatched (module, type);
41                        addHook (type, "ExecuteCmdFromClient", true, 3, false, typeof(AllocsLogFunctions).GetMethod ("ExecuteCmdFromClient"));
42                }
43
44                private static void telnetPatch (ModuleDefinition module)
45                {
46                        TypeDefinition type = module.GetType ("NetTelnetServer");
47
48                        if (isPatched (type)) {
49                                return;
50                        }
51
52                        markTypePatched (module, type);
53                        replaceMethod (type, ".ctor", 1, typeof(AllocsNetTelnetServer).GetMethod ("init"));
54                        replaceMethod (type, "Disconnect", 0, typeof(AllocsNetTelnetServer).GetMethod ("Disconnect"));
55                        replaceMethod (type, "SetConsole", 1, typeof(AllocsNetTelnetServer).GetMethod ("SetConsole"));
56                        replaceMethod (type, "WriteToClient", 1, typeof(AllocsNetTelnetServer).GetMethod ("WriteToClient"));
57                }
58
59                private static void markTypePatched (ModuleDefinition module, TypeDefinition type)
60                {
61                        type.Fields.Add (new FieldDefinition ("AllocsPatch", Mono.Cecil.FieldAttributes.Private | Mono.Cecil.FieldAttributes.SpecialName, module.Import (typeof(int))));
62                }
63
64                private static void addHook (TypeDefinition type, string methodName, bool addThisRef, int opCount, bool atEnd, MethodBase targetMethod)
65                {
66                        foreach (MethodDefinition method in type.Methods) {
67                                if (method.Name.Equals (methodName)) {
68                                        Console.WriteLine ("Patching " + methodName);
69                                        var il = method.Body.GetILProcessor ();
70                                        var call = il.Create (OpCodes.Call, method.Module.Import (targetMethod));
71                                        if (atEnd) {
72                                                int insBefore = method.Body.Instructions.Count;
73                                                if (addThisRef)
74                                                        il.Append (il.Create (OpCodes.Ldarg, 0));
75                                                for (int op = 0; op < opCount; op++) {
76                                                        il.Append (il.Create (OpCodes.Ldarg, op + 1));
77                                                }
78                                                il.Append (call);
79                                                il.Remove (method.Body.Instructions [insBefore - 1]);
80                                                il.Append (il.Create (OpCodes.Ret));
81                                        } else {
82                                                var i = 0;
83                                                if (addThisRef)
84                                                        il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, 0));
85                                                for (int op = 0; op < opCount; op++) {
86                                                        il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, op + 1));
87                                                }
88                                                il.InsertBefore (method.Body.Instructions [i++], call);
89                                        }
90                                }
91                        }
92                }
93
94                private static void replaceMethod (TypeDefinition type, string methodName, int opCount, MethodBase targetMethod)
95                {
96                        foreach (MethodDefinition method in type.Methods) {
97                                if (method.Name.Equals (methodName)) {
98                                        Console.WriteLine ("Patching " + methodName);
99                                        var il = method.Body.GetILProcessor ();
100                                        var call = il.Create (OpCodes.Call, method.Module.Import (targetMethod));
101                                        var i = 0;
102                                        for (int op = 0; op < opCount; op++) {
103                                                il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, op + 1));
104                                        }
105                                        il.InsertBefore (method.Body.Instructions [i++], call);
106                                        il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ret));
107                                }
108                        }
109                }
110
111                private static bool isPatched (TypeDefinition type)
112                {
113                        foreach (FieldDefinition fd in type.Fields) {
114                                if (fd.Name.Equals ("AllocsPatch")) {
115                                        Console.WriteLine ("\"" + type.Name + "\" is already patched, skipping");
116                                        return true;
117                                }
118                        }
119                        Console.WriteLine ("Patching \"" + type.Name + "\"");
120                        return false;
121                }
122        }
123}
Note: See TracBrowser for help on using the repository browser.