2012-08-22 85 views
2

我想使用WinDbg附加到正在運行的進程,並修改某個函數的代碼以簡單地返回調用(用於教育目的)。使用WinDbg在運行時修改函數內容

我用下面的命令:

UF DLL名稱

這使我的函數的拆卸。

我已經在某個位置選擇了一個特定的地址,並修改它RET

EW地址C3

這個崩潰每一次,我究竟做錯了什麼?

+0

你也插入了epilogue代碼嗎?見http://en.wikipedia.org/wiki/Function_prologue#Epilogue –

+0

函數的調用約定是什麼? – Neil

+0

其實它的聲明是什麼? – Neil

回答

5

你需要確保你做了適當的清理,以便堆棧保持適當的狀態。根據調用約定,該方法通常將堆棧中的東西作爲prologue的一部分。作爲結語的一部分,這必須被撤消。

下面是使用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"); 
     } 
    } 
} 

我編這是調試,以防止編譯器內聯調用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實際方法主體的第一部分和改變兩個操作碼到5dc3分別pop edbret。如果我跳過了pop edb部分,堆棧就會混亂,我會得到一個異常。

我打開Go,應用程序繼續不打印「消息」的第二次。

+0

謝謝。你是如何改變這兩個操作碼的?您使用了哪個命令 –

+1

@ lysergic-acid可以通過直接更改Memory窗口中的值來更改操作碼。 –

+0

你也可以使用'e'命令(eb,ew,ed,eq)。編輯內存窗口更容易。我只是提到完整性。 –