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

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

fixer

File size: 3.7 KB
RevLine 
[73]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);
[76]14 connectLogPatch (module);
[73]15 module.Write ("Assembly-CSharp.dll");
16 Console.WriteLine ("Done");
17 }
18
[75]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);
[76]28 addHook (type, "RequestToSpawnPlayer", true, 5, true, typeof(AllocsRequestToSpawnPlayer).GetMethod ("RequestToSpawnPlayer"));
[75]29 }
30
[73]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);
[75]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"));
[73]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
[76]51 private static void addHook (TypeDefinition type, string methodName, bool addThisRef, int opCount, bool atEnd, MethodBase targetMethod)
[73]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));
[76]58 if (atEnd) {
59 int insBefore = method.Body.Instructions.Count;
60 if (addThisRef)
61 il.Append (il.Create (OpCodes.Ldarg, 0));
62 for (int op = 0; op < opCount; op++) {
63 il.Append (il.Create (OpCodes.Ldarg, op + 1));
64 }
65 il.Append (call);
66 il.Remove (method.Body.Instructions [insBefore - 1]);
67 il.Append (il.Create (OpCodes.Ret));
68 } else {
69 var i = 0;
70 if (addThisRef)
71 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, 0));
72 for (int op = 0; op < opCount; op++) {
73 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, op + 1));
74 }
75 il.InsertBefore (method.Body.Instructions [i++], call);
[73]76 }
[75]77 }
78 }
79 }
80
81 private static void replaceMethod (TypeDefinition type, string methodName, int opCount, MethodBase targetMethod)
82 {
83 foreach (MethodDefinition method in type.Methods) {
84 if (method.Name.Equals (methodName)) {
85 Console.WriteLine ("Patching " + methodName);
86 var il = method.Body.GetILProcessor ();
87 var call = il.Create (OpCodes.Call, method.Module.Import (targetMethod));
88 var i = 0;
89 for (int op = 0; op < opCount; op++) {
90 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ldarg, op + 1));
91 }
92 il.InsertBefore (method.Body.Instructions [i++], call);
[73]93 il.InsertBefore (method.Body.Instructions [i++], il.Create (OpCodes.Ret));
94 }
95 }
96 }
97
98 private static bool isPatched (TypeDefinition type)
99 {
100 foreach (FieldDefinition fd in type.Fields) {
101 if (fd.Name.Equals ("AllocsPatch")) {
102 Console.WriteLine ("\"" + type.Name + "\" is already patched, skipping");
103 return true;
104 }
105 }
106 Console.WriteLine ("Patching \"" + type.Name + "\"");
107 return false;
108 }
109 }
110}
Note: See TracBrowser for help on using the repository browser.