2011-01-29 12 views
8

多かれ少なかれそれはすべてです。 this記事に基づいて、私はこれを作ってみた:これが実際に動作実行時にメソッドにILを注入する方法

public static unsafe void Replace(this MethodBase destination, MethodBase source) 
{ 
    IntPtr srcHandle = source.MethodHandle.GetFunctionPointer(); 
    IntPtr dstHandle = destination.MethodHandle.GetFunctionPointer(); 

    int* dstPtr = (int*)dstHandle.ToPointer(); 
    *dstPtr = srcHandle.ToInt32(); 
} 

...例えば時折-.-

を、これは動作します。

public static class Program 
{ 
    public static void Main(string[] args) 
    { 
     MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static); 
     MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static); 

     methodA.Replace(methodB); 

     A(); 
     B(); 
    } 

    public static void A() 
    { 
     Console.WriteLine("Hai World"); 
    } 

    public static void B() 
    { 
     Console.WriteLine("Bai World"); 
    } 
} 

ただし、これは(SEHException)ではありません。私がしたことは、関数が定義された順序を変更することでした。

public static class Program 
{ 
    public static void Main(string[] args) 
    { 
     MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static); 
     MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static); 

     methodA.Replace(methodB); 

     A(); 
     B(); 
    } 

    public static void B() 
    { 
     Console.WriteLine("Bai World"); 
    } 

    public static void A() 
    { 
     Console.WriteLine("Hai World"); 
    } 
} 

記事のコードは...私はそれがまったく動作するようにはできませんでした。

アイデア/代替品はありますか?

+0

なぜこれをやりたいですか?これは恐ろしい考えのように聞こえる。 – Amy

+2

悪意のあるものはありません。ちょうど知識のために:D – YellPika

+0

これを行う唯一の安全な方法は、アセンブリがロードされる前にコードを注入することだと思います。 – porges

答えて

8

これは、お尻にあなたをかむ悪い仮定をたくさん作っています。

まず最初に、リフレクションによって返された構造体は、どのランタイム構造体もまったく指すことが保証されていません。したがって、それが含まれているか返されているポインタを変更しようとすると、間違っているだけです。

第2に、プリ/ポストメソッドコールインバリアント(例として)を注入するようなことをしたいのであれば、おそらくランタイムプロキシオブジェクトを構築してそれらを注入するべきでしょう。または、Emit名前空間で動的メソッド構築を使用します。文書化されていない動作/未知の動作(上記のコードなど)を介して操作しようとすると動作しません。

また、JITがいつ実行するかを決定することを理解する必要があります。クラス全体に対して実行されることもあれば、単一のメソッドに対して実行されることもあります。あなたのコードは、メソッドがまだJITされているかどうかを調べることを試みておらず、返された関数ポインタが変更可能であると盲目的に仮定しています。

+0

私はその名前が大好きで、私はショーを愛していました。良い一日を! – Amy

+0

その場合... a)それでは、正確にそれは何を指していますか? b)メソッドがJITされているかどうかを確認するにはどうすればよいですか? – YellPika

+0

b)実行前にプログラムがNGenで処理されていない限り、実行できません。 – Amy

関連する問題