WinDbgを使用して実行中のプロセスにアタッチし、特定の関数のコードを変更して、呼び出しを返すだけにします(教育目的で)。
次のコマンドを使用しました。
uf dll!name
これにより、関数が分解されます。
特定の場所で特定のアドレスを選択し、それをretに変更しました:
ew addr c3
これは毎回クラッシュします、私は何が間違っているのですか?
WinDbgを使用して実行中のプロセスにアタッチし、特定の関数のコードを変更して、呼び出しを返すだけにします(教育目的で)。
次のコマンドを使用しました。
uf dll!name
これにより、関数が分解されます。
特定の場所で特定のアドレスを選択し、それをretに変更しました:
ew addr c3
これは毎回クラッシュします、私は何が間違っているのですか?
スタックが適切な状態のままになるように、適切なクリーンアップを実行する必要があります。呼び出し規約にもよりますが、メソッドは通常、プロローグの一部としてスタックにデータをプッシュします。これは、エピローグの一部として元に戻す必要があります。
WinDbgを使用してJITコンパイル済みメソッドを変更する例を次に示します。
コード:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Message();
Console.ReadLine();
Message();
Console.WriteLine("done");
}
private static void Message()
{
Console.WriteLine("message");
}
}
}
コンパイラがへの呼び出しをインライン化しないように、これをDebugとしてコンパイルしましたMessage
。
次に、実行可能ファイルを実行し、の呼び出しでデバッガーを接続しましたReadLine
。
マネージコードの場合、SOS.dllを使用してJITコンパイル済みコードを見つける必要があります。そこで、SOSをロードして、次のようにコードのアドレスを見つけました。
0:004> .loadby sos clr
0:004> !name2ee *!ConsoleApplication1.Program
Module: 04a11000
Assembly: mscorlib.dll
--------------------------------------
Module: 001b2e94
Assembly: ConsoleApplication1.exe
Token: 02000002
MethodTable: 001b37b4
EEClass: 001b125c
Name: ConsoleApplication1.Program
0:004> !dumpmt -md 001b37b4
EEClass: 001b125c
Module: 001b2e94
Name: ConsoleApplication1.Program
mdToken: 02000002
File: c:\temp\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe
BaseSize: 0xc
ComponentSize: 0x0
Slots in VTable: 7
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
Entry MethodDe JIT Name
04d14960 04a16728 PreJIT System.Object.ToString()
04d08790 04a16730 PreJIT System.Object.Equals(System.Object)
04d08360 04a16750 PreJIT System.Object.GetHashCode()
04d016f0 04a16764 PreJIT System.Object.Finalize()
001bc019 001b37ac NONE ConsoleApplication1.Program..ctor()
002a0050 001b3794 JIT ConsoleApplication1.Program.Main(System.String[])
002a00a8 001b37a0 JIT ConsoleApplication1.Program.Message()
0:004> !u 001b37a0
Normal JIT generated code
ConsoleApplication1.Program.Message()
Begin 002a00a8, size 21
*** WARNING: Unable to verify checksum for c:\temp\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe
c:\temp\ConsoleApplication1\ConsoleApplication1\Program.cs @ 20:
002a00a8 55 push ebp <-- prologue
002a00a9 8bec mov ebp,esp
002a00ab 833d60311b0000 cmp dword ptr ds:[1B3160h],0 <-- start of method
002a00b2 7405 je ConsoleApplication1!ConsoleApplication1.Program.Message()+0x11 (002a00b9)
002a00b4 e8fb6ff570 call clr!JIT_DbgIsJustMyCode (711f70b4)
002a00b9 90 nop
c:\temp\ConsoleApplication1\ConsoleApplication1\Program.cs @ 21:
002a00ba 8b0d34217403 mov ecx,dword ptr ds:[3742134h] ("message")
002a00c0 e82bd3ad04 call mscorlib_ni!System.Console.WriteLine(System.String) (04d7d3f0)
002a00c5 90 nop
c:\temp\ConsoleApplication1\ConsoleApplication1\Program.cs @ 22:
002a00c6 90 nop
002a00c7 5d pop ebp <-- epilogue
002a00c8 c3 ret
次に、[メモリ]ウィンドウを開き、実際のメソッド本体の最初の部分である002a00abをポイントしMessage
、2つのオペコードをそれぞれとに変更し5d
ましc3
た。その部分をスキップすると、スタックが台無しになり、例外が発生します。pop edb
ret
pop edb
Goを押すと、アプリケーションは「メッセージ」を2回印刷せずに続行しました。