我使用单声道塞西尔在另一种方法来注入代码。 我想补充在我的代码try-catch块。
所以我写了一个与HelloWorld.exe的一个try catch块和反编译它。
它看起来像这样在反射器在try-catch:
.try L_0001 to L_0036 catch [mscorlib]System.Exception handler L_0036 to L_003b
我怎样才能通过注入单塞西尔一个尝试捕捉这样吗?
我使用单声道塞西尔在另一种方法来注入代码。 我想补充在我的代码try-catch块。
所以我写了一个与HelloWorld.exe的一个try catch块和反编译它。
它看起来像这样在反射器在try-catch:
.try L_0001 to L_0036 catch [mscorlib]System.Exception handler L_0036 to L_003b
我怎样才能通过注入单塞西尔一个尝试捕捉这样吗?
添加例外处理程序与Mono.Cecil能做到并不难,它只是需要你知道的异常处理程序如何在元数据布局。
让我们假设你有C#的方法:
static void Throw ()
{
throw new Exception ("oups");
}
如果你编译它,它应该看起来有点类似于此:
.method private static hidebysig default void Throw () cil managed
{
IL_0000: ldstr "oups"
IL_0005: newobj instance void class [mscorlib]System.Exception::.ctor(string)
IL_000a: throw
}
现在,让我们说,你想在这个方法中注入代码,比如它类似于C#代码:
static void Throw ()
{
try {
throw new Exception ("oups");
} catch (Exception e) {
Console.WriteLine (e);
}
}
也就是说,你只是想换行现有的代码在一个try catch处理。 你可以很容易地塞西尔做到这一点是这样的:
var method = ...;
var il = method.Body.GetILProcessor ();
var write = il.Create (
OpCodes.Call,
module.Import (typeof (Console).GetMethod ("WriteLine", new [] { typeof (object)})));
var ret = il.Create (OpCodes.Ret);
var leave = il.Create (OpCodes.Leave, ret);
il.InsertAfter (
method.Body.Instructions.Last (),
write);
il.InsertAfter (write, leave);
il.InsertAfter (leave, ret);
var handler = new ExceptionHandler (ExceptionHandlerType.Catch) {
TryStart = method.Body.Instructions.First (),
TryEnd = write,
HandlerStart = write,
HandlerEnd = ret,
CatchType = module.Import (typeof (Exception)),
};
method.Body.ExceptionHandlers.Add (handler);
此代码操纵以前的方法是这样的:
.method private static hidebysig default void Throw () cil managed
{
.maxstack 1
.try { // 0
IL_0000: ldstr "oups"
IL_0005: newobj instance void class [mscorlib]System.Exception::'.ctor'(string)
IL_000a: throw
} // end .try 0
catch class [mscorlib]System.Exception { // 0
IL_000b: call void class [mscorlib]System.Console::WriteLine(object)
IL_0010: leave IL_0015
} // end handler 0
IL_0015: ret
}
我们增加了三个新的指示:Console.WriteLine,打电话请假优雅的退出catch处理程序,最后(双关语意),一个RET。 然后,我们只是创建一个的ExceptionHandler实例来表示一个try catch处理程序,其试涵盖了现有机构,而其前提条件是该声明的WriteLine。
需要注意的重要一点是,一定范围的结束指令没有包含在范围之内。 这基本上是一个[TryStart:TryEnd [范围。