添加一个try-catch与单塞西尔(Add a try-catch with Mono Cecil

2019-07-30 00:21发布

我使用单声道塞西尔在另一种方法来注入代码。 我想补充在我的代码try-catch块。

所以我写了一个与HelloWorld.exe的一个try catch块和反编译它。

它看起来像这样在反射器在try-catch:

.try L_0001 to L_0036 catch [mscorlib]System.Exception handler L_0036 to L_003b

我怎样才能通过注入单塞西尔一个尝试捕捉这样吗?

Answer 1:

添加例外处理程序与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 [范围。



文章来源: Add a try-catch with Mono Cecil
标签: c# mono.cecil