【转载】Windwos CE 跨进程内存注入
?? ? 由于windows系統(tǒng)的窗體消息總是投遞至一個特定進程的指定窗體消息函數(shù)中。于是在本地進程(自己的應用程序)中取得屬于其它進程的窗體的消息必須實現(xiàn)以下兩個部分:
1、將需要掛接窗體的代碼放到目標進程的地址空間中去。
2、執(zhí)行這一段代碼,并獲得目標進程窗體的消息。
這兩步看起來很簡單,但在實現(xiàn)過程中就比較困難。由于Windows CE作為嵌入式移動設備操作系統(tǒng),與windows 98/2000/XP等桌面操作系統(tǒng)在 內核的設計理念以及API的支持上有極大的區(qū)別。這就直接導致了常規(guī)的桌面系統(tǒng)利用全局鼠標鉤子注入/遠程線程注入等方法在CE中完全得不通。不過可喜的 是,微軟在開發(fā)工具中提供的remotexxx等遠程調試程序使我清楚這個目標并不是不可能的任務,微軟既然可以做到,那就是說在CE的內部一定有一套完 整的跨進程內存訪問/代碼注入的機制。
二、程序實現(xiàn)的基本原理
?? ? 經(jīng)過兩天的google 搜索,在網(wǎng)上我發(fā)現(xiàn)了一個沒有在微軟文檔中聲明的有趣的API函數(shù):PerformCallBack4,傳說中這個函數(shù)可以在自己的應用程序中執(zhí)行指定的 進程中的一個函數(shù),So Cool!這好象正是我所需要的東西。雖然網(wǎng)上也傳聞這個函數(shù)在wm5不受支持,其實經(jīng)過實踐這個傳聞只是謠傳而已!
?? ??PerformCallBack4函數(shù)的定義: [DllImport("coredll.dll")]
public?static?extern?uint?PerformCallBack4(ref?CallBackInfo?CallBackInfo,IntPtr?ni_pVoid1,IntPtr?ni_pVoid2,IntPtr?ni_pVoid3); ?? ? 其中函數(shù)的參數(shù)CallBackInfo結構定義:? 1?[StructLayout(LayoutKind.Sequential)]
2?public?struct?CallBackInfo
3?{
4?public?IntPtr?hProc;?//遠程的目標進程
5?public?IntPtr?pfn;?//指向遠程目標進程的函數(shù)地址的指針
6?public?IntPtr?pvArg0;?//函數(shù)的需要的第一個參數(shù)
7?}//end?struct
而PerformCallback4的 ni_pVoid1、ni_pVoid2、ni_pVoid3為傳遞到遠程目標進程執(zhí)行函數(shù)的其它三個參數(shù)。至于將代碼放到目標進程的內存空間,我們可以利用CE設計上的一個特性:
1、為了節(jié)約內存使用,CE將所有程序調用的動態(tài)鏈接庫(DLL)都映射到同一個內存地址中。
2、CE的內存布局中劃分有一個slot0的內存位置,這個內存位置是由正在執(zhí)行的進程所占有的,每一個特定的時間片,只能有一個進程可以占有這個內存空 間。在進程要求執(zhí)行時,系統(tǒng)并不直接執(zhí)行進程所處內存位置的代碼,而是將該進程的執(zhí)行代碼復制到slot0的內存位置中產(chǎn)生一個副本執(zhí)行。也就是說進程在 執(zhí)行時內存將會有進程執(zhí)行代碼的兩個完全一樣的版本:存在于slot0中正在執(zhí)行的進程代碼和進程本身所處的內存中的代碼。在這個特性下,可以得到結論:如果進程A通過LoadLibrary函數(shù)裝載Test.dll,而進程B也通過LoadLibrary函數(shù)裝載同一個 Test.dll,這個Test.dll的所有函數(shù)在進程A和進程B中執(zhí)行時,相對于slot0中的進程執(zhí)行代碼都會得到同一地址。
?? ? 3、在CE中,系統(tǒng)在內存中劃分出33個slot,slot0保留給正在執(zhí)行的進程,然后在進程啟動時將所有的代碼放到除slot0以外的一個slot中 (這就是臭名昭著的CE系統(tǒng)中內存最多只能有不多于32個程序執(zhí)行的限制的來由)。在進程執(zhí)行時,每個應用程序的內存訪問默認只能訪問slot0內存空間 中的地址以及進程所處的slot內存空間的地址。 但為使設備驅動程序可以訪問到它們所需的其它應用程序數(shù)據(jù),CE提供了兩個函數(shù)以打破這個限制,SetKmode和 SetProcPermission,SetKmode函數(shù)告訴系統(tǒng),當前運行的進程是否需要在內核模式中執(zhí)行;SetProcPermission函數(shù) 可以接受一個位掩碼,每一位代碼一個slot的訪問控制,1代表可以訪問該slot的內存內容。0表示不能訪問該slot的內存內容。這兩個函數(shù)在 msdn中有幫助文檔,可參閱msdn的文檔說明。
?? ? 本文我們對實現(xiàn)的原理進行了剖析,在下一篇文章中我們將以一個小示例程序演示實現(xiàn)的全過程。?
?? ? 在文章《淺析Windows CE跨進程內存注入實現(xiàn)窗體消息掛接(上)》中,我們已經(jīng)得到了這個七巧板游戲所需要的所有小板塊,剩下的事就是等待我們按一定順序將合適的板塊放到合適的位置,本章我們開始進行真刀真槍的實戰(zhàn)演練。
?? ?程序目標:捕獲explore窗體(也就是程序窗體的消息并輸出到WinProcInfo.txt中)
?? ?程序的執(zhí)行步驟設計如下:
?? 1、編寫一個窗體消息掛接DLL,這個DLL提供一個,函數(shù)中利用setwindowlong函數(shù)將窗體的默認消息處理過程改為這個掛接DLL中定義的一個窗體過程。
?? 2、在C#程序中利用findwindow等API函數(shù)獲得exlore類窗體的句柄及窗體所屬的進程,并使用performcallback4在目標進程空間中執(zhí)行coredll.dll的loadLibrary函數(shù)將我們寫的掛接dll放到目標進程中。
?? 3、在C#程序中使用performcallback4在目標進程空間中執(zhí)行掛接DLL提供的導出接口函數(shù)實現(xiàn)跨進程窗體消息截獲.
?? 一、程序的實現(xiàn)如下:
?? 在VS2005中建立一個智能設備的MFC DLL,命名為HookWindowsProcMFCDLL。
?? 在HookWindowsProcMFCDLL.cpp中進行掛接DLL的核心編碼:
Code
?1?LRESULT?CALLBACK?fnHookWindowProc(HWND?hwnd,UINT?msg,WPARAM?wparam,?LPARAM?lparam);
?2?
?3?int?__declspec(dllexport)?WINAPI?fnAttachWinProc(HWND?ni_hAttatchWin,PVOID?,PVOID,PVOID);
?4?
?5?int?__declspec(dllexport)?WINAPI?fnDetachWinMsgProc(HWND?ni_hDetachWin);
?6?
?7?WNDPROC?tpOldWindowProc;
?8?
?9?FILE?*m_pDebugOutputFile;
10?
11?//將一個窗體消息處理掛接到net精簡版MessageWindow對象上的代碼
12?typedef?struct
13?{?
14? WNDPROC?OldWinProc;//保留窗體原始消息處理過程的函數(shù)指針
15? HWND?WindowHandle;//保存net精簡版中對應的窗口掛接的MessageWindow對象的句柄
16?}?DEFUDT_AttachWinInfo;?//end?struct
17?
18?CMap<HWND,HWND,DEFUDT_AttachWinInfo,DEFUDT_AttachWinInfo>?m_aAttachWinInfoMap;
19?
20?//對指定的窗口進程進行掛接
21?int?__declspec(dllexport)?WINAPI?fnAttachWinProc(HWND?ni_hAttatchWin,
22?PVOID?ni_0,
23?PVOID?ni_1,
24?PVOID?ni_2?)
25?{
26? DEFUDT_AttachWinInfo?tudtAttachWinInfo;
27? m_pDebugOutputFile?=?fopen("\\Storage?Card\\WinProcInfo.txt",?"w");
28? WNDPROC?tpOldWindowProc=(WNDPROC)::SetWindowLong(ni_hAttatchWin,?GWL_WNDPROC,(LONG)?fnHookWindowProc?);
29? fprintf(m_pDebugOutputFile,"Attatch?successfully!?OldWindowProc:?%08X\n",tpOldWindowProc);
30? tudtAttachWinInfo.OldWinProc=tpOldWindowProc?;
31? tudtAttachWinInfo.WindowHandle=ni_hAttatchWin;
32? m_aAttachWinInfoMap.SetAt(ni_hAttatchWin,tudtAttachWinInfo);
33? fclose(m_pDebugOutputFile);
34? return?77;//?(int)tpOldWindowProc?;
35?}//end?function
36?
37?int?__declspec(dllexport)?WINAPI?fnDetachWinMsgProc(HWND?ni_hDetachWin)
38?{
39? DEFUDT_AttachWinInfo?tudtAttachWinInfo;
40? WNDPROC?tpOldWindowProc;
41?
42? //取得在ncf中消息接收窗口對應的原始消息處理函數(shù)的函數(shù)指針
43? m_aAttachWinInfoMap.Lookup(ni_hDetachWin,tudtAttachWinInfo)?;
44?
45? //將窗體的消息處理函數(shù)設為默認的處理過程
46? tpOldWindowProc?=(WNDPROC)?SetWindowLong(ni_hDetachWin,GWL_WNDPROC?,?(LONG)tudtAttachWinInfo.OldWinProc);
47?
48? //將掛接信息消息處理映謝類中刪除
49? m_aAttachWinInfoMap.RemoveKey(ni_hDetachWin);
50?
51? return?(int)tpOldWindowProc?;
52?
53?}//end?function
54?
55?
56?LRESULT?CALLBACK?fnHookWindowProc(HWND?hwnd,UINT?msg,WPARAM?wparam,?LPARAM?lparam)
57?{
58? DEFUDT_AttachWinInfo?tudtAttachWinInfo;
59? m_aAttachWinInfoMap.Lookup(hwnd,tudtAttachWinInfo)?;
60? m_pDebugOutputFile?=?fopen("\\Storage?Card\\WinProcInfo.txt",?"a");
61? if?(m_pDebugOutputFile!=NULL)
62? {
63? fprintf(m_pDebugOutputFile,"HWND:?%08X?Msg:?%08X?Wparam?%08X?Lparam?%08X?\n",
64?hwnd,msg,wparam,lparam);
65?
66? }//EHD?IF
67?
68? fclose(m_pDebugOutputFile);
69? //tudtAttachWin=maatt
70? LRESULT?tobjResult=?::CallWindowProc(tudtAttachWinInfo.OldWinProc?,hwnd,msg,wparam,lparam);
71? return?tobjResult;
72?}//
?
?? ? 而在C#的主程序中,我們使用這個DLL掛接explore類的程序窗體,以下給出掛接部分的代碼:
Code
?1?int?m_hTargetWindow;//要掛接的目標窗體句柄
?2?IntPtr?m_hTargetProcess;//目標窗體所屬的進程
?3?IntPtr?m_hModule;?//掛接DLL的句柄
?4?
?5?private?void?Form1_Load(object?sender,?EventArgs?e)
?6?{
?7? IntPtr?tpTemp?=?IntPtr.Zero,?tpTempa?=?IntPtr.Zero;
?8? uint?tuntApiRet;
?9?
10? m_hTargetWindow?=?(int)clsCECoreAPI.FindWindow("Explore",?null?);//資源管理器?0x0013e800;
11?
12? //掛接指定的進程窗體消息
13? IntPtr?thCurrentProcess?=?clsCECoreAPI.GetCurrentProcess();
14? m_hTargetProcess=IntPtr.Zero?;//?(IntPtr)?(unchecked((int)0xedd84e4a));
15? tuntApiRet=?clsCECoreAPI.GetWindowThreadProcessId(new?IntPtr(unchecked((int)?m_hTargetWindow)),
16?ref?m_hTargetProcess);
17?
18? string?tstrArgument;
19? tstrArgument?=?"\\Program?Files\\processinject\\HookWindowsProcMFCDLL.dll";//?HookWindowsProcMFCDLL.dll";
20? IntPtr?tpArg0;
21?
22? int?tintOriginalKMode?=?clsCECoreAPI.SetKMode(1);
23? int?tintOriginalProcPermission?=?(int)clsCECoreAPI.SetProcPermissions(0xffffffff);
24?
25? IntPtr?tpFuncProc?=?clsCECoreAPI.GetProcAddress(clsCECoreAPI.GetModuleHandle("coredll.dll"),?"LoadLibraryW");
26?
27? CallBackInfo?tudtCALLBACKINFO;
28?
29? tpArg0?=?clsCECoreAPI.MapPtrToProcess(tstrArgument,?thCurrentProcess);
30?
31? tudtCALLBACKINFO.hProc?=?m_hTargetProcess;//?Proc;
32? tudtCALLBACKINFO.pfn?=?clsCECoreAPI.MapPtrToProcess(tpFuncProc,?m_hTargetProcess);
33? tudtCALLBACKINFO.pvArg0?=?tpArg0;
34? m_hModule?=new?IntPtr(unchecked(
35?(int)?clsCECoreAPI.PerformCallBack4(ref?tudtCALLBACKINFO,IntPtr.Zero,IntPtr.Zero,IntPtr.Zero?)));
36? //clsCECoreAPI.Sleep(1000);
37?
38? IntPtr?thModule?=?clsCECoreAPI.LoadLibrary("HookWindowsProcMFCDLL.dll");
39? tpFuncProc?=?clsCECoreAPI.GetProcAddress(thModule,?"fnAttachWinProc");
40?
41? tpArg0?=?(IntPtr)?m_hTargetWindow;//?clsCECoreAPI.MapPtrToProcess(ref?thTargetWindow,?thCurrentProcess);
42?
43? tudtCALLBACKINFO.hProc?=?m_hTargetProcess;
44? tudtCALLBACKINFO.pfn?=?clsCECoreAPI.MapPtrToProcess(tpFuncProc,?m_hTargetProcess);
45? tudtCALLBACKINFO.pvArg0?=?tpArg0?;
46? tuntApiRet?=?clsCECoreAPI.PerformCallBack4(ref?tudtCALLBACKINFO,IntPtr.Zero,IntPtr.Zero,IntPtr.Zero?);
47? //clsCECoreAPI.Sleep(5000);
48?}
49?
50?[DllImport("HookWindowsProcMFCDLL.dll")]
51?public?static?extern?int?fnAttachWinProc(IntPtr?ni_hAttatchWin);
52?
53?[DllImport("HookWindowsProcMFCDLL.dll")]
54?public?static?extern?int
?
?? ?取消掛接的代碼根據(jù)上述代碼很容易就可以建立,不再細敘。
?? ?注:clsCECoreAPI的函數(shù)全是封裝的標準CE API,由于這些API在msdn 中都有詳細的文檔注釋,因篇幅所限,不再將代碼一一列舉.
?? ?在執(zhí)行這個程序時,將模擬器的共享路徑設為PC機的桌面,這樣模擬器的storage card目錄就等同桌面了,點模擬器的開始菜單,選程序,你就可以看到explore窗體的消息都輸出到桌面的WinProcInfo.txt文件中了,運行結果如下:
?
?? ? 目前本程序只在PPC2003/wm5 for PPC測試通過,由于smartphone系統(tǒng)在編譯時使用了和ppc系統(tǒng)不同的機制,內存運作不明,本程序在smartphone上無法正確運行,有好的建議的話請指教一二,謝謝.?
?
轉載于:https://www.cnblogs.com/IamEasy_Man/archive/2009/08/16/1547289.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的【转载】Windwos CE 跨进程内存注入的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Struts+Spring+Hibern
- 下一篇: C#获取屏幕分辨率(大小)