原始碼下載 摘 要詳細闡述了如何使用DLL遠程注入技術對Windows 記事本進行換膚,講解了DLL遠程注入的概念和步驟。 關鍵詞DLL遠程注入,換膚 一、概述 1. DLL遠程注入原理 DLL遠程注入就是使用遠程線程來插入DLL,就是要求目標進程中的線程調用LoadLibrary函數來載入必要的DLL。由於除了自己進程中的線程外,我們無法方便地控制其它進程中的線程,因此這種解決方案要求我們在目標進程中建立一個新線程。由於是自己建立這個線程,因此我們能夠控制它執行什麼代碼。 Windows提供了一個稱為CreaeRemoteThread的函數,使我們能夠非常容易地在另一個進程中建立線程: HANDLE CreateRemoteThread(HANDLE hProcess,PSECURITY_ARRTRIBUTES psa,DWORD dwStackSize, PTHREAD_START_ROUTINE pfnStartAddr,PVOID pvParam,DWORD fdwCreate,PDOWRD pdwThreadId); 如何才能讓該線程載入我們的DLL呢?那就需要該線程調用LoadLibrary函數: HINSTANCE LoadLibraryA (LPCSTR pszLibFileName); //ANSI 版本 HINSTANCE LoadLibraryW (LPCWSTR pszLibFileName); //Unicode版本 我們現在要做的事情是建立一個新線程,並使線程函數的地址成為LoadLibraryA或LoadLibraryW函數的地址。 PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(TEXT(“kernel32”)),”LoadLibraryA”); HANDLE hThread = CreateRemoteThread(hProcessRemote,NULL,0,pfnThreadRtn,”C:""MyLib.dll”,0,NULL); 細心的讀者應該注意到一個問題:就是字串”C:""MyLib.dll”是在調用進程的地址空間中,會導致遠程進程的線程可能引發訪問違規。所以我們必須將DLL的路徑名字串放入遠程進程的地址空間中。 // 向目標進程地址空間寫入 DLL 名稱
DWORD dwSize, dwWritten;
dwSize = lstrlenA( lpszDll ) + 1;
LPVOID lpBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( hProcess, lpBuf, (LPVOID)lpszDll, dwSize, &dwWritten ) ; HANDLE hThread = CreateRemoteThread(hProcessRemote,NULL,0,pfnThreadRtn, lpBuf , 0,NULL);
// 等待 LoadLibrary 載入完畢 , 對字串空間進行回收
VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
這時,DLL已經被插入遠端地址空間中,同時DLL的DllMain函數接收到一個DLL_PROCESS_ATTACH通知,並且能夠執行需要的代碼。 需要提醒的是,這種插入DLL的方法存在唯一一個不足是,Windows98並不支援這樣的函數。只能用在Window2000及以上版本。 2. 對記事本換膚 要對記事本換膚,需要解決2個問題: 第一、找到能對程式進行換膚DLL檔案,這裡我們採用Skin++ (www.uipower.com)作為換膚DLL; 第二、能將DLL遠程注入到記事本的方法,該方法我們在上面已經做了介紹。 二、換膚的關鍵區段代碼 TCHAR szLibFileName[_MAX_PATH]; GetModuleFileName(NULL, szLibFileName,_MAX_PATH); CString strLibFileName(szLibFileName); strLibFileName = strLibFileName.Left(strLibFileName.ReverseFind(_T('""')) + 1); strLibFileName += _T("SkinPlusPlus.dll"); _tcscpy(szLibFileName,strLibFileName); HWND hNotepad = ::FindWindow(_T("Notepad"),NULL); if (hNotepad == NULL) return; DWORD dwRemoteProcessId; ::GetWindowThreadProcessId( hNotepad, (DWORD*)&dwRemoteProcessId ); HANDLE hRemoteProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE,dwRemoteProcessId); //計算DLL路徑名需要的記憶體空間 int cb = (1 + _tcslen(szLibFileName)) * sizeof(TCHAR); //使用VirtualAllocEx函數在遠程進程的記憶體位址空間分配DLL檔案名稱緩衝區 BYTE* pszLibFileRemote = (BYTE*) VirtualAllocEx( hRemoteProcess, NULL, cb,MEM_COMMIT, PAGE_EXECUTE_READWRITE); //使用WriteProcessMemory函數將DLL的路徑名複製到遠程進程的記憶體空間 int iReturnCode = WriteProcessMemory(hRemoteProcess,pszLibFileRemote, (PVOID)szLibFileName,cb, NULL); //計算LoadLibraryW的入口地址 PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA"); //啟動遠程線程LoadLibraryW,通過遠程線程調用使用者的DLL檔案 HANDLE hThread = CreateRemoteThread( hRemoteProcess, NULL, 0,pfnStartAddr, pszLibFileRemote, 0, NULL); WaitForSingleObject( hThread, INFINITE ); DWORD dwHandle; GetExitCodeThread( hThread, &dwHandle ); VirtualFreeEx( hRemoteProcess, pszLibFileRemote, cb, MEM_DECOMMIT ); CloseHandle( hThread ); ::SetForegroundWindow(hNotepad); 三、結束語 DLL的遠程注入技術和軟體換膚是目前Windows上非常流行的2項技術,您可以在很多場合約時看到這2者的身影,比如MSNShell。有興趣的讀者可以到http://www.msnshell.com/上下載使用。 |