Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
Injector.cpp
Package: apihook_Code.zip [view]
Upload User: jstlsd
Upload Date: 2007-01-13
Package Size: 186k
Code Size: 14k
Category:
Hook api
Development Platform:
Visual C++
- //---------------------------------------------------------------------------
- //
- // Injector.cpp
- //
- // SUBSYSTEM:
- // API hooking system
- // MODULE:
- // Implements injection mechanism
- //
- // DESCRIPTION:
- //
- //
- // AUTHOR: Ivo Ivanov (ivopi@hotmail.com)
- // DATE: 2001 November 13, version 1.0
- //
- // FIXES:
- // - 2002 November 20
- // Added a mechanism for handling reference count of the HookTool.dll
- // instances. This allows us to fix a problem caused by the asynchronous
- // behavior of ::UnhookWindowsHookEx() API
- //
- //---------------------------------------------------------------------------
- #include "Injector.h"
- #include "..CommonModuleInstance.h"
- #include "..CommonSysUtils.h"
- #include "..CommonIniFile.h"
- #include "NtInjectorThread.h"
- //---------------------------------------------------------------------------
- //
- // Thread function prototype
- //
- //---------------------------------------------------------------------------
- typedef unsigned (__stdcall *PTHREAD_START)(void *);
- //---------------------------------------------------------------------------
- //
- // External declarations
- //
- //---------------------------------------------------------------------------
- extern LRESULT CALLBACK GetMsgProc(
- int code, // hook code
- WPARAM wParam, // removal option
- LPARAM lParam // message
- );
- //---------------------------------------------------------------------------
- //
- // class CInjector
- //
- //---------------------------------------------------------------------------
- CInjector::CInjector(BOOL bServerInstance):
- m_bServerInstance(bServerInstance),
- m_bHookAllEnabledInitialized(FALSE),
- m_bHookAllEnabled(FALSE)
- {
- }
- CInjector::~CInjector()
- {
- }
- //
- // examines whether a process should be hooked up by the DLL
- //
- BOOL CInjector::IsProcessForHooking(PSTR pszExaminedProcessName)
- {
- BOOL bHoolAll = GetHookAllEnabled();
- BOOL bProcessProtected = FALSE;
- char szProcessName[MAX_PATH];
- DWORD dwStartPos = 0;
- long nCommaPos;
- if (bHoolAll)
- {
- while ( (dwStartPos < strlen(m_szProcessesForHooking)) &&
- GetNextCommaSeparatedString(
- &m_szProcessesForHooking[dwStartPos],
- szProcessName,
- sizeof(szProcessName),
- &nCommaPos
- )
- )
- {
- strcat(szProcessName, ".exe");
- if (0 == stricmp(szProcessName, pszExaminedProcessName))
- {
- bProcessProtected = TRUE;
- return FALSE;
- } // if
- dwStartPos += nCommaPos + 1;
- } // while
- } // if
- if (!bHoolAll)
- {
- dwStartPos = 0;
- while ( (dwStartPos < strlen(m_szProcessesForHooking)) &&
- GetNextCommaSeparatedString(
- &m_szProcessesForHooking[dwStartPos],
- szProcessName,
- sizeof(szProcessName),
- &nCommaPos
- )
- )
- {
- strcat(szProcessName, ".exe");
- if (0 == stricmp(szProcessName, pszExaminedProcessName))
- return TRUE;
- dwStartPos += nCommaPos + 1;
- } // while
- return FALSE;
- } // if
- return TRUE;
- }
- //
- // Return the name of the INI file
- //
- void CInjector::GetIniFile(char* pszIniFile)
- {
- char *pdest;
- ::GetModuleFileName(
- ModuleFromAddress(GetMsgProc),
- pszIniFile,
- MAX_PATH
- );
- pdest = &pszIniFile[strlen(pszIniFile) - 4];
- strcpy(pdest, ".ini");
- }
- //
- // Get the value of [Scope] / HookAll from the INI file
- //
- BOOL CInjector::GetHookAllEnabled()
- {
- if (!m_bHookAllEnabledInitialized)
- {
- char szIniFile[MAX_PATH];
- GetIniFile(szIniFile);
- CIniFile iniFile(szIniFile);
- m_bHookAllEnabled = iniFile.ReadBool(
- "Scope",
- "HookAll",
- TRUE
- );
- m_bHookAllEnabledInitialized = TRUE;
- strcpy(m_szProcessesForHooking, "");
- strcpy(m_szProtectedProcesses, "");
- //
- // Should we process the two lists with processes for hooking
- // and ones that shouldn't be hooked up at all
- //
- if (!m_bHookAllEnabled)
- iniFile.ReadString(
- "Scope",
- "Hook",
- "",
- m_szProcessesForHooking
- );
- else
- iniFile.ReadString(
- "Scope",
- "Protect",
- "",
- m_szProtectedProcesses
- );
- } // if
- return m_bHookAllEnabled;
- }
- //---------------------------------------------------------------------------
- //
- // class CWinHookInjector
- //
- //---------------------------------------------------------------------------
- HHOOK* CWinHookInjector::sm_pHook = NULL;
- CWinHookInjector::CWinHookInjector(BOOL bServerInstance, HHOOK* pHook):
- CInjector(bServerInstance)
- {
- sm_pHook = pHook;
- }
- //
- // Inject the DLL into all running processes
- //
- BOOL CWinHookInjector::InjectModuleIntoAllProcesses()
- {
- *sm_pHook = ::SetWindowsHookEx(
- WH_GETMESSAGE,
- (HOOKPROC)(GetMsgProc),
- ModuleFromAddress(GetMsgProc),
- 0
- );
- return (NULL != *sm_pHook);
- }
- //
- // Eject the DLL from all processes if it has been injected before
- //
- BOOL CWinHookInjector::EjectModuleFromAllProcesses(HANDLE hWaitOn)
- {
- BOOL bResult;
- if (NULL != *sm_pHook)
- {
- bResult = ::UnhookWindowsHookEx(*sm_pHook);
- // Wait on the reference counter event handle
- // until all the instances of the DLL get unloaded
- ::WaitForSingleObject(hWaitOn, INFINITE);
- }
- else
- bResult = TRUE;
- return bResult;
- }
- //---------------------------------------------------------------------------
- //
- // class CRemThreadInjector
- //
- //---------------------------------------------------------------------------
- CCSWrapper CRemThreadInjector::sm_CritSecInjector;
- //
- //
- //
- CRemThreadInjector::CRemThreadInjector(BOOL bServerInstance):
- CInjector(bServerInstance),
- m_pNtInjectorThread(NULL)
- {
- if (bServerInstance)
- m_pNtInjectorThread = new CNtInjectorThread(this);
- }
- //
- //
- //
- CRemThreadInjector::~CRemThreadInjector()
- {
- if (m_bServerInstance)
- {
- m_pNtInjectorThread->SetActive(FALSE);
- delete m_pNtInjectorThread;
- } // if
- }
- //
- // Attempts to enable SeDebugPrivilege. This is required by use of
- // CreateRemoteThread() under NT/2K
- //
- BOOL CRemThreadInjector::EnableDebugPrivilege()
- {
- HANDLE hToken;
- LUID sedebugnameValue;
- TOKEN_PRIVILEGES tp;
- if ( !::OpenProcessToken(
- GetCurrentProcess(),
- TOKEN_ADJUST_PRIVILEGES | // to adjust privileges
- TOKEN_QUERY, // to get old privileges setting
- &hToken
- ) )
- //
- // OpenProcessToken() failed
- //
- return FALSE;
- //
- // Given a privilege's name SeDebugPrivilege, we should locate its local LUID mapping.
- //
- if ( !::LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
- {
- //
- // LookupPrivilegeValue() failed
- //
- ::CloseHandle( hToken );
- return FALSE;
- }
- tp.PrivilegeCount = 1;
- tp.Privileges[0].Luid = sedebugnameValue;
- tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- if ( !::AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(tp), NULL, NULL ) )
- {
- //
- // AdjustTokenPrivileges() failed
- //
- ::CloseHandle( hToken );
- return FALSE;
- }
- ::CloseHandle( hToken );
- return TRUE;
- }
- //
- // Inject the DLL into all running processes
- //
- BOOL CRemThreadInjector::InjectModuleIntoAllProcesses()
- {
- BOOL bResult = FALSE;
- if (m_bServerInstance)
- {
- CTaskManager taskManager;
- CExeModuleInstance* pProcess;
- taskManager.Populate(FALSE);
- EnableDebugPrivilege();
- for (long i = 0; i < taskManager.GetProcessCount(); i++)
- {
- pProcess = taskManager.GetProcessByIndex(i);
- bResult = InjectModuleInto( pProcess->Get_ProcessId() ) || bResult;
- } // for
- m_pNtInjectorThread->SetActive(TRUE);
- } // if
- return bResult;
- }
- //
- // Eject the DLL from all processes if it has been injected before
- //
- BOOL CRemThreadInjector::EjectModuleFromAllProcesses(HANDLE hWaitOn)
- {
- BOOL bResult = FALSE;
- if (m_bServerInstance)
- {
- CTaskManager taskManager;
- CExeModuleInstance* pProcess;
- m_pNtInjectorThread->SetActive(FALSE);
- taskManager.Populate(FALSE);
- for (long i = 0; i < taskManager.GetProcessCount(); i++)
- {
- pProcess = taskManager.GetProcessByIndex(i);
- bResult = EjectModuleFrom( pProcess->Get_ProcessId() ) || bResult;
- } // for
- } // if
- return bResult;
- }
- //
- // Inject the DLL into address space of a specific external process
- //
- BOOL CRemThreadInjector::InjectModuleInto(DWORD dwProcessId)
- {
- CLockMgr<CCSWrapper> lockMgr(sm_CritSecInjector, TRUE);
- BOOL bResult = FALSE;
- //
- // We shouldn't inject the dll into the address space of the
- // server
- //
- if (dwProcessId != ::GetCurrentProcessId())
- {
- CTaskManager taskManager;
- taskManager.PopulateProcess(dwProcessId, TRUE);
- CExeModuleInstance *pProcess = taskManager.GetProcessById(dwProcessId);
- if (TRUE == IsProcessForHooking(pProcess->GetBaseName()))
- bResult = DoInjectModuleInto(pProcess);
- } // if
- return bResult;
- }
- //
- // Eject the DLL from the address space of an external process
- //
- BOOL CRemThreadInjector::EjectModuleFrom(DWORD dwProcessId)
- {
- CLockMgr<CCSWrapper> lockMgr(sm_CritSecInjector, TRUE);
- BOOL bResult = FALSE;
- //
- // We shouldn't eject the dll into the address space of the
- // server
- //
- if (dwProcessId != ::GetCurrentProcessId())
- {
- CTaskManager taskManager;
- taskManager.PopulateProcess(dwProcessId, TRUE);
- CExeModuleInstance *pProcess = taskManager.GetProcessById(dwProcessId);
- if (pProcess)
- bResult = DoEjectModuleFrom(*pProcess);
- } // if
- return bResult;
- }
- //
- // Execute injection mechanism for NT/2K systems
- //
- BOOL CRemThreadInjector::DoInjectModuleInto(CExeModuleInstance *pProcess)
- {
- BOOL bResult = FALSE;
- HANDLE hProcess = NULL;
- HANDLE hThread = NULL;
- PSTR pszLibFileRemote = NULL;
- __try
- {
- if (TRUE == IsWindows9x())
- __leave;
- if (NULL == pProcess)
- __leave;
- char szLibFile[MAX_PATH];
- ::GetModuleFileNameA(
- ModuleFromAddress(GetMsgProc),
- szLibFile,
- MAX_PATH
- );
- BOOL bFound = FALSE;
- CModuleInstance* pModuleInstance;
- for (long i = 0; i < pProcess->GetModuleCount(); i++)
- {
- pModuleInstance = pProcess->GetModuleByIndex(i);
- if ( 0 == stricmp(pModuleInstance->Get_Name(), szLibFile) )
- {
- bFound = TRUE;
- break;
- } // if
- } // for
- if (bFound)
- __leave;
- // Get a handle for the process we want to inject into
- hProcess = ::OpenProcess(
- PROCESS_ALL_ACCESS, // Specifies all possible access flags
- FALSE,
- pProcess->Get_ProcessId()
- );
- if (hProcess == NULL)
- __leave;
- // Calculate the number of bytes needed for the DLL's pathname
- int cch = 1 + strlen(szLibFile);
- // Allocate space in the remote process for the pathname
- pszLibFileRemote = (PSTR)::VirtualAllocEx(
- hProcess,
- NULL,
- cch,
- MEM_COMMIT,
- PAGE_READWRITE
- );
- if (pszLibFileRemote == NULL)
- __leave;
- // Copy the DLL's pathname to the remote process's address space
- if (!::WriteProcessMemory(
- hProcess,
- (PVOID)pszLibFileRemote,
- (PVOID)szLibFile,
- cch,
- NULL))
- __leave;
- // Get the real address of LoadLibraryW in Kernel32.dll
- PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
- ::GetProcAddress(::GetModuleHandle("Kernel32"), "LoadLibraryA");
- if (pfnThreadRtn == NULL)
- __leave;
- // Create a remote thread that calls LoadLibraryW(DLLPathname)
- hThread = ::CreateRemoteThread(
- hProcess,
- NULL,
- 0,
- pfnThreadRtn,
- (PVOID)pszLibFileRemote,
- 0,
- NULL
- );
- if (hThread == NULL)
- __leave;
- // Wait for the remote thread to terminate
- ::WaitForSingleObject(hThread, INFINITE);
- bResult = TRUE;
- }
- __finally
- {
- // Free the remote memory that contained the DLL's pathname
- if (pszLibFileRemote != NULL)
- ::VirtualFreeEx(hProcess, (PVOID)pszLibFileRemote, 0, MEM_RELEASE);
- if (hThread != NULL)
- ::CloseHandle(hThread);
- if (hProcess != NULL)
- ::CloseHandle(hProcess);
- }
- return bResult;
- }
- //
- // Perform actual ejection of the DLL from the address space of an external process
- //
- BOOL CRemThreadInjector::DoEjectModuleFrom(CExeModuleInstance& process)
- {
- BOOL bResult = FALSE;
- HANDLE hProcess = NULL;
- HANDLE hThread = NULL;
- __try
- {
- if (TRUE == IsWindows9x())
- __leave;
- //
- // Do not force the server to eject the DLL
- //
- if (process.Get_ProcessId() == ::GetCurrentProcessId())
- __leave;
- char szLibFile[MAX_PATH];
- ::GetModuleFileNameA(
- ModuleFromAddress(GetMsgProc),
- szLibFile,
- MAX_PATH
- );
- BOOL bFound = FALSE;
- CModuleInstance* pModuleInstance;
- for (long i = 0; i < process.GetModuleCount(); i++)
- {
- pModuleInstance = process.GetModuleByIndex(i);
- if ( 0 == stricmp(pModuleInstance->Get_Name(), szLibFile) )
- {
- bFound = TRUE;
- break;
- } // if
- } // for
- if (!bFound)
- __leave;
- // Get a handle for the target process.
- hProcess = ::OpenProcess(
- PROCESS_ALL_ACCESS, // Specifies all possible access flags
- FALSE,
- process.Get_ProcessId()
- );
- if (hProcess == NULL)
- __leave;
- // Get the real address of LoadLibraryW in Kernel32.dll
- PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
- ::GetProcAddress(::GetModuleHandle("Kernel32"), "FreeLibrary");
- if (pfnThreadRtn == NULL)
- __leave;
- // Create a remote thread that calls LoadLibraryW(DLLPathname)
- hThread = ::CreateRemoteThread(
- hProcess,
- NULL,
- 0,
- pfnThreadRtn,
- pModuleInstance->Get_Module(),
- 0,
- NULL
- );
- if (hThread == NULL)
- __leave;
- // Wait for the remote thread to terminate
- ::WaitForSingleObject(hThread, INFINITE);
- bResult = TRUE;
- }
- __finally
- {
- if (hThread != NULL)
- ::CloseHandle(hThread);
- if (hProcess != NULL)
- ::CloseHandle(hProcess);
- }
- return bResult;
- }
- //----------------------------End of the file -------------------------------