C++ code colored by C++2HTML
每個進程都有它自己的私有地址空間。當使用指針來引用內存時,指針的值將引用你自己進程的地址空間中的一個內存地址,有些情況下,必須打破進程的界限,訪問另一個進程的地址空間,這些情況包括:
? 當你想要為另一個進程創建的窗口建立子類時。
? 當你需要調試幫助時(例如,當你需要確定另一個進程正在使用哪個DLL時)。
? 當你想要掛接其他進程時
將DLL 插入到另一個進程的地址空間中。一旦DLL進入另一個進程的地址空間,就可以對另一個進程為所欲為。Dll必須進入進程的空間否則就會出現地址訪問的越界違規。這就是問什么不能直接用函數 SetWindowLongPtr(hwnd,GWLP_WNDPROC,Mysubclassproc);插入的方法有多種:
1:注冊表插入
windows98不可以用!是在windows初始化的時候加載的!DLL只會映射到使用User 32.dll的進程中。所有基于GUI的應用程序均使用User32.dll,不過大多數基于CUI的應用程序并不使用它。很容易實現但很不安全,系統易崩潰!
2:用windows掛鉤插入DLL
Microsoft Spy++就是安裝了掛鉤(wm_getmessage)查看系統各個窗口處理的消息!用下面的函數安裝
HHOOK HhOOK = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hinstDll,0);
第一個參數WH_GETMESSAGE用于指定安裝掛鉤的類型,GetMsgProc用于指明窗口準備處理一個消息時系統應該調用的函數的地址。 HinstDll指明包含GetMsgProc函數的DLL,DLL的hinstDll的值用于標識DLL被映射到的進程的地址空間中的虛擬內存地址;最后一個參數0用于指明要掛接的線程,對于一個線程來說,它可以調用SetWindowsHookEx函數,傳遞系統中的另一個線程的ID。通過為這個參數傳遞0,就告訴系統說,我們想要掛接系統中的所有GUI線程。現在讓我們來看一看將會發生什么情況:
1) 進程B中的一個線程準備將一條消息發送到一個窗口。
2) 系統查看該線程上是否已經安裝了WH_GETMESSAGE掛鉤。
3) 系統查看包含GetMsgProc函數的DLL是否被映射到進程B的地址空間中。
4) 如果該DLL尚未被映射,系統將強制該DLL映射到進程B的地址空間,并且將進程B中的DLL映像的自動跟蹤計數遞增1
這個方法允許你在另一個進程的地址空間中不再需要DLL時刪除該DLL的映像,方法是調用函數 BOOL UnhookWindowsHookEx(HHOOK hhook);
3: 使用遠程線程來插入D L L
這個DLL插入法要求目標進程中的線程調用LoadLibrary函數來加載必要的DLL。但我們無法控制其它線程,因此要求我們可以在目標進程中創建一個新進程以便控制它。CreateRemoteThread函數可以做到這一點:
HANDLE CreateRemoteThread(
HANDLE hProcess,
PSECURITY_ATTRIBUTES psa,
PTHREAD_START_ROUTINE pfnStartAddr,
PVOID pvParam,
DWORD fdwCreate,
PDWORD pdwThreadId);
使用實例:
HANDLE hThread=CreateRemoteThread(hProcessRemote,NULL,0,
LoadLibraryA,”C:\\mylib.dll”,0,NULL);
CreateRemoteThread的前提條件是Kernel32.dll已經被同事映射到了本地和遠程進程的地址空間中,恰好每個程序都要用到Kernel32.dll。
PTHREAD_START_ROUTIME pfnThreadRtn = (PTHREAD_START_ROUTIME)
GetProcAddress(GetModuleHandle(TEXT(“Kernel32”),”LoadLibraryA”);
HANDLE hThread = CreateRemoteThread(hProcessRemote,NULL,0,
pfnThreadRtn,”c:\\mylib.dll”,0,NULL);
《WINDOWS核心編程》中的例子
BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile)
{
BOOL fOk = FALSE;
HANDLE hProcess = NULL, hThread = NULL;
PWSTR pszLibFileRemote = NULL;
__try {
hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION |
PROCESS_Create_THREAD |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE,
FALSE, dwProcessId);
if (hProcess == NULL) __leave;
int cch = 1 + lstrlenW(pszLibFile);
int cb = cch * sizeof(WCHAR);
pszLibFileRemote = (PWSTR)
VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);
if (pszLibFileRemote == NULL) __leave;
if (!WriteProcessMemory(hProcess, pszLibFileRemote,
(PVOID) pszLibFile, cb, NULL)) __leave;
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
if (pfnThreadRtn == NULL) __leave;
hThread = CreateRemoteThread(hProcess, NULL, 0,
pfnThreadRtn, pszLibFileRemote, 0, NULL);
if (hThread == NULL) __leave;
WaitForSingleObject(hThread, INFINITE);
fOk = TRUE;
}
__finally {
if (pszLibFileRemote != NULL)
VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);
if (hThread != NULL)
CloseHandle(hThread);
if (hProcess != NULL)
CloseHandle(hProcess);
}