ReadProcessMemory可不是一個進程間通信的好方法
有時候我看到有人會使用 ReadProcessMemory 這個 API 來實現進程間通信,老實說吧,我覺得這不是一個明智的選擇,原因有如下幾條。
首先,你不能使用 ReadProcessMemory 來跨越安全上下文 (Security Contexts),至少你需要做一些額外的工作才能做到。如果用戶通過 “runas” 來使用另一個用戶身份來運行程序,則這兩個進程將不能通過 ReadProcessMemory 來進行進程間數據的傳輸。
我們可以通過調整進程的權限來實現這個功能,具體來說,就是對正在與之通信的進程的所有者授予 PROCESS_VM_READ 權限,但這樣會將安全的大門開的太大。使用該用戶標識運行的任何進程都會讀取到共享的數據,而不僅僅是要與之通信的進程。如果你正在與較低特權的進程進行通信,則只是將數據暴露給你感興趣的進程以外的較低特權的進程。
更重要的是,一旦授予了 PROCESS_VM_READ 權限,你就會將其授予您的整個進程。該進程不僅可以讀取你嘗試共享的數據,還可以讀取映射到你的地址空間的任何其他內容。它可以讀取所有全局變量,可以讀取堆,可以從堆棧中讀取變量。它甚至可以損壞堆棧的數據結構!
什么?僅僅是授予讀取訪問權限就損壞堆棧?
如果進程將其堆棧增長到堆棧保護頁中,則未經處理的異常篩選器將捕獲保護異常并擴展堆棧。但是,當它發生在私有的“捕獲所有異常”處理程序(例如 IsBadReadPtr 函數使用的處理程序)中時,它將私下處理,并且不會到達未處理的異常篩選器。結果,堆棧不會增長,不會創建新的堆棧保護頁面。當堆棧正常增長到并超過過早提交的保護頁的點時,通常的堆棧保護異?,F在是訪問沖突,導致線程死亡,并可能擴散到隨之而來的進程。
你可能認為,可以捕獲堆棧訪問沖突并嘗試干凈地關閉線程,但由于多種原因,這是不可能的。首先,結構化異常處理在遇到異常的線程堆棧上執行。如果該線程具有損壞的堆棧,則無法調度該異常,因為異常篩選器想要在其上運行的堆棧不再可行。
即使你可以以某種方式在某種“緊急堆棧”上運行這些異常過濾器,但仍然無法解決問題。在異常點,線程可能處于任何中間d的代碼流。也許它是在堆管理器內部,堆鎖持有,堆數據結構處于不斷變化的狀態。為了使進程保持活動狀態,需要使堆數據結構保持一致并釋放堆鎖。但是你不知道該怎么做。
還有許多其他進程間通信機制可供使用。其中之一是匿名共享內存,我幾年前討論過。匿名共享內存仍然存在一個問題,即在與你與之通信的同一令牌下運行的任何進程都可以讀取共享內存塊,但至少公開的范圍僅限于你希望明確想要共享的數據。
(從某種意義上說,沒有比這更好的了。你正在與之通信的進程一旦從你那里獲得數據,就可以對數據做任何它想做的事情。即使你以某種方式安排了只有目標進程可以訪問內存,也沒有什么能阻止該目標進程將其復制到共享內存塊之外的某個地方,此時任何運行相同令牌的人都可以從目標進程中讀取數據。)
總結
目前小僧僅僅使用到了共享內存,慚愧慚愧。
什么郵槽管道剪貼板,我是一個都沒有聽說過。