WindowsCE跨進(jìn)程內存注入原理
一、程序實(shí)現的先決條件
由于windows系統的窗體消息總是投遞至一個(gè)特定進(jìn)程的指定窗體消息函數中。于是在本地進(jìn)程(自己的應用程序)中取得屬于其它進(jìn)程的窗體的消息必須實(shí)現以下兩個(gè)部分:
1、將需要掛接窗體的代碼放到目標進(jìn)程的地址空間中去。
2、執行這一段代碼,并獲得目標進(jìn)程窗體的消息。
這兩步看起來(lái)很簡(jiǎn)單,但在實(shí)現過(guò)程中就比較困難。由于Windows CE作為嵌入式移動(dòng)設備操作系統,與windows 98/2000/XP等桌面操作系統在內核的設計理念以及API的支持上有極大的區別。這就直接導致了常規的桌面系統利用全局鼠標鉤子注入/遠程線(xiàn)程注入等方法在CE中完全得不通。不過(guò)可喜的是,微軟在開(kāi)發(fā)工具中提供的remotexxx等遠程調試程序使我清楚這個(gè)目標并不是不可能的任務(wù),微軟既然可以做到,那就是說(shuō)在CE的內部一定有一套完整的跨進(jìn)程內存訪(fǎng)問(wèn)/代碼注入的機制。
二、程序實(shí)現的基本原理
經(jīng)過(guò)兩天的google 搜索,在網(wǎng)上我發(fā)現了一個(gè)沒(méi)有在微軟文檔中聲明的有趣的API函數:PerformCallBack4,傳說(shuō)中這個(gè)函數可以在自己的應用程序中執行指定的進(jìn)程中的一個(gè)函數,So Cool!這好象正是我所需要的東西。雖然網(wǎng)上也傳聞這個(gè)函數在wm5不受支持,其實(shí)經(jīng)過(guò)實(shí)踐這個(gè)傳聞只是謠傳而已!
PerformCallBack4函數的定義:
[DllImport("coredll.dll")]
public static extern uint PerformCallBack4(ref CallBackInfo CallBackInfo,
IntPtr ni_pVoid1,IntPtr ni_pVoid2,IntPtr ni_pVoid3);
其中函數的參數CallBackInfo結構定義:
[StructLayout(LayoutKind.Sequential)]
public struct CallBackInfo
{
public IntPtr hProc; //遠程的目標進(jìn)程
public IntPtr pfn; //指向遠程目標進(jìn)程的函數地址的指針
public IntPtr pvArg0; //函數的需要的第一個(gè)參數
}//end struct
而PerformCallback4的 ni_pVoid1、ni_pVoid2、ni_pVoid3為傳遞到遠程目標進(jìn)程執行函數的其它三個(gè)參數。
至于將代碼放到目標進(jìn)程的內存空間,我們可以利用CE設計上的一個(gè)特性:
1、為了節約內存使用,CE將所有程序調用的動(dòng)態(tài)鏈接庫(DLL)都映射到同一個(gè)內存地址中。
2、CE的內存布局中劃分有一個(gè)slot0的內存位置,這個(gè)內存位置是由正在執行的進(jìn)程所占有的,每一個(gè)特定的時(shí)間片,只能有一個(gè)進(jìn)程可以占有這個(gè)內存空間。在進(jìn)程要求執行時(shí),系統并不直接執行進(jìn)程所處內存位置的代碼,而是將該進(jìn)程的執行代碼復制到slot0的內存位置中產(chǎn)生一個(gè)副本執行。也就是說(shuō)進(jìn)程在執行時(shí)內存將會(huì )有進(jìn)程執行代碼的兩個(gè)完全一樣的版本:存在于slot0中正在執行的進(jìn)程代碼和進(jìn)程本身所處的內存中的代碼。
在這個(gè)特性下,可以得到結論:如果進(jìn)程A通過(guò)LoadLibrary函數裝載Test.dll,而進(jìn)程B也通過(guò)LoadLibrary函數裝載同一個(gè)Test.dll,這個(gè)Test.dll的所有函數在進(jìn)程A和進(jìn)程B中執行時(shí),相對于slot0中的進(jìn)程執行代碼都會(huì )得到同一地址。
3、在CE中,系統在內存中劃分出33個(gè)slot,slot0保留給正在執行的進(jìn)程,然后在進(jìn)程啟動(dòng)時(shí)將所有的代碼放到除slot0以外的一個(gè)slot中(這就是臭名昭著(zhù)的CE系統中內存最多只能有不多于32個(gè)程序執行的限制的來(lái)由)。在進(jìn)程執行時(shí),每個(gè)應用程序的內存訪(fǎng)問(wèn)默認只能訪(fǎng)問(wèn)slot0內存空間中的地址以及進(jìn)程所處的slot內存空間的地址。 但為使設備驅動(dòng)程序可以訪(fǎng)問(wèn)到它們所需的其它應用程序數據,CE提供了兩個(gè)函數以打破這個(gè)限制,SetKmode和SetProcPermission,SetKmode函數告訴系統,當前運行的進(jìn)程是否需要在內核模式中執行;SetProcPermission函數可以接受一個(gè)位掩碼,每一位代碼一個(gè)slot的訪(fǎng)問(wèn)控制,1代表可以訪(fǎng)問(wèn)該slot的內存內容。0表示不能訪(fǎng)問(wèn)該slot的內存內容。這兩個(gè)函數在msdn中有幫助文檔,可參閱msdn的文檔說(shuō)明。
評論