Dynamically Writing and Executing Native Assembly in C# より
.NET Framework 2.0 では Marshal.GetDelegateForFunctionPointer() っていうのが追加されます。こいつは、「PInvoke する DLL を Load/Unload する方法」 で紹介したみたいに GetProcAddress() API で取得した関数ポインタなんかを .NET な delegate に変換するってのが普通の使い方だと思います。
んが、関数ポインタと言ったって特別なものではなく .NET 的には単なる IntPtr です。そこで、Marshal.AllocCoTaskMem() したメモリに適当なバイト列 (実は x86 コードになってる) を用意しておいて、その先頭アドレスを Marshal.GetDelegateForFunctionPointer() に渡せば delegate にできるってことになります。
っていうのを具体的にサンプルコードで示してるのが上記の blog です。インラインアセンブラならぬインラインマシン語ですね。すんげぇw
>Marshal.AllocCoTaskMem() したメモリに適当なバイト列 (実は x86 コードになってる) を用意しておい
返信削除>て、その先頭アドレスを Marshal.GetDelegateForFunctionPointer() に渡せば delegate にできる
>ってことになります。
XPSP2 以降では、NX bit チェックにより無効かも。
うーん、コードセグメント内なんだろうか>TaskMemAlloc で帰ってくる場所
返信削除セグメントは、どっちかというとロードモジュール(=ファイル)のための概念だよん。
返信削除NX bit と関係が深いのは、仮想記憶が管理する「ページ」の実行属性すね。
ローダが
・コードセグメントの内容は実行属性の付いたページに読み込む
・初期化データ有りのデータセグメントは実行属性の無いページに読み込む
・初期化データの無いデータセグメントは実行属性の無いページを確保して0爆弾投下
という作業を行ってからプログラムの実行が開始されるわけですが、NX bit サポート付きの x86 では、「実行属性の無いページに置かれたコード」を実行しようとすると、例外が発生します。
(cpu レベルではソフトウェア割り込みかな?)
ただし、これまでの、NX bit サポートの無い x86 では「実行属性が無いページにあるコード」も実行できちゃうのよね ;-p
実行属性付きのメモリ確保は、VirtualXXX 系でしかできないんじゃないかな?
えーと、著者さんはちゃんとわかってるようで、記事の一番下のところに
返信削除このサンプルでは Marshal.AllocCoTaskMem() を使ってるけど、コードが
PAGE_EXECUTE アクセスを持つページに確実にできるようにするために P/Invoke で
VirtualAllocEx と VirtualProtectEx を使うようにすべき
と書いてあります。
# しかし、こういうネタは食いつきがいいなぁ(笑)
パクっw
返信削除