I have access to a function body Intermediate Language like this :
byte[] ilCodes = NestedFooInfo.GetMethodBody().GetILAsByteArray();
I am able to modify its IL code so that before executing the method body I call the following method named OnChangeField
:
public static void OnChangeField()
{
Console.WriteLine("VICTORY");
return;
}
So far I do it like this :
I define the call instruction to the method I want to call:
MethodInfo OnStfld = typeof(MethodBoundaryAspect).GetMethod("OnChangeField");
byte[] callIL = new byte[5];
callIL[0] = (byte)OpCodes.Call.Value;
callIL[1] = (byte)(OnStfld.MetadataToken & 0xFF);
callIL[2] = (byte)(OnStfld.MetadataToken >> 8 & 0xFF);
callIL[3] = (byte)(OnStfld.MetadataToken >> 16 & 0xFF);
callIL[4] = (byte)(OnStfld.MetadataToken >> 24 & 0xFF);
Notice that OnChangeField is located in the MethodBoundaryAspect Class. This class is located outside the assembly of the method beeing edited.
And this is how I alter the original(NestedFoo(...)
) method body :
byte[] ilCodes = NestedFooInfo.GetMethodBody().GetILAsByteArray();
InjectionHelper.UpdateILCodes(NestedFooInfo, callIL.Concat(ilCodes).ToArray());
And I get a :
System.BadImageFormatException: 'Index not found. (Exception from HRESULT: 0x80131124)'
But only if the hooking method OnChangeField
is outside (or so I understood) the executing assemly. If I move OnChangeField
in the same class as NestedFoo or in another class of NestedFoo
's assembly, it works perfectly.
I understand that the metadatatoken points towards a memory location which isn't valid. Is there a way to change that ?
For references here is : what the method body of the altered method looks like:
public class ExceptionHandlingService : IExceptionHandlingService
{
public static string var1 = "initialValue";
public static string Var2 { get; set; } = "initialValue";
public string var3 = "initialValue";
public string Var4 { get; set; } = "initialValue";
public string NestedFoo(SampleClass bar)
{
var1 = "value set in NestedFoo()";
Var2 = "value set in NestedFoo()";
var3 = "value set in NestedFoo()";
Var4 = "value set in NestedFoo()";
AddPerson("From", "NestedFoo", 2);
return Foo();
}
[...]
}
and how I call the altered method :
var a = new ExceptionHandlingService();
var b = new SampleClass("bonjour", 2, 3L); // Not really relevant
a.NestedFoo(b);
For those who wonder what magic happens in
InjectionHelper.UpdateILCodes(NestedFooInfo, newIlCodes);
you can check this link which shows how you can edit Il code at runtime.
You need to add records to MemberRef
and consecutively TypeRef
or TypeSpec
metadata tables to contain references to types and reference these tokens. This also involves properly writing signature blobs.
See Partition II 22.38, 22.25 of ECMA-335
User contributions licensed under CC BY-SA 3.0