Skip to content

Instantly share code, notes, and snippets.

@HurricanKai
Created September 25, 2018 10:04
Show Gist options
  • Select an option

  • Save HurricanKai/3c8354d952d6c6bb72d9a6f0e5501d75 to your computer and use it in GitHub Desktop.

Select an option

Save HurricanKai/3c8354d952d6c6bb72d9a6f0e5501d75 to your computer and use it in GitHub Desktop.
Repointing Types isnt fun
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using OpCodes = System.Reflection.Emit.OpCodes;
namespace Test
{
public static class Repointer
{
private static void Repoint()
{
var location = Assembly.GetExecutingAssembly().Location;
var definition = AssemblyDefinition.ReadAssembly(location);
definition = OverrideFunction(definition, nameof(Test), nameof(Test.WriteA),
definition, nameof(Test), nameof(Test.WriteB));
definition.Write("Patched.dll");
patched = Assembly.Load(File.ReadAllBytes("Patched.dll"));
File.Delete("Patched.dll");
}
public static AssemblyDefinition OverrideFunction(
AssemblyDefinition target, string targetClass, string targetMethode,
AssemblyDefinition from, string fromClass, string fromMethode)
{
TypeDefinition fromClassDef = from.MainModule.GetType("Test", fromClass);
if (fromClassDef == null)
throw new Exception($"Source {from.FullName}/{fromClass} not found");
TypeDefinition toClassDef = target.MainModule.GetType("Test", targetClass);
if (toClassDef == null)
throw new Exception($"Target {target.FullName}/{targetClass} not found");
MethodDefinition copyFromMethode = fromClassDef.Methods.FirstOrDefault(method => method.Name == fromMethode);
if (copyFromMethode == null)
throw new Exception($"Target {from.FullName}.{fromClass}.{fromMethode} not found");
MethodDefinition copyToMethode = toClassDef.Methods.FirstOrDefault(method => method.Name == targetMethode);
if (copyToMethode == null)
throw new Exception($"Source {target.FullName}.{targetClass}.{targetMethode} not found");
ILProcessor copyFromProcessor = copyFromMethode.Body.GetILProcessor();
ILProcessor copyToProcessor = copyToMethode.Body.GetILProcessor();
Collection<Instruction> copyFromMethodeIL = copyFromProcessor.Body.Instructions;
Collection<Instruction> copyToMethodeIL = copyToProcessor.Body.Instructions;
Console.WriteLine("Copying Instructions:");
Console.WriteLine();
copyToMethodeIL.Clear();
for (int i = 0; i < copyFromMethodeIL.Count; i++)
{
Console.WriteLine(copyFromMethodeIL[i].OpCode.Name);
copyToMethodeIL.Add(copyFromMethodeIL[i]);
}
Console.WriteLine();
Console.WriteLine("Written");
Console.WriteLine("To Confirm, here are the Instructions Read again:");
Console.WriteLine();
foreach (var instruction in copyToMethodeIL)
{
Console.WriteLine(instruction.OpCode.Name);
}
Console.WriteLine();
Console.WriteLine("Please work...");
return target;
}
private static Assembly patched;
public static Assembly Patched { get { if (patched == null) Repoint(); return patched; } }
}
public static class ActualMain
{
public static void Main(string[] args)
{
try
{
Test.WriteA();
Console.WriteLine("Repointing");
// Repoint();
Console.WriteLine("Repointed");
Test.WriteA();
Console.ReadLine();
}
finally
{
}
}
}
class Program
{
static void Main(string[] args)
{
// Lets first call initial nonrepointed Test.WriteA()
Test.WriteA();
// First we create a temp Assembly
var name = new AssemblyName("InMemory");
var a = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndCollect);
var mB = a.DefineDynamicModule(name.Name);
// Then we define the Type "TestType"
var tb = mB.DefineType("TestType", System.Reflection.TypeAttributes.Public);
// Create a Constructor
var ctor = tb.DefineConstructor(System.Reflection.MethodAttributes.Public, CallingConventions.Standard, new Type[0]);
var ctorIL = ctor.GetILGenerator();
// and add a Call to the Test Type in the *Repointed* Assembly
var repointedTest = Repointer.Patched.GetType(/* The Namespace */"Test." + nameof(Test));
var repointedMethod = repointedTest.GetMethod(nameof(Test.WriteA));
ctorIL.EmitCall(OpCodes.Call, repointedMethod, new Type[0]);
ctorIL.Emit(OpCodes.Ret);
// Next we call the just created type
// We just told it to in its constructor call the Test.WriteA() Methode in the *Repointed* Assembly
var testType = tb.CreateType();
var testCtor = testType.GetConstructor(new Type[0]);
var v = testCtor.Invoke(new object[0]);
// v in theory shoud now be "TestType"
Console.ReadLine();
}
}
public static class Test
{
public static void WriteA()
{
Console.WriteLine("1");
Console.WriteLine("2");
// ret;
}
public static void WriteB()
{
Console.WriteLine("C");
Console.WriteLine("B");
// ret;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment