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

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

fixes

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