CreateRemoteThread小记
利用全局钩子可以注入DLL到当前的所有进程,若要注入到特定的进程中可用CreateRemoteThread函数.
#include <Tlhelp32.h>
/*
* 向指定进程注入DLL
* dwProcessID: 目标进程ID
* lpszDll: 待注入的DLL完全路径
* 返回注入成功与否
*/
inline BOOL InjectDllIntoProcess( DWORD dwProcessID, LPCTSTR lpszDll )
{
BOOL bRet = FALSE;
HANDLE hProcess = NULL;
PSTR pszRemoteDll = NULL;
do
{
//根据进程ID获取进程句柄
hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessID );
if( hProcess == NULL )
break;
int nAllocSize = ( _tcslen( lpszDll ) + 1 ) * sizeof(TCHAR);
//在远程进程中分配内存
pszRemoteDll = (PSTR)::VirtualAllocEx( hProcess, NULL, nAllocSize, MEM_COMMIT, PAGE_READWRITE );
if( pszRemoteDll == NULL )
break;
//写内存
if( !::WriteProcessMemory( hProcess, pszRemoteDll, lpszDll, nAllocSize, NULL ) )
break;
LPTHREAD_START_ROUTINE pfnThread = NULL;
//Kernel32模块在每个进程中都被映射到相同的地址,故在本进程获取到的LoadLibrary函数地址和远程进程中地址是一样的
#ifdef UNICODE
pfnThread = ( LPTHREAD_START_ROUTINE ) ::GetProcAddress( ::GetModuleHandle( _T("Kernel32") ), "LoadLibraryW" );
#else
pfnThread = ( LPTHREAD_START_ROUTINE ) ::GetProcAddress( ::GetModuleHandle( _T("Kernel32") ), "LoadLibraryA" );
#endif // !UNICODE
if( pfnThread == NULL )
break;
HANDLE hThread = ::CreateRemoteThread( hProcess, NULL, 0, pfnThread, pszRemoteDll, 0, NULL );
if( hThread == NULL )
break;
//等待远程线程结束
::WaitForSingleObject( hThread, INFINITE );
::CloseHandle( hThread );
bRet = TRUE;
} while( FALSE );
//释放资源
if( pszRemoteDll != NULL )
::VirtualFreeEx( hProcess, pszRemoteDll, 0, MEM_RELEASE );
if( hProcess != NULL )
::CloseHandle( hProcess );
return bRet;
}
/*
* 从指定进程释放DLL
* dwProcessID: 目标进程ID
* lpszDll: 待释放的DLL名称
* 返回释放成功与否
*/
inline BOOL FreeDllFromProcess( DWORD dwProcessID, LPCTSTR lpszDll )
{
//首先搜索进程的所有模块,如果没找到lpszDll指定的模块则直接退出
HANDLE hthSnapShot = ::CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessID );
if( hthSnapShot == INVALID_HANDLE_VALUE )
return FALSE;
BOOL bHasMod = FALSE;
MODULEENTRY32 hMod = { sizeof(MODULEENTRY32) };
BOOL bMoreMods = ::Module32First( hthSnapShot, &hMod );
while ( bMoreMods )
{
if( ( lstrcmpi( hMod.szExePath, lpszDll ) == 0 ) || ( lstrcmpi( hMod.szModule, lpszDll ) == 0 ) )
{
bHasMod = TRUE;
break;
}
bMoreMods = ::Module32Next( hthSnapShot, &hMod );
}
::CloseHandle( hthSnapShot );
if( !bHasMod )
return FALSE;
BOOL bRet = FALSE;
HANDLE hProcess = NULL;
do
{
hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessID );
if( hProcess == NULL )
break;
LPTHREAD_START_ROUTINE pfnThread = ( LPTHREAD_START_ROUTINE ) ::GetProcAddress( ::GetModuleHandle( _T("Kernel32") ), "FreeLibrary" );
if( pfnThread == NULL )
break;
HANDLE hThread = ::CreateRemoteThread( hProcess, NULL, 0, pfnThread, hMod.modBaseAddr, 0, NULL );
if( hThread == NULL )
break;
::WaitForSingleObject( hThread, INFINITE );
::CloseHandle( hThread );
bRet = TRUE;
} while( FALSE );
if( hProcess != NULL )
::CloseHandle( hProcess );
return bRet;
}
///////////////////////////////////CreateRemoteThread注入线程函数////////////////////////////////////////////////////
/*
* 在Debug下编译须去除/GZ编译开关
*/
typedef struct _SMsgBoxParam
{
DWORD_PTR m_pfnMsgBox; //MessageBox的函数地址
TCHAR m_szCaption[128]; //标题
TCHAR m_szText[256]; //文本
UINT m_uType; //MessageBox显示类型
}SMsgBoxParam, *PSMsgBoxParam;
DWORD WINAPI _InjectThreadProc( PSMsgBoxParam pMsgParam )
{
ATLASSERT( pMsgParam != NULL );
typedef int (WINAPI *PMessageBox)( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );
PMessageBox pfnMsgBox = (PMessageBox)pMsgParam->m_pfnMsgBox;
if( pfnMsgBox != NULL )
{
pfnMsgBox( NULL, pMsgParam->m_szText, pMsgParam->m_szCaption, pMsgParam->m_uType );
}
return 0;
}
const DWORD THREADSIZE = 4096;
inline BOOL InjectTaskIntoProcess( DWORD dwProcessID )
{
BOOL bRet = FALSE;
HANDLE hProcess = NULL;
LPVOID pRemoteProc = NULL;
PSMsgBoxParam pMsgParam = NULL;
do
{
//根据进程ID获取进程句柄
hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessID );
if( hProcess == NULL )
break;
//在远程进程中注入函数地址
pRemoteProc = ::VirtualAllocEx( hProcess, NULL, THREADSIZE, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE );
if( pRemoteProc == NULL )
break;
//写内存
if( !::WriteProcessMemory( hProcess, pRemoteProc, &_InjectThreadProc, THREADSIZE, NULL ) )
break;
//在远程进程中注入参数地址
SMsgBoxParam msgboxParam;
wsprintf( msgboxParam.m_szCaption, _T("提示") );
wsprintf( msgboxParam.m_szText, _T("来自注入进程的对话框") );
msgboxParam.m_uType = MB_OK;
#ifdef UNICODE
msgboxParam.m_pfnMsgBox = ( DWORD_PTR ) ::GetProcAddress( ::GetModuleHandle( _T("User32") ), "MessageBoxW" );
#else
msgboxParam.m_pfnMsgBox = ( DWORD_PTR ) ::GetProcAddress( ::GetModuleHandle( _T("User32") ), "MessageBoxA" );
#endif // !UNICODE
pMsgParam = (PSMsgBoxParam)::VirtualAllocEx( hProcess, NULL, sizeof(msgboxParam), MEM_COMMIT, PAGE_READWRITE );
if( pMsgParam == NULL )
break;
//写内存
if( !::WriteProcessMemory( hProcess, pMsgParam, &msgboxParam, sizeof(msgboxParam), NULL ) )
break;
HANDLE hThread = ::CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteProc, pMsgParam, 0, NULL );
if( hThread == NULL )
break;
//等待远程线程结束
::WaitForSingleObject( hThread, INFINITE );
::CloseHandle( hThread );
bRet = TRUE;
} while( FALSE );
//释放资源
if( pMsgParam != NULL )
::VirtualFreeEx( hProcess, pMsgParam, 0, MEM_RELEASE );
if( pRemoteProc != NULL )
::VirtualFreeEx( hProcess, pRemoteProc, 0, MEM_RELEASE );
if( hProcess != NULL )
::CloseHandle( hProcess );
return bRet;
}
/*
* 向指定进程注入DLL
* dwProcessID: 目标进程ID
* lpszDll: 待注入的DLL完全路径
* 返回注入成功与否
*/
inline BOOL InjectDllIntoProcess( DWORD dwProcessID, LPCTSTR lpszDll )
{
BOOL bRet = FALSE;
HANDLE hProcess = NULL;
PSTR pszRemoteDll = NULL;
do
{
//根据进程ID获取进程句柄
hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessID );
if( hProcess == NULL )
break;
int nAllocSize = ( _tcslen( lpszDll ) + 1 ) * sizeof(TCHAR);
//在远程进程中分配内存
pszRemoteDll = (PSTR)::VirtualAllocEx( hProcess, NULL, nAllocSize, MEM_COMMIT, PAGE_READWRITE );
if( pszRemoteDll == NULL )
break;
//写内存
if( !::WriteProcessMemory( hProcess, pszRemoteDll, lpszDll, nAllocSize, NULL ) )
break;
LPTHREAD_START_ROUTINE pfnThread = NULL;
//Kernel32模块在每个进程中都被映射到相同的地址,故在本进程获取到的LoadLibrary函数地址和远程进程中地址是一样的
#ifdef UNICODE
pfnThread = ( LPTHREAD_START_ROUTINE ) ::GetProcAddress( ::GetModuleHandle( _T("Kernel32") ), "LoadLibraryW" );
#else
pfnThread = ( LPTHREAD_START_ROUTINE ) ::GetProcAddress( ::GetModuleHandle( _T("Kernel32") ), "LoadLibraryA" );
#endif // !UNICODE
if( pfnThread == NULL )
break;
HANDLE hThread = ::CreateRemoteThread( hProcess, NULL, 0, pfnThread, pszRemoteDll, 0, NULL );
if( hThread == NULL )
break;
//等待远程线程结束
::WaitForSingleObject( hThread, INFINITE );
::CloseHandle( hThread );
bRet = TRUE;
} while( FALSE );
//释放资源
if( pszRemoteDll != NULL )
::VirtualFreeEx( hProcess, pszRemoteDll, 0, MEM_RELEASE );
if( hProcess != NULL )
::CloseHandle( hProcess );
return bRet;
}
/*
* 从指定进程释放DLL
* dwProcessID: 目标进程ID
* lpszDll: 待释放的DLL名称
* 返回释放成功与否
*/
inline BOOL FreeDllFromProcess( DWORD dwProcessID, LPCTSTR lpszDll )
{
//首先搜索进程的所有模块,如果没找到lpszDll指定的模块则直接退出
HANDLE hthSnapShot = ::CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessID );
if( hthSnapShot == INVALID_HANDLE_VALUE )
return FALSE;
BOOL bHasMod = FALSE;
MODULEENTRY32 hMod = { sizeof(MODULEENTRY32) };
BOOL bMoreMods = ::Module32First( hthSnapShot, &hMod );
while ( bMoreMods )
{
if( ( lstrcmpi( hMod.szExePath, lpszDll ) == 0 ) || ( lstrcmpi( hMod.szModule, lpszDll ) == 0 ) )
{
bHasMod = TRUE;
break;
}
bMoreMods = ::Module32Next( hthSnapShot, &hMod );
}
::CloseHandle( hthSnapShot );
if( !bHasMod )
return FALSE;
BOOL bRet = FALSE;
HANDLE hProcess = NULL;
do
{
hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessID );
if( hProcess == NULL )
break;
LPTHREAD_START_ROUTINE pfnThread = ( LPTHREAD_START_ROUTINE ) ::GetProcAddress( ::GetModuleHandle( _T("Kernel32") ), "FreeLibrary" );
if( pfnThread == NULL )
break;
HANDLE hThread = ::CreateRemoteThread( hProcess, NULL, 0, pfnThread, hMod.modBaseAddr, 0, NULL );
if( hThread == NULL )
break;
::WaitForSingleObject( hThread, INFINITE );
::CloseHandle( hThread );
bRet = TRUE;
} while( FALSE );
if( hProcess != NULL )
::CloseHandle( hProcess );
return bRet;
}
///////////////////////////////////CreateRemoteThread注入线程函数////////////////////////////////////////////////////
/*
* 在Debug下编译须去除/GZ编译开关
*/
typedef struct _SMsgBoxParam
{
DWORD_PTR m_pfnMsgBox; //MessageBox的函数地址
TCHAR m_szCaption[128]; //标题
TCHAR m_szText[256]; //文本
UINT m_uType; //MessageBox显示类型
}SMsgBoxParam, *PSMsgBoxParam;
DWORD WINAPI _InjectThreadProc( PSMsgBoxParam pMsgParam )
{
ATLASSERT( pMsgParam != NULL );
typedef int (WINAPI *PMessageBox)( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );
PMessageBox pfnMsgBox = (PMessageBox)pMsgParam->m_pfnMsgBox;
if( pfnMsgBox != NULL )
{
pfnMsgBox( NULL, pMsgParam->m_szText, pMsgParam->m_szCaption, pMsgParam->m_uType );
}
return 0;
}
const DWORD THREADSIZE = 4096;
inline BOOL InjectTaskIntoProcess( DWORD dwProcessID )
{
BOOL bRet = FALSE;
HANDLE hProcess = NULL;
LPVOID pRemoteProc = NULL;
PSMsgBoxParam pMsgParam = NULL;
do
{
//根据进程ID获取进程句柄
hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessID );
if( hProcess == NULL )
break;
//在远程进程中注入函数地址
pRemoteProc = ::VirtualAllocEx( hProcess, NULL, THREADSIZE, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE );
if( pRemoteProc == NULL )
break;
//写内存
if( !::WriteProcessMemory( hProcess, pRemoteProc, &_InjectThreadProc, THREADSIZE, NULL ) )
break;
//在远程进程中注入参数地址
SMsgBoxParam msgboxParam;
wsprintf( msgboxParam.m_szCaption, _T("提示") );
wsprintf( msgboxParam.m_szText, _T("来自注入进程的对话框") );
msgboxParam.m_uType = MB_OK;
#ifdef UNICODE
msgboxParam.m_pfnMsgBox = ( DWORD_PTR ) ::GetProcAddress( ::GetModuleHandle( _T("User32") ), "MessageBoxW" );
#else
msgboxParam.m_pfnMsgBox = ( DWORD_PTR ) ::GetProcAddress( ::GetModuleHandle( _T("User32") ), "MessageBoxA" );
#endif // !UNICODE
pMsgParam = (PSMsgBoxParam)::VirtualAllocEx( hProcess, NULL, sizeof(msgboxParam), MEM_COMMIT, PAGE_READWRITE );
if( pMsgParam == NULL )
break;
//写内存
if( !::WriteProcessMemory( hProcess, pMsgParam, &msgboxParam, sizeof(msgboxParam), NULL ) )
break;
HANDLE hThread = ::CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteProc, pMsgParam, 0, NULL );
if( hThread == NULL )
break;
//等待远程线程结束
::WaitForSingleObject( hThread, INFINITE );
::CloseHandle( hThread );
bRet = TRUE;
} while( FALSE );
//释放资源
if( pMsgParam != NULL )
::VirtualFreeEx( hProcess, pMsgParam, 0, MEM_RELEASE );
if( pRemoteProc != NULL )
::VirtualFreeEx( hProcess, pRemoteProc, 0, MEM_RELEASE );
if( hProcess != NULL )
::CloseHandle( hProcess );
return bRet;
}