[STATUS: ONLINE] 当サイトは要約付きのエンジニア向けFeedです。

TechDistill.dev

[DISCLAIMER] 当サイトの要約は正確性を保証しません。気になる記事は必ず原文を確認してください。
cd ..

【要約】12 バイトで .NET メソッドの行き先を変える [Qiita_Trend] | Summary by TechDistill

> Source: Qiita_Trend
Execute Primary Source

// Problem

開発者は、実行中のメソッドの挙動を動的に変更したい。既存コードを書き換えずに制御を奪う手法が必要だ。しかし、従来の手段では以下の課題に直面する。
  • 呼び出し側のコードを特定し、call命令を差し替える膨大なコスト。
  • ILレベルの書き換えでは、JIT後のネイティブコードを直接制御できない。
  • 5バイトの相対ジャンプでは、ジャンプ先が2GBの範囲外だと機能しない。

// Approach

著者は、JIT後のネイティブコードの入り口を直接書き換える手法を採用した。実装手順は以下の通りだ。
  • RuntimeHelpers.PrepareMethod を使い、対象メソッドを事前にJITコンパイルする。
  • ResolveRealEntry を用いて、実際の実行アドレスを特定する。
  • 12バイトの命令 mov rax, imm64; jmp rax で、64ビット絶対アドレスへのジャンプを実現する。
  • VirtualProtect 等で、書き込み不可のメモリ領域に一時的な権限を付与する。

// Result

実験の結果、呼び出し側のコードを一切変更せずに、メソッドの挙動を完全に制御することに成功した。
  • DateTime.Now の戻り値を西暦9999年に固定するなどの改道を実現した。
  • 12バイトの絶対ジャンプにより、広範なアドレスへの遷移が可能となった。
  • 元の命令を保存する仕組みにより、Hookの解除と元の状態への復元も可能である。

Senior Engineer Insight

> 本手法は極めて強力だが、実戦投入には高いリスクが伴う。現場での評価は以下の通りだ。
  • 運用リスク: 書き換え中の命令実行によるプロセス停止の懸念がある。
  • デバッグ性: 実行時の制御フローが隠蔽され、事後解析が困難になる。
  • 適用範囲: プロダクションでの常用は避け、高度なデバッグ等に限定すべきだ。

[ RELATED_KERNELS_DETECTED ]

cd ..

> System.About()

TechDistillは、膨大な技術記事から情報の真髄(Kernel)のみを抽出・提示します。