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

Last change on this file since 84 was 84, checked in by alloc, 10 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.