簡體   English   中英

調試器如何窺視另一個進程的內存?

[英]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_PEEKTEXTPTRACE_PEEKDATA實際上是相同的功能,因此您可以在PTRACE_PEEKDATA代碼中為地址提供一個地址,例如,在PTRACE_PEEKTEXT的堆棧中為地址提供一個地址,它將完全愉快地復制回來為了你。 區別在於OS /處理器組合,其中存儲器在DATA存儲器和CODE存儲器之間“分離”。 大多數現代操作系統和處理器都沒有做出這種區分。 同樣明顯適用於PTRACE_POKEDATAPTRACE_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM