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

Last change on this file since 75 was 75, checked in by alloc, 10 years ago

fixes

File size: 3.3 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 module.Write ("Assembly-CSharp.dll");
16 Console.WriteLine ("Done");
17 }
18
19 private static void connectLogPatch (ModuleDefinition module)
20 {
21 TypeDefinition type = module.GetType ("GameManager");
22
23 if (isPatched (type)) {
24 return;
25 }
26
27 markTypePatched (module, type);
28 addHook (type, "RequestToSpawnPlayer", true, 5, typeof(AllocsRequestToSpawnPlayer).GetMethod ("RequestToSpawnPlayer"));
29 }
30
31 private static void telnetPatch (ModuleDefinition module)
32 {
33 TypeDefinition type = module.GetType ("NetTelnetServer");
34
35 if (isPatched (type)) {
36 return;
37 }
38
39 markTypePatched (module, type);
40 replaceMethod (type, ".ctor", 1, typeof(AllocsNetTelnetServer).GetMethod ("init"));
41 replaceMethod (type, "Disconnect", 0, typeof(AllocsNetTelnetServer).GetMethod ("Disconnect"));
42 replaceMethod (type, "SetConsole", 1, typeof(AllocsNetTelnetServer).GetMethod ("SetConsole"));
43 replaceMethod (type, "WriteToClient", 1, typeof(AllocsNetTelnetServer).GetMethod ("WriteToClient"));
44 }
45
46 private static void markTypePatched (ModuleDefinition module, TypeDefinition type)
47 {
48 type.Fields.Add (new FieldDefinition ("AllocsPatch", Mono.Cecil.FieldAttributes.Private | Mono.Cecil.FieldAttributes.SpecialName, module.Import (typeof(int))));
49 }
50
51 private static void addHook (TypeDefinition type, string methodName, bool addThisRef, int opCount, MethodBase targetMethod)
52 {
53 foreach (MethodDefinition method in type.Methods) {
54 if (method.Name.Equals (methodName)) {
55 Console.WriteLine ("Patching " + methodName);
56 var il = method.Body.GetILProcessor ();
57 var call = il.Create (OpCodes.Call, method.Module.Import (targetMethod));
58 var i = 0;
59 if (addThisRef)
60 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, 0));
61 for (int op = 0; op < opCount; op++) {
62 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, op + 1));
63 }
64 il.InsertBefore (method.Body.Instructions [i++], call);
65 }
66 }
67 }
68
69 private static void replaceMethod (TypeDefinition type, string methodName, int opCount, MethodBase targetMethod)
70 {
71 foreach (MethodDefinition method in type.Methods) {
72 if (method.Name.Equals (methodName)) {
73 Console.WriteLine ("Patching " + methodName);
74 var il = method.Body.GetILProcessor ();
75 var call = il.Create (OpCodes.Call, method.Module.Import (targetMethod));
76 var i = 0;
77 for (int op = 0; op < opCount; op++) {
78 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, op + 1));
79 }
80 il.InsertBefore (method.Body.Instructions [i++], call);
81 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ret));
82 }
83 }
84 }
85
86 private static bool isPatched (TypeDefinition type)
87 {
88 foreach (FieldDefinition fd in type.Fields) {
89 if (fd.Name.Equals ("AllocsPatch")) {
90 Console.WriteLine ("\"" + type.Name + "\" is already patched, skipping");
91 return true;
92 }
93 }
94 Console.WriteLine ("Patching \"" + type.Name + "\"");
95 return false;
96 }
97 }
98}
Note: See TracBrowser for help on using the repository browser.