[英]How does a debugger peek into another process' memory?
當每個進程都有自己的私有內存空間,沒有外部進程可以訪問時,調試器如何訪問進程的內存空間?
例如,我可以使用gdb -p <pid>
將gdb附加到正在運行的進程
我可以通過gdb訪問此進程的所有內存。
gdb如何做到這一點?
我在SO中閱讀了相關問題,沒有帖子似乎回答了這一點。
由於這個問題被標記為Linux和Unix,我將對David Scwartz所說的內容進行一些擴展,簡而言之就是“操作系統中有一個API”。 同樣的基本原則也適用於Windows,但實際的實現是不同的,雖然我懷疑操作系統內部的實現做了同樣的事情,但是沒有真正的方法可以知道,因為我們無法檢查Windows的源代碼(但是,可以理解操作系統和處理器的工作原理,弄清楚必須發生的事情!)
Linux有一個名為ptrace
的函數,它允許一個進程(在某些特權檢查之后)以各種方式檢查另一個進程。 這是一個電話,但第一個參數是“你想做什么”。 以下是一些最基本的例子 - 還有幾十個用於較少“常見”操作:
PTRACE_ATTACH
- 連接到進程。 PTRACE_PEEKTEXT
- 查看附加進程的代碼內存(例如反匯編代碼) PTRACE_PEEKDATA
- 查看附加進程的'數據存儲器(顯示變量) PTRACE_POKETEXT
- 寫入進程'代碼存儲器 PTRACE_POKEDATA
- 寫入進程'數據存儲器。 PTRACE_GETREGS
- 復制當前寄存器值。 PTRACE_SETREGS
- 更改當前寄存器值(例如,如果x
恰好位於寄存器中,則set variable x = 7
的調試命令) 在Linux中,由於內存“完全相同”, PTRACE_PEEKTEXT
和PTRACE_PEEKDATA
實際上是相同的功能,因此您可以在PTRACE_PEEKDATA
代碼中為地址提供一個地址,例如,在PTRACE_PEEKTEXT
的堆棧中為地址提供一個地址,它將完全愉快地復制回來為了你。 區別在於OS /處理器組合,其中存儲器在DATA存儲器和CODE存儲器之間“分離”。 大多數現代操作系統和處理器都沒有做出這種區分。 同樣明顯適用於PTRACE_POKEDATA
和PTRACE_POKETEXT
。
所以,說“調試程序”使用:
long data = ptrace(PTRACE_PEEKDATA, pid, 0x12340128, NULL);
當使用PTRACE_PEEKDATA
為地址0x12340128調用OS時,它將“查看”內存的相應內存映射,位於0x12340128(頁面對齊,使得0x12340000),如果存在,它將被映射到內核,數據是然后從地址0x12340128復制到本地存儲器,內存未映射,復制的數據作為返回值傳回。
手冊說明了使用的啟動:
父進程可以通過調用fork(2)並讓生成的子進行PTRACE_TRACEME來啟動跟蹤,然后(通常)執行exec(3)。 或者,父母可以使用PTRACE_ATTACH開始跟蹤現有過程。
對於幾頁,有關man ptrace
更多信息。
對於Linux調試,有一個系統調用ptrace
,它可以控制系統上的另一個進程。 實際上,如果您是流程的所有者並且尚未手動刪除權限,那么您需要具有執行此操作的權限(通常是這樣做的)。
os調用ptrace
本身可以訪問內存,程序計數器,寄存器以及幾乎所有其他相關的東西來讀寫。
有關詳細信息,請參閱man ptrace
。
如果您對它在調試器中的工作方式感興趣,請查看gdb-xxx/gdb/linux-nat.c
。 在那里,您可以找到用於訪問其他進程以進行調試的核心內容。
當每個進程都有自己的私有內存空間,沒有外部進程可以訪問...
那是假的。 具有正確權限並使用正確API的外部進程可以訪問其他進程的內存。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.