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