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

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

fixes

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