About This Tutorial
This tutorial will cover how to implement function alterations to a managed target using Mono.Cecil. As far as I know Mono.Cecil only works for recreating a binary before it is loaded. I am not sure if it will allow runtime reconstruction, nor have I tried to get it to so. So if you know if it can please do let me know.

This tutorial will cover hooking onto an XNA application.
Legal Bullshit No One Reads
This is a tutorial for research purposes only. I am not responsible for what you do with this material. You agree that by reading this that you take full responsibility of your actions. I am not responsible for what you do with this information!
Tools Needed- Visual Studio 2010 (http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-csharp-express)
- XNA Game Studio 4 (http://www.microsoft.com/download/en/details.aspx?id=23714)
- Mono.Ceci
- Download: http://www.mediafire.com/?pxn1ym9ds9op5iq
- Credits / Info: http://www.mono-project.com/Cecil
- .NET Target To Hook (I will be using Terraria as the example.)
- IL Disassembler if you wish to view the IL code with ease. (VS2010 comes with ildasm which you can run from the VS command line.)
- ILSpy: http://wiki.sharpdevelop.net/ilspy.ashx
Getting Started
To start, we'll be working on attaching onto XNA's main functions for a normal game. Since Terraria is written in C# using XNA we can see that it inherits 'Game' in its main class.
If we use a .NET object browser we can see what Game contains. For the sake of this tutorial you can find the members here:
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game_members%28v=xnagamestudio.40%29.aspx
So we are mainly interested in:
- Initialize
- LoadContent
- Update
- Draw
Like most hacks we will want pre/post hooks for each of these functions. This will allow us to handle things before and after the actual call occurs.
Preparing Our Project
We'll start by making a new XNA game, it is easier to do this since it will add all the XNA references for us even though we don't need any of the actual game code it makes. So start by opening VS2010 and going to:
File -> New -> Project -> C# -> XNA Game Studio 4.0 -> Windows Game (4.0)
Next, we'll remove the Content project because its useless to us (unless you plan to add custom content). So right-click the Content project and remove it. You will also need to remove the content reference in the main project's Content References if it wasn't removed automatically.
Next, we'll delete Game1.cs since we don't need it.
Create a new class, call it whatever you want. In this case I'm calling it Hooks.cs
Preparing Our Hooks Class
To start we will need four main class variables, one for the loaded assembly definition, one for the main module definition, one for the complete assembly, and one for the assemblies main class type. So we will add:
PHP Code:
private AssemblyDefinition m_vAsmDefinition = null;
private ModuleDefinition m_vModDefinition = null;
private Assembly m_vAssembly = null;
private Type m_vMainType = null;
Next we will write an initialize function to load our target into our assembly definition and obtain its main module for the module definition:
PHP Code:
public bool Initialize()
{
try
{
this.m_vAsmDefinition = AssemblyDefinition.ReadAssembly("Terraria.exe");
this.m_vModDefinition = this.m_vAsmDefinition.MainModule;
return true;
}
catch { return false; }
}
Next we'll write the finalization function to finish up our modifications and prepare the new assembly for usage:
PHP Code:
public bool Finialize()
{
try
{
// Validate we've loaded the main executable first..
if (this.m_vAsmDefinition == null)
return false;
using (MemoryStream mStream = new MemoryStream())
{
// Write the edited data to the memory stream..
this.m_vAsmDefinition.Write(mStream);
// Load the new assembly from the memory stream buffer..
this.m_vAssembly = Assembly.Load(mStream.GetBuffer());
return true;
}
}
catch { return false; }
}
Next, we need to create a call to run the new assembly rather then using the one on the disk. Since we have the assembly written in memory we can load it in memory as well, so we'll write our Run function like this:
PHP Code:
public bool Run()
{
try
{
if (this.m_vAssembly == null)
return false;
// Get the main class type..
this.m_vMainType = this.m_vAssembly.GetType("Terraria.Main");
// Create the constructor call..
var constructor = this.m_vMainType.GetConstructor(new Type[] { }).Invoke(null);
// Obtain the main run method and invoke it..
var method = this.m_vMainType.GetMethod("Run", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
method.Invoke(constructor, null);
return true;
}
catch { return false; }
}
Now that we have our base done, we can setup the program to run this new instance of the assembly.
Inside of Program.cs, inside of Main() replace everything with:
PHP Code:
static void Main(string[] args)
{
var hooks = new Hooks();
hooks.Initialize();
hooks.Finialize();
hooks.Run();
}
Now you can test if the base hooking works by running your wrapper etc. to make sure its working as expected.
Hooking Onto Our Functions..
Next we want to hook onto the functions. Simple enough, Pre* hooks just get called at the start of the function, while Post* at the end.
(Please see the note below at the end of this tutorial, you may need to do more work in some cases for some hooks to work properly!)
We'll start with Initialize. Inside our Hooks class lets add two functions PreInitialize and PostInitialize following the same method definition from MSDN for Initialize. For now we'll out some console outputs to determine if they get called. (Be sure that these are marked public and static or you will get runtime errors!)
PHP Code:
public static void PreInitialize()
{
System.Diagnostics.Debug.WriteLine("Custom PreInitialize was called!");
}
public static void PostInitialize()
{
System.Diagnostics.Debug.WriteLine("Custom PostInitialize was called!");
}
Our next step involves digging into Mono.Cecil's abilities. We'll make a new function to apply our hooks. So lets call that ApplyHooks for now. To start, we need to locate the method inside our main type. I wrote wrappers for making these parts easier. These are the wrappers I wrote for these next steps:
PHP Code:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Object Reflection From New Terraria Objects
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Gets a method definition from the new Terraria executable.
/// </summary>
/// <param name="t"></param>
/// <param name="methodName"></param>
/// <returns></returns>
public MethodDefinition GetMethodDefinition(TypeDefinition t, String methodName)
{
return (from MethodDefinition m in t.Methods
where m.Name == methodName
select m).FirstOrDefault();
}
/// <summary>
/// Gets a field definition from the new Terraria executable.
/// </summary>
/// <param name="t"></param>
/// <param name="fieldName"></param>
/// <returns></returns>
public FieldDefinition GetFieldDefinition(TypeDefinition t, String fieldName)
{
return (from FieldDefinition f in t.Fields
where f.Name == fieldName
select f).FirstOrDefault();
}
/// <summary>
/// Gets a property definition from the new Terraria executable.
/// </summary>
/// <param name="t"></param>
/// <param name="propName"></param>
/// <returns></returns>
public PropertyDefinition GetPropertyDefinition(TypeDefinition t, String propName)
{
return (from PropertyDefinition p in t.Properties
where p.Name == propName
select p).FirstOrDefault();
}
/// <summary>
/// Gets a type definition from the new Terraria executable.
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
public TypeDefinition GetTypeDefinition(String typeName)
{
return (from TypeDefinition t in this.m_vModDefinition.Types
where t.Name == typeName
select t).FirstOrDefault();
}
/// <summary>
/// Gets a type from within the new Terraria executable.
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
public Type GetType(String typeName)
{
return (from Type t in this.m_vAssembly.GetTypes()
where t.Name == typeName
select t).FirstOrDefault();
}
/// <summary>
/// Gets a method from within Terraria.Main.
/// </summary>
/// <param name="methodName"></param>
/// <returns></returns>
public MethodInfo GetMethod(String methodName)
{
return (from MethodInfo m in this.m_vMainType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
where m.Name == methodName
select m).FirstOrDefault();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Object Reflection From New Terraria.Main Object
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Gets the value of a field within Terraria.Main.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fieldName"></param>
/// <returns></returns>
public T GetMainField<T>(String fieldName)
{
var field = (from FieldInfo f in this.m_vMainType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
where f.Name == fieldName
select f).FirstOrDefault();
if (field == null)
return default(T);
return (T)field.GetValue(this.m_vMainType);
}
/// <summary>
/// Sets the value of a field within Terraria.Main.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fieldName"></param>
/// <param name="objValue"></param>
public void SetMainField<T>(String fieldName, T objValue)
{
var field = (from FieldInfo f in this.m_vMainType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
where f.Name == fieldName
select f).FirstOrDefault();
if (field == null)
return;
field.SetValue(this.m_vMainType, objValue);
}
So now we can easily locate the method for Initialize using:
PHP Code:
MethodDefinition initMethod = GetMethodDefinition(GetTypeDefinition("Main"), "Initialize");
Next we want to inject our 'PreInitialize' call to the start of this method. We can do that by using:
PHP Code:
MethodDefinition initMethod = GetMethodDefinition(GetTypeDefinition("Main"), "Initialize");
var initProc = initMethod.Body.GetILProcessor();
initProc.InsertBefore(initMethod.Body.Instructions[0], initProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PreInitialize", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
We can run the test app again and see if it gets called, in the output window you should see:
Custom PreInitialize was called!
Great now we want to add our PostInitialize call to the end of the function. If we look at the all in a IL decoder (such as ILSpy) we can see the Initialize call ends with:
So we need to inject before this return:
PHP Code:
initProc.InsertBefore(initMethod.Body.Instructions[initMethod.Body.Instructions.Count - 2], initProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PostInitialize", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
So now we have in total for our Initialize hooks:
PHP Code:
public void ApplyHooks()
{
MethodDefinition initMethod = GetMethodDefinition(GetTypeDefinition("Main"), "Initialize");
var initProc = initMethod.Body.GetILProcessor();
initProc.InsertBefore(initMethod.Body.Instructions[0], initProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PreInitialize", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
initProc.InsertBefore(initMethod.Body.Instructions[initMethod.Body.Instructions.Count - 2], initProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PostInitialize", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
}
Next we'll do the same for LoadContent, add the Pre and Post methods:
PHP Code:
public static void PreLoadContent()
{
System.Diagnostics.Debug.WriteLine("Custom PreLoadContent was called!");
}
public static void PostLoadContent()
{
System.Diagnostics.Debug.WriteLine("Custom PostLoadContent was called!");
}
And then for our hook it will be similar to Initializes hook:
PHP Code:
MethodDefinition contMethod = GetMethodDefinition(GetTypeDefinition("Main"), "LoadContent");
var contProc = contMethod.Body.GetILProcessor();
contProc.InsertBefore(contMethod.Body.Instructions[0], contProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PreLoadContent", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
contProc.InsertBefore(contMethod.Body.Instructions[contMethod.Body.Instructions.Count - 2], contProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PostLoadContent", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
Hooking Onto Update and Draw
Next, we want to hook onto Update and Draw. The difference here is that we now have functions that take arguments. In this case a 'GameTime' object which holds the time of the current XNA game. Looking at some of the function in a diassembler we'll see that using the GameTime object will look like this:
PHP Code:
IL_1922: ldarg.0
IL_1923: ldarg.1
IL_1924: call instance void [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.Game::Update(class [Microsoft.Xna.Framework.Game]Microsoft.Xna.Framework.GameTime)
IL_1929: ret
We see that two arguments are being pushed to Update. That's because this is a class method so ldarg.0 is the base Game object, and ldarg.1 is the GameTime object. So let's add our handlers first for Update:
PHP Code:
public static void PreUpdate(GameTime gameTime)
{
}
public static void PostUpdate(GameTime gameTime)
{
}
Next we'll do the similar stuff to get the function. But we will add an extra opcode to push the gameTime argument:
PHP Code:
MethodDefinition updateMethod = GetMethodDefinition(GetTypeDefinition("Main"), "Update");
var updateProc = updateMethod.Body.GetILProcessor();
var updateInst = updateMethod.Body.Instructions[0];
updateProc.InsertBefore(updateInst, updateProc.Create(OpCodes.Ldarg_1)); // push gameTime
updateProc.InsertBefore(updateInst, updateProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PreUpdate", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
Now, if you wish you could push Ldarg_0 as well to your function, but you will need to add the param for the Game object.
Next we want to inject our PostUpdate call. The above IL code I posted about the Update function is the end of the function, so we know it ends with a Ret. We want to push our code, again, before the return.
PHP Code:
updateProc.InsertBefore(updateMethod.Body.Instructions[updateMethod.Body.Instructions.Count - 1], updateProc.Create(OpCodes.Ldarg_1)); // push gameTime
updateProc.InsertBefore(updateMethod.Body.Instructions[updateMethod.Body.Instructions.Count - 1], updateProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PostUpdate", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
For draw, we'll do the same thing. Add the two methods calls:
PHP Code:
public static void PreDraw(GameTime gameTime)
{
}
public static void PostDraw(GameTime gameTime)
{
}
Then we'll add our hook code the same way as Update:
PHP Code:
MethodDefinition drawMethod = GetMethodDefinition(GetTypeDefinition("Main"), "Draw");
var drawProc = drawMethod.Body.GetILProcessor();
var drawInst = drawMethod.Body.Instructions[0];
drawProc.InsertBefore(drawInst, drawProc.Create(OpCodes.Ldarg_1)); // push gameTime
drawProc.InsertBefore(drawInst, drawProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PreDraw", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
drawProc.InsertBefore(drawMethod.Body.Instructions[drawMethod.Body.Instructions.Count - 1], drawProc.Create(OpCodes.Ldarg_1));
drawProc.InsertBefore(drawMethod.Body.Instructions[drawMethod.Body.Instructions.Count - 1], drawProc.Create(OpCodes.Call,
this.m_vModDefinition.Import(typeof(Hooks).GetMethod("PostDraw", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
));
There we have it, all of the main XNA calls are now hooked as we wanted.
Hooking Other Methods
So now that we have hooked all the XNA methods, lets hook something else. In this case I will be using the collectors edition method CheckBunny. This method determines if you have the Collectors Edition of the game by looking in your Registry for a specific key. The IL of this code looks like:
PHP Code:
.try
{
IL_0000: ldsfld class [mscorlib]Microsoft.Win32.RegistryKey [mscorlib]Microsoft.Win32.Registry::CurrentUser
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldstr "Software\\Terraria"
IL_000c: callvirt instance class [mscorlib]Microsoft.Win32.RegistryKey [mscorlib]Microsoft.Win32.RegistryKey::CreateSubKey(string)
IL_0011: stloc.0
IL_0012: ldloc.0
IL_0013: brfalse.s IL_0044
IL_0015: ldloc.0
IL_0016: ldstr "Bunny"
IL_001b: callvirt instance object [mscorlib]Microsoft.Win32.RegistryKey::GetValue(string)
IL_0020: brfalse.s IL_0044
IL_0022: ldloc.0
IL_0023: ldstr "Bunny"
IL_0028: callvirt instance object [mscorlib]Microsoft.Win32.RegistryKey::GetValue(string)
IL_002d: callvirt instance string [mscorlib]System.Object::ToString()
IL_0032: ldstr "1"
IL_0037: call bool [mscorlib]System.String::op_Equality(string, string)
IL_003c: brfalse.s IL_0044
IL_003e: ldc.i4.1
IL_003f: stsfld bool Terraria.Main::cEd
IL_0044: leave.s IL_004f
} // end .try
catch [mscorlib]System.Object
{
IL_0046: pop
IL_0047: ldc.i4.0
IL_0048: stsfld bool Terraria.Main::cEd
IL_004d: leave.s IL_004f
} // end handler
IL_004f: ret
However, instead of injecting anything, we'll just rewrite the entire method. We knw that we want to set the property cEd to true. Which can be done with:
PHP Code:
IL_003e: ldc.i4.1
IL_003f: stsfld bool Terraria.Main::cEd
So we'll rewrite this method using:
PHP Code:
MethodDefinition bunnyMethod = GetMethodDefinition(GetTypeDefinition("Main"), "CheckBunny");
FieldDefinition bunnyField = GetFieldDefinition(GetTypeDefinition("Main"), "cEd");
// Clear the old function instructions..
bunnyMethod.Body.Instructions.Clear();
// Remove the exception handler..
bunnyMethod.Body.ExceptionHandlers.Clear();
// Rewrite the function..
var bunnyProc = bunnyMethod.Body.GetILProcessor();
bunnyProc.Append(bunnyProc.Create(OpCodes.Nop)); // nop for alignment
bunnyProc.Append(bunnyProc.Create(OpCodes.Ldc_I4_1)); // push true (1) onto the stack
bunnyProc.Append(bunnyProc.Create(OpCodes.Stsfld, bunnyField)); // set field to the value on stack
bunnyProc.Append(bunnyProc.Create(OpCodes.Ret)); // return
My Methods Aren't Getting Called In The Right Order!
With Terraria as an example you may notice that your XNA hooks may not be called in the right order. This is due to how Terraria is written. For example, Draw has multiple returns within it to handle drawing certain parts of the game. For instance, it will attempt to Draw the menu specifically with:
PHP Code:
IL_52dd: ldarg.0
IL_52de: call instance void Terraria.Main::DrawMenu()
IL_52e3: ret
Which will return before our PostDraw is called while we are at the main menu. There are a few ways to correct this. Without actually digging into the code here are some suggestions you can do to fix problems like:
- Hook DrawMenu and call PostDraw at the end of it to ensure your PostDraw is called. (I recommend this method.)
- Inject your PostDraw call after every Ret inside the function to ensure it gets called.
- Disassemble the code and look to see where you should place each Post call to ensure that it will always be called. (This could become a tiresome process if its a large method.)
~~~
Another fun thing you can do is use a custom attribute to automatically find methods in your application that will be applying detours/edits to the new assembly and execute them like this:
InjectionAttribute.cs
PHP Code:
// Adjust the namespace / class name as needed!
namespace toxyClient.Classes
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
/// <summary>
/// InjectionAttribute Class Implementation
///
/// Attribute used to mark a function as an injection function.
///
/// The main program class will scan the application for this
/// attribute and automatically call the functions.
/// </summary>
public class InjectionAttribute : Attribute
{
/// <summary>
/// Default Constructor
/// </summary>
/// <param name="detourName"></param>
/// <param name="detourDesc"></param>
public InjectionAttribute(String detourName, String detourDesc = "")
{
this.Name = detourName;
this.Desc = detourDesc;
}
/// <summary>
/// Gets or sets the name of this detour.
/// </summary>
public String Name { get; set; }
/// <summary>
/// Gets or sets the desc of this detour.
/// </summary>
public String Desc { get; set; }
}
}
Then in your main Program.cs code use this before you call Finalize:
PHP Code:
// Scan for detour attributes and apply their detour..
(from Type t in Assembly.GetExecutingAssembly().GetTypes()
from MethodInfo m in t.GetMethods()
from InjectionAttribute d in m.GetCustomAttributes(typeof(InjectionAttribute), false)
select m).ToList().ForEach(m => m.Invoke(null, null));
Then any function that you want to apply detours/injection stuff with to the new assembly just mark with the new custom attribute like this:
PHP Code:
/// <summary>
/// Applies the detours required by this class.
/// </summary>
[Injection("Some Name Here", "A short description about what this function is for.")]
public static void DoInjection()
{
}
This style of loading can be used on various .NET targets, not just games. Allowing you to use a loader situation to make alterations to a file rather then completely editing the binary. (You can however save the edited binary after your edits have been made if you wish too.) This is mostly a tutorial showing off Mono.Cecil and some of the advantages it has to using it.
Terraria is a fairly small XNA game that I used as the example in this tutorial. This tutorial demonstrates hooking the various XNA render pipeline functions, as well as towards the end hooking onto a game-specific function with the use of Mono.Cecil. You can fully take over functions, 'detour' them, alter bits of them etc. with Mono.Cecil allowing you to take full advantage of a .NET program.