Advertisement
LaPanthere

Tutorial 4: Advanced Importing

Jan 31st, 2014
551
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.12 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Mono.Cecil;
  6. using Mono.Cecil.Cil;
  7. using Mono.Collections.Generic;
  8.  
  9. namespace Tutorial4Code
  10. {
  11.     class Program
  12.     {
  13.         static void Main(string[] args)
  14.         {
  15.             // Loads the assembly from the start arguments
  16.             AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(args[0]);
  17.  
  18.             // Iterates through the assembly's modules, aspects of the program
  19.             foreach (ModuleDefinition mod in asm.Modules)
  20.             {
  21.                 // Create a type definition
  22.                 TypeDefinition injected = createType(mod);
  23.  
  24.                 // Finds or creates the modules main constructor, "<Module>.cctor".
  25.                 FindMethod(mod, injected);
  26.  
  27.                 // Getting the method "Begin" from our injected type
  28.                 MethodDefinition inMtd = Extensions.FirstOrDefault<MethodDefinition>(injected.Methods, m => m.Name == "Begin");
  29.  
  30.                 // Iterating through the instructions and replacing a string if its equal to "PADDING"
  31.                 for (int i = 0; i < inMtd.Body.Instructions.Count; i++)
  32.                 {
  33.                     Instruction inst = inMtd.Body.Instructions[i];
  34.  
  35.                     if (inst.OpCode == OpCodes.Ldstr)
  36.                     {
  37.                         if ((inst.Operand as string) == "PADDING")
  38.                         {
  39.                             inst.Operand = "Hi there, I've been changed from my original value!";
  40.                         }
  41.                     }
  42.                 }
  43.  
  44.                 // Insert the injected type
  45.                 mod.Types.Add(injected);
  46.             }
  47.  
  48.             // Write the file to disk
  49.             asm.Write(@"C:\Tut\importerInjector.exe");
  50.         }
  51.  
  52.         static void FindMethod(ModuleDefinition mod, TypeDefinition importedType)
  53.         {
  54.             // Because the main constructor is never in a nested type we don't have to worry about looking there
  55.             foreach (TypeDefinition td in mod.Types)
  56.             {
  57.                 // If the type definitions name is equal to "<Module>"
  58.                 if (td.Name == "<Module>")
  59.                 {
  60.                     // We'll use a bool to see if the static constructor is found
  61.                     bool constructorFound = false;
  62.  
  63.                     // Same as up at the start, we want the "Begin" method of the injected type.
  64.                     MethodDefinition meth = Extensions.FirstOrDefault<MethodDefinition>(importedType.Methods, m => m.Name == "Begin");
  65.  
  66.                     // Searching for the module's static constructor
  67.                     foreach (MethodDefinition md in td.Methods)
  68.                     {
  69.                         if (md.Name == ".cctor")
  70.                         {
  71.                             // If its found it'll set the variable to true
  72.                             constructorFound = true;
  73.  
  74.                             // Add the needed instructions to call our method to the static constructor
  75.                             AddInstructions(md, meth);
  76.                         }
  77.                     }
  78.                     if (!constructorFound)
  79.                     {
  80.                         // If the constructor is not found, add a static constructor
  81.                         MethodDefinition cctor = AddStaticConstructor(td);
  82.  
  83.                         // Then we can add the instructions to call our injected method
  84.                         AddInstructions(cctor, meth);
  85.                     }
  86.                 }
  87.             }
  88.         }
  89.  
  90.         private static MethodDefinition AddStaticConstructor(TypeDefinition td)
  91.         {
  92.             ModuleDefinition mod = td.Module;
  93.  
  94.             // Static constructors must have the same attributes, otherwise it won't be recoginized
  95.             MethodDefinition method = new MethodDefinition(".cctor", Mono.Cecil.MethodAttributes.Private | Mono.Cecil.MethodAttributes.Static | Mono.Cecil.MethodAttributes.HideBySig | Mono.Cecil.MethodAttributes.SpecialName | Mono.Cecil.MethodAttributes.RTSpecialName, mod.Import(typeof(void)));
  96.  
  97.             // Add the static constructor to "<Module>"
  98.             td.Methods.Add(method);
  99.             return method;
  100.         }
  101.  
  102.         private static void AddInstructions(MethodDefinition cctor, MethodDefinition reference)
  103.         {
  104.             // You should know what is happening here, if not go and visit my other tutorials
  105.             ModuleDefinition mod = cctor.DeclaringType.Module;
  106.             ILProcessor ilp = cctor.Body.GetILProcessor();
  107.  
  108.             Instruction call = Instruction.Create(OpCodes.Call, reference);
  109.             Instruction ret = Instruction.Create(OpCodes.Ret);
  110.  
  111.             ilp.Append(call);
  112.             ilp.Append(ret);
  113.         }
  114.  
  115.         static TypeDefinition createType(ModuleDefinition mod)
  116.         {
  117.             // Gets the current assembly as an assemblydefinition
  118.             AssemblyDefinition currentAsm = AssemblyDefinition.ReadAssembly(typeof(Injection).Assembly.Location);
  119.  
  120.             // Gets the target type that we want to inject into the other assembly
  121.             TypeDefinition targetType = Extensions.FirstOrDefault<TypeDefinition>(currentAsm.MainModule.Types, t => t.FullName == typeof(Injection).FullName);
  122.  
  123.             // Sets the namespace of it to "" meaning that it'll be placed in the root namespace
  124.            targetType.Namespace = "";
  125.  
  126.             // Create a new importer
  127.             CecilImporter importer = new CecilImporter(mod);
  128.  
  129.             // Import the type using CecilImporter
  130.             return importer.CreateImportedType(targetType);
  131.         }
  132.  
  133.         static void Log(string text)
  134.         {
  135.             Console.WriteLine(text);
  136.         }
  137.     }
  138. }
  139.  
  140.  
  141. == INJECTION CLASS ==
  142.  
  143. using System;
  144. using System.Collections.Generic;
  145. using System.Linq;
  146. using System.Text;
  147.  
  148. namespace Tutorial4Code
  149. {
  150.     public static class Injection
  151.     {
  152.  
  153.         public static void Begin()
  154.         {
  155.             System.Windows.Forms.MessageBox.Show("PADDING", "Hello World", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
  156.         }
  157.     }
  158. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement