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

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

fixes

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