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

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