方式四:修改模块导入段来拦截API
2015-02-28 17:20
260 查看
一个模块的导入段包含一组DLL,导入段还包含一个符号表,其中列出了该模块从各DLL中导入的符号,
当该模块调用一个导入函数的时候,线程实际上会先从模块的导入表中得到相应的导入函数的地址,然后再跳转到那个地址。
模块的导入段中所有的字符串都是以ANSI格式保存的,有的编译器会生成多个导入段。
hook dll project will generate injectdll.dll
the test result:
当该模块调用一个导入函数的时候,线程实际上会先从模块的导入表中得到相应的导入函数的地址,然后再跳转到那个地址。
模块的导入段中所有的字符串都是以ANSI格式保存的,有的编译器会生成多个导入段。
//hook dll /****************************************************************************** Module: APIHook.h Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre ******************************************************************************/ #pragma once /////////////////////////////////////////////////////////////////////////////// class CAPIHook { public: // Hook a function in all modules CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook); // Unhook a function from all modules ~CAPIHook(); // Returns the original address of the hooked function operator PROC() { return(m_pfnOrig); } // Hook module w/CAPIHook implementation? // I have to make it static because I need to use it // in ReplaceIATEntryInAllMods static BOOL ExcludeAPIHookMod; public: // Calls the real GetProcAddress static FARPROC WINAPI GetProcAddressRaw(HMODULE hmod, PCSTR pszProcName); private: static PVOID sm_pvMaxAppAddr; // Maximum private memory address static CAPIHook* sm_pHead; // Address of first object CAPIHook* m_pNext; // Address of next object PCSTR m_pszCalleeModName; // Module containing the function (ANSI) PCSTR m_pszFuncName; // Function name in callee (ANSI) PROC m_pfnOrig; // Original function address in callee PROC m_pfnHook; // Hook function address private: // Replaces a symbol's address in a module's import section static void WINAPI ReplaceIATEntryInAllMods(PCSTR pszCalleeModName, PROC pfnOrig, PROC pfnHook); // Replaces a symbol's address in all modules' import sections static void WINAPI ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, PROC pfnOrig, PROC pfnHook, HMODULE hmodCaller); // Replaces a symbol's address in a module's export sections static void ReplaceEATEntryInOneMod(HMODULE hmod, PCSTR pszFunctionName, PROC pfnNew); private: // Used when a DLL is newly loaded after hooking a function static void WINAPI FixupNewlyLoadedModule(HMODULE hmod, DWORD dwFlags); // Used to trap when DLLs are newly loaded static HMODULE WINAPI LoadLibraryA(PCSTR pszModulePath); static HMODULE WINAPI LoadLibraryW(PCWSTR pszModulePath); static HMODULE WINAPI LoadLibraryExA(PCSTR pszModulePath, HANDLE hFile, DWORD dwFlags); static HMODULE WINAPI LoadLibraryExW(PCWSTR pszModulePath, HANDLE hFile, DWORD dwFlags); // Returns address of replacement function if hooked function is requested static FARPROC WINAPI GetProcAddress(HMODULE hmod, PCSTR pszProcName); private: // Instantiates hooks on these functions static CAPIHook sm_LoadLibraryA; static CAPIHook sm_LoadLibraryW; static CAPIHook sm_LoadLibraryExA; static CAPIHook sm_LoadLibraryExW; static CAPIHook sm_GetProcAddress; }; //////////////////////////////// End of File ////////////////////////////////// /****************************************************************************** Module: APIHook.cpp Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre ******************************************************************************/ #include <Windows.h> #include <CommCtrl.h> #include <process.h> #include <ImageHlp.h> #pragma comment(lib, "ImageHlp") #include "APIHook.h" #include <tlhelp32.h> #include <tchar.h> #include <StrSafe.h> ///////////////////////////////////////////////////////////////////////////////// // The head of the linked-list of CAPIHook objects CAPIHook* CAPIHook::sm_pHead = NULL; // By default, the module containing the CAPIHook() is not hooked BOOL CAPIHook::ExcludeAPIHookMod = TRUE; /////////////////////////////////////////////////////////////////////////////// CAPIHook::CAPIHook(PSTR pszCalleeModName, PSTR pszFuncName, PROC pfnHook) { // Note: the function can be hooked only if the exporting module // is already loaded. A solution could be to store the function // name as a member; then, in the hooked LoadLibrary* handlers, parse // the list of CAPIHook instances, check if pszCalleeModName // is the name of the loaded module to hook its export table and // re-hook the import tables of all loaded modules. m_pNext = sm_pHead; // The next node was at the head sm_pHead = this; // This node is now at the head // Save information about this hooked function m_pszCalleeModName = pszCalleeModName; m_pszFuncName = pszFuncName; m_pfnHook = pfnHook; m_pfnOrig = GetProcAddressRaw(GetModuleHandleA(pszCalleeModName), m_pszFuncName); // If function does not exit,... bye bye // This happens when the module is not already loaded if (m_pfnOrig == NULL) { wchar_t szPathname[MAX_PATH]; GetModuleFileNameW(NULL, szPathname, _countof(szPathname)); wchar_t sz[1024]; StringCchPrintfW(sz, _countof(sz), TEXT("[%4u - %s] impossible to find %S\r\n"), GetCurrentProcessId(), szPathname, pszFuncName); OutputDebugString(sz); return; } #ifdef _DEBUG // This section was used for debugging sessions when Explorer died as // a folder content was requested // //static BOOL s_bFirstTime = TRUE; //if (s_bFirstTime) //{ // s_bFirstTime = FALSE; // wchar_t szPathname[MAX_PATH]; // GetModuleFileNameW(NULL, szPathname, _countof(szPathname)); // wchar_t* pszExeFile = wcsrchr(szPathname, L'\\') + 1; // OutputDebugStringW(L"Injected in "); // OutputDebugStringW(pszExeFile); // if (_wcsicmp(pszExeFile, L"Explorer.EXE") == 0) // { // DebugBreak(); // } // OutputDebugStringW(L"\n --> "); // StringCchPrintfW(szPathname, _countof(szPathname), L"%S", pszFuncName); // OutputDebugStringW(szPathname); // OutputDebugStringW(L"\n"); //} #endif // Hook this function in all currently loaded modules ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnOrig, m_pfnHook); } /////////////////////////////////////////////////////////////////////////////// CAPIHook::~CAPIHook() { // Unhook this function from all modules ReplaceIATEntryInAllMods(m_pszCalleeModName, m_pfnHook, m_pfnOrig); // Remove this object from the linked list CAPIHook* p = sm_pHead; if (p == this) { // Removing the head node sm_pHead = p->m_pNext; } else { BOOL bFound = FALSE; // Walk list from head and fix pointers for (; !bFound && (p->m_pNext != NULL); p = p->m_pNext) { if (p->m_pNext == this) { // Make the node that points to us point to our next node p->m_pNext = p->m_pNext->m_pNext; bFound = TRUE; } } } } /////////////////////////////////////////////////////////////////////////////// // NOTE: This function must NOT be inlined FARPROC CAPIHook::GetProcAddressRaw(HMODULE hmod, PCSTR pszProcName) { return(::GetProcAddress(hmod, pszProcName)); } /////////////////////////////////////////////////////////////////////////////// // Returns the HMODULE that contains the specified memory address static HMODULE ModuleFromAddress(PVOID pv) { MEMORY_BASIC_INFORMATION mbi; return((VirtualQuery(pv, &mbi, sizeof(mbi)) != 0) ? (HMODULE) mbi.AllocationBase : NULL); } /////////////////////////////////////////////////////////////////////////////// void CAPIHook::ReplaceIATEntryInAllMods(PCSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew) { HMODULE hmodThisMod = ExcludeAPIHookMod ? ModuleFromAddress(ReplaceIATEntryInAllMods) : NULL; // Get the list of modules in this process //CToolhelp th(TH32CS_SNAPMODULE, GetCurrentProcessId()); HANDLE m_hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); //if(m_hSnapshot == INVALID_HANDLE_VALUE) MODULEENTRY32 me = { sizeof(me) }; for (BOOL bOk = Module32First(m_hSnapshot, &me); bOk; bOk = Module32Next(m_hSnapshot, &me)) { // NOTE: We don't hook functions in our own module if (me.hModule != hmodThisMod) { // Hook this function in this module ReplaceIATEntryInOneMod( pszCalleeModName, pfnCurrent, pfnNew, me.hModule); } } if (m_hSnapshot != INVALID_HANDLE_VALUE) CloseHandle(m_hSnapshot); } /////////////////////////////////////////////////////////////////////////////// // Handle unexpected exceptions if the module is unloaded LONG WINAPI InvalidReadExceptionFilter(PEXCEPTION_POINTERS pep) { // handle all unexpected exceptions because we simply don't patch // any module in that case LONG lDisposition = EXCEPTION_EXECUTE_HANDLER; // Note: pep->ExceptionRecord->ExceptionCode has 0xc0000005 as a value return(lDisposition); } void CAPIHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) { // Get the address of the module's import section ULONG ulSize; // An exception was triggered by Explorer (when browsing the content of // a folder) into imagehlp.dll. It looks like one module was unloaded... // Maybe some threading problem: the list of modules from Toolhelp might // not be accurate if FreeLibrary is called during the enumeration. PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL; __try { pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData( hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize); } __except (InvalidReadExceptionFilter(GetExceptionInformation())) { // Nothing to do in here, thread continues to run normally // with NULL for pImportDesc } if (pImportDesc == NULL) return; // This module has no import section or is no longer loaded // Find the import descriptor containing references to callee's functions for (; pImportDesc->Name; pImportDesc++) { PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name); if (lstrcmpiA(pszModName, pszCalleeModName) == 0) { // Get caller's import address table (IAT) for the callee's functions PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) ((PBYTE) hmodCaller + pImportDesc->FirstThunk); // Replace current function address with new function address for (; pThunk->u1.Function; pThunk++) { // Get the address of the function address PROC* ppfn = (PROC*) &pThunk->u1.Function; // Is this the function we're looking for? BOOL bFound = (*ppfn == pfnCurrent); if (bFound) { if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) { DWORD dwOldProtect; if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY, &dwOldProtect)) { WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL); VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect, &dwOldProtect); } } return; // We did it, get out } } } // Each import section is parsed until the right entry is found and patched } } /////////////////////////////////////////////////////////////////////////////// void CAPIHook::ReplaceEATEntryInOneMod(HMODULE hmod, PCSTR pszFunctionName, PROC pfnNew) { // Get the address of the module's export section ULONG ulSize; PIMAGE_EXPORT_DIRECTORY pExportDir = NULL; __try { pExportDir = (PIMAGE_EXPORT_DIRECTORY) ImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &ulSize); } __except (InvalidReadExceptionFilter(GetExceptionInformation())) { // Nothing to do in here, thread continues to run normally // with NULL for pExportDir } if (pExportDir == NULL) return; // This module has no export section or is unloaded PDWORD pdwNamesRvas = (PDWORD) ((PBYTE) hmod + pExportDir->AddressOfNames); PWORD pdwNameOrdinals = (PWORD) ((PBYTE) hmod + pExportDir->AddressOfNameOrdinals); PDWORD pdwFunctionAddresses = (PDWORD) ((PBYTE) hmod + pExportDir->AddressOfFunctions); // Walk the array of this module's function names for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) { // Get the function name PSTR pszFuncName = (PSTR) ((PBYTE) hmod + pdwNamesRvas ); // If not the specified function, try the next function if (lstrcmpiA(pszFuncName, pszFunctionName) != 0) continue; // We found the specified function // --> Get this function's ordinal value WORD ordinal = pdwNameOrdinals ; // Get the address of this function's address PROC* ppfn = (PROC*) &pdwFunctionAddresses[ordinal]; // Turn the new address into an RVA pfnNew = (PROC) ((PBYTE) pfnNew - (PBYTE) hmod); // Replace current function address with new function address if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) { DWORD dwOldProtect; if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY, &dwOldProtect)) { WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL); VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect, &dwOldProtect); } } break; // We did it, get out } } /////////////////////////////////////////////////////////////////////////////// // Hook LoadLibrary functions and GetProcAddress so that hooked functions // are handled correctly if these functions are called. CAPIHook CAPIHook::sm_LoadLibraryA ("Kernel32.dll", "LoadLibraryA", (PROC) CAPIHook::LoadLibraryA); CAPIHook CAPIHook::sm_LoadLibraryW ("Kernel32.dll", "LoadLibraryW", (PROC) CAPIHook::LoadLibraryW); CAPIHook CAPIHook::sm_LoadLibraryExA("Kernel32.dll", "LoadLibraryExA", (PROC) CAPIHook::LoadLibraryExA); CAPIHook CAPIHook::sm_LoadLibraryExW("Kernel32.dll", "LoadLibraryExW", (PROC) CAPIHook::LoadLibraryExW); CAPIHook CAPIHook::sm_GetProcAddress("Kernel32.dll", "GetProcAddress", (PROC) CAPIHook::GetProcAddress); /////////////////////////////////////////////////////////////////////////////// void CAPIHook::FixupNewlyLoadedModule(HMODULE hmod, DWORD dwFlags) { // If a new module is loaded, hook the hooked functions if ((hmod != NULL) && // Do not hook our own module (hmod != ModuleFromAddress(FixupNewlyLoadedModule)) && ((dwFlags & LOAD_LIBRARY_AS_DATAFILE) == 0) && ((dwFlags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) == 0) && ((dwFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) == 0) ) { for (CAPIHook* p = sm_pHead; p != NULL; p = p->m_pNext) { if (p->m_pfnOrig != NULL) { ReplaceIATEntryInAllMods(p->m_pszCalleeModName, p->m_pfnOrig, p->m_pfnHook); } else { #ifdef _DEBUG // We should never end up here wchar_t szPathname[MAX_PATH]; GetModuleFileNameW(NULL, szPathname, _countof(szPathname)); wchar_t sz[1024]; StringCchPrintfW(sz, _countof(sz), TEXT("[%4u - %s] impossible to find %S\r\n"), GetCurrentProcessId(), szPathname, p->m_pszCalleeModName); OutputDebugString(sz); #endif } } } } /////////////////////////////////////////////////////////////////////////////// HMODULE WINAPI CAPIHook::LoadLibraryA(PCSTR pszModulePath) { HMODULE hmod = ::LoadLibraryA(pszModulePath); FixupNewlyLoadedModule(hmod, 0); return(hmod); } /////////////////////////////////////////////////////////////////////////////// HMODULE WINAPI CAPIHook::LoadLibraryW(PCWSTR pszModulePath) { HMODULE hmod = ::LoadLibraryW(pszModulePath); FixupNewlyLoadedModule(hmod, 0); return(hmod); } /////////////////////////////////////////////////////////////////////////////// HMODULE WINAPI CAPIHook::LoadLibraryExA(PCSTR pszModulePath, HANDLE hFile, DWORD dwFlags) { HMODULE hmod = ::LoadLibraryExA(pszModulePath, hFile, dwFlags); FixupNewlyLoadedModule(hmod, dwFlags); return(hmod); } /////////////////////////////////////////////////////////////////////////////// HMODULE WINAPI CAPIHook::LoadLibraryExW(PCWSTR pszModulePath, HANDLE hFile, DWORD dwFlags) { HMODULE hmod = ::LoadLibraryExW(pszModulePath, hFile, dwFlags); FixupNewlyLoadedModule(hmod, dwFlags); return(hmod); } /////////////////////////////////////////////////////////////////////////////// FARPROC WINAPI CAPIHook::GetProcAddress(HMODULE hmod, PCSTR pszProcName) { // Get the true address of the function FARPROC pfn = GetProcAddressRaw(hmod, pszProcName); // Is it one of the functions that we want hooked? CAPIHook* p = sm_pHead; for (; (pfn != NULL) && (p != NULL); p = p->m_pNext) { if (pfn == p->m_pfnOrig) { // The address to return matches an address we want to hook // Return the hook function address instead pfn = p->m_pfnHook; break; } } return(pfn); } //////////////////////////////// End of File ////////////////////////////////// // Prototypes for the hooked functions typedef int (WINAPI *PFNMESSAGEBOXA)(HWND hWnd, PCSTR pszText, PCSTR pszCaption, UINT uType); typedef int (WINAPI *PFNMESSAGEBOXW)(HWND hWnd, PCWSTR pszText, PCWSTR pszCaption, UINT uType); // We need to reference these variables before we create them. extern CAPIHook g_MessageBoxA; extern CAPIHook g_MessageBoxW; /////////////////////////////////////////////////////////////////////////////// // This function sends the MessageBox info to our main dialog box void SendLastMsgBoxInfo(BOOL bUnicode, PVOID pvCaption, PVOID pvText, int nResult) { // Get the pathname of the process displaying the message box wchar_t szProcessPathname[MAX_PATH]; GetModuleFileNameW(NULL, szProcessPathname, MAX_PATH); // Convert the return value into a human-readable string PCWSTR pszResult = L"(Unknown)"; switch (nResult) { case IDOK: pszResult = L"Ok"; break; case IDCANCEL: pszResult = L"Cancel"; break; case IDABORT: pszResult = L"Abort"; break; case IDRETRY: pszResult = L"Retry"; break; case IDIGNORE: pszResult = L"Ignore"; break; case IDYES: pszResult = L"Yes"; break; case IDNO: pszResult = L"No"; break; case IDCLOSE: pszResult = L"Close"; break; case IDHELP: pszResult = L"Help"; break; case IDTRYAGAIN: pszResult = L"Try Again"; break; case IDCONTINUE: pszResult = L"Continue"; break; } // Construct the string to send to the main dialog box wchar_t sz[2048]; StringCchPrintfW(sz, _countof(sz), bUnicode ? L"Process: (%d) %s\r\nCaption: %s\r\nMessage: %s\r\nResult: %s" : L"Process: (%d) %s\r\nCaption: %S\r\nMessage: %S\r\nResult: %s", GetCurrentProcessId(), szProcessPathname, pvCaption, pvText, pszResult); // Send the string to the main dialog box //COPYDATASTRUCT cds = { 0, ((DWORD)wcslen(sz) + 1) * sizeof(wchar_t), sz }; //FORWARD_WM_COPYDATA(FindWindow(NULL, TEXT("Last MessageBox Info")), // NULL, &cds, SendMessage); ::OutputDebugStringW(sz); } /////////////////////////////////////////////////////////////////////////////// // This is the MessageBoxW replacement function int WINAPI Hook_MessageBoxW(HWND hWnd, PCWSTR pszText, LPCWSTR pszCaption, UINT uType) { // Call the original MessageBoxW function int nResult = ((PFNMESSAGEBOXW)(PROC) g_MessageBoxW) (hWnd, pszText, pszCaption, uType); // Send the information to the main dialog box SendLastMsgBoxInfo(TRUE, (PVOID) pszCaption, (PVOID) pszText, nResult); // Return the result back to the caller return(nResult); } /////////////////////////////////////////////////////////////////////////////// // This is the MessageBoxA replacement function int WINAPI Hook_MessageBoxA(HWND hWnd, PCSTR pszText, PCSTR pszCaption, UINT uType) { // Call the original MessageBoxA function int nResult = ((PFNMESSAGEBOXA)(PROC) g_MessageBoxA) (hWnd, pszText, pszCaption, uType); // Send the information to the main dialog box SendLastMsgBoxInfo(FALSE, (PVOID) pszCaption, (PVOID) pszText, nResult); // Return the result back to the caller return(nResult); } // Hook the MessageBoxA and MessageBoxW functions CAPIHook g_MessageBoxA("User32.dll", "MessageBoxA", (PROC) Hook_MessageBoxA); CAPIHook g_MessageBoxW("User32.dll", "MessageBoxW", (PROC) Hook_MessageBoxW); //dllmain.cpp #include <windows.h> wchar_t log[1024] = { 0 }; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: wsprintfW(log,L"DLL_PROCESS_ATTACH tid:%d \n",GetCurrentThreadId()); ::OutputDebugStringW(log); break; case DLL_THREAD_ATTACH: wsprintfW(log,L"DLL_THREAD_ATTACH tid:%d \n",GetCurrentThreadId()); ::OutputDebugStringW(log); break; case DLL_THREAD_DETACH: wsprintfW(log,L"DLL_THREAD_DETACH tid:%d \n",GetCurrentThreadId()); ::OutputDebugStringW(log); break; case DLL_PROCESS_DETACH: wsprintfW(log,L"DLL_PROCESS_DETACH tid:%d \n",GetCurrentThreadId()); ::OutputDebugStringW(log); break; } return TRUE; }
hook dll project will generate injectdll.dll
// inject exe project, it will inject hook dll to test project. #include <Windows.h> #include <TlHelp32.h> #include <tchar.h> #include <stdio.h> wchar_t log[1024] = { 0 }; BOOL WINAPI InjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) { BOOL bOk = FALSE; // Assume that the function fails HANDLE hProcess = NULL, hThread = NULL; PWSTR pszLibFileRemote = NULL; __try { // Get a handle for the target process. hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | // Required by Alpha PROCESS_CREATE_THREAD | // For CreateRemoteThread PROCESS_VM_OPERATION | // For VirtualAllocEx/VirtualFreeEx PROCESS_VM_WRITE, // For WriteProcessMemory FALSE, dwProcessId); if (hProcess == NULL) __leave; // Calculate the number of bytes needed for the DLL's pathname int cch = 1 + lstrlenW(pszLibFile); int cb = cch * sizeof(wchar_t); // Allocate space in the remote process for the pathname pszLibFileRemote = (PWSTR) VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE); if (pszLibFileRemote == NULL) __leave; // Copy the DLL's pathname to the remote process' address space if (!WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID) pszLibFile, cb, NULL)) __leave; // Get the real address of LoadLibraryW in Kernel32.dll PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW"); if (pfnThreadRtn == NULL) __leave; // Create a remote thread that calls LoadLibraryW(DLLPathname) DWORD remoteTID = 0; hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, pszLibFileRemote, 0, &remoteTID); wsprintfW(log,L"CreateRemoteThread tid:%d for inject dll.\n",remoteTID); ::OutputDebugStringW(log); if (hThread == NULL) __leave; // Wait for the remote thread to terminate WaitForSingleObject(hThread, INFINITE); bOk = TRUE; // Everything executed successfully } __finally { // Now, we can clean everything up // Free the remote memory that contained the DLL's pathname if (pszLibFileRemote != NULL) VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE); if (hThread != NULL) CloseHandle(hThread); if (hProcess != NULL) CloseHandle(hProcess); } return(bOk); } BOOL WINAPI EjectLibW(DWORD dwProcessId, PCWSTR pszLibFile) { BOOL bOk = FALSE; // Assume that the function fails HANDLE hthSnapshot = NULL; HANDLE hProcess = NULL, hThread = NULL; __try { // Grab a new snapshot of the process hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId); if (hthSnapshot == INVALID_HANDLE_VALUE) __leave; // Get the HMODULE of the desired library MODULEENTRY32W me = { sizeof(me) }; BOOL bFound = FALSE; BOOL bMoreMods = Module32FirstW(hthSnapshot, &me); for (; bMoreMods; bMoreMods = Module32NextW(hthSnapshot, &me)) { bFound = (_wcsicmp(me.szModule, pszLibFile) == 0) || (_wcsicmp(me.szExePath, pszLibFile) == 0); if (bFound) break; } if (!bFound) __leave; // Get a handle for the target process. hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION, // For CreateRemoteThread FALSE, dwProcessId); if (hProcess == NULL) __leave; // Get the real address of FreeLibrary in Kernel32.dll PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary"); if (pfnThreadRtn == NULL) __leave; // Create a remote thread that calls FreeLibrary() //hThread = CreateRemoteThread(hProcess, NULL, 0, // pfnThreadRtn, me.modBaseAddr, 0, NULL); DWORD remoteTID = 0; hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, me.hModule, 0, &remoteTID); wsprintfW(log,L"CreateRemoteThread tid:%d for Eject dll.\n",remoteTID); ::OutputDebugStringW(log); if (hThread == NULL) __leave; // Wait for the remote thread to terminate WaitForSingleObject(hThread, INFINITE); bOk = TRUE; // Everything executed successfully } __finally { // Now we can clean everything up if (hthSnapshot != NULL) CloseHandle(hthSnapshot); if (hThread != NULL) CloseHandle(hThread); if (hProcess != NULL) CloseHandle(hProcess); } return(bOk); } int main() { wchar_t szLibFile[MAX_PATH]; GetModuleFileNameW(NULL, szLibFile, _countof(szLibFile)); wchar_t *pFilename = wcsrchr(szLibFile, L'\\') + 1; wcscpy_s(pFilename, _countof(szLibFile) - (pFilename-szLibFile),L"injectdll.dll"); DWORD pid = 0; wprintf_s(L"Please put in inject process ID:\n"); wscanf_s(L"%d",&pid); InjectLibW(pid,szLibFile); getchar(); EjectLibW(pid,szLibFile); return 0; }
//test project, this project will be hooked #include <Windows.h> #include <stdio.h> void main() { OutputDebugStringW(L"this process will be inject hook dll.\n"); while(true) { MessageBoxA(NULL,"MessageBoxA","MessageBoxA TEST",MB_OKCANCEL); int ret = MessageBoxW(NULL,L"MessageBoxW",L"MessageBoxW TEST",MB_YESNOCANCEL); if( ret == IDNO ) break; } getchar(); }
the test result:
相关文章推荐
- 《windows核心编程系列》二十二谈谈修改导入段拦截API。
- 《windows核心编程系列》谈谈修改导入段拦截API。
- 《windows核心编程系列》二十二谈谈修改导入段拦截API。
- 如何使用WINSOCK Api hook拦截修改socket数据包
- Hook导入表 —— 实现挂钩FreeLibaray和HOOK延迟加载模块的API
- 如何使用WINSOCK Api hook拦截修改socket数据包
- 一个API方式存取日志文件的模块
- 用API修改注册表的完整模块
- RequireJs 2.0 API 中四种定义模块的方式。
- PHPExcel导入导出及大量数据导入缓存方式的修改
- 采用修改导入节的HOOK方式使用范围
- windows 下实现函数打桩:拦截API方式
- [导入]ASP进阶:VB中的模块,类,ActiveX与API的使用
- 用钩子实现API拦截(解决延迟加载模块问题)
- 拦截API(修改函数地址方法)
- 嗷,库存管理系统内侧版!!!(添加所有数据验证,修改模块显示方式,更新所有图标)
- [导入]微软研究院Detour开发包之API拦截技术
- 拦截指定进程的API(修改+收藏)
- API钩子(IAT修改方式)
- 新闻模块之新闻修改-使用FreeboxText模块修改新闻数据-页面表示层(Linq方式)-1