1 #ifndef NCBI_WIN_HOOK__HPP 2 #define NCBI_WIN_HOOK__HPP 3 4 /* $Id: ncbi_win_hook.hpp 403742 2013-06-18 15:26:09Z grichenk $ 5 * =========================================================================== 6 * 7 * PUBLIC DOMAIN NOTICE 8 * National Center for Biotechnology Information 9 * 10 * This software/database is a "United States Government Work" under the 11 * terms of the United States Copyright Act. It was written as part of 12 * the author's official duties as a United States Government employee and 13 * thus cannot be copyrighted. This software/database is freely available 14 * to the public for use. The National Library of Medicine and the U.S. 15 * Government have not placed any restriction on its use or reproduction. 16 * 17 * Although all reasonable efforts have been taken to ensure the accuracy 18 * and reliability of the software and data, the NLM and the U.S. 19 * Government do not and cannot warrant the performance or results that 20 * may be obtained by using this software or data. The NLM and the U.S. 21 * Government disclaim all warranties, express or implied, including 22 * warranties of performance, merchantability or fitness for any particular 23 * purpose. 24 * 25 * Please cite the author in any work or product based on this material. 26 * 27 * =========================================================================== 28 * 29 * Author: Sergey Sikorskiy 30 * 31 * File Description: Windows DLL function hooking 32 * 33 */ 34 35 36 /** @addtogroup WinHook 37 * 38 * @{ 39 */ 40 41 #if defined(NCBI_OS_MSWIN) 42 43 #include <corelib/ncbi_safe_static.hpp> 44 #include <process.h> 45 #include <Tlhelp32.h> 46 #include <vector> 47 48 BEGIN_NCBI_SCOPE 49 50 namespace NWinHook 51 { 52 53 /////////////////////////////////////////////////////////////////////////////// 54 class NCBI_DBAPIDRIVER_EXPORT CWinHookException : public CCoreException 55 { 56 public: 57 enum EErrCode { 58 eDbghelp, 59 eDisabled 60 }; 61 62 /// Translate from the error code value to its string representation. 63 virtual const char* GetErrCodeString(void) const; 64 65 // Standard exception boilerplate code. 66 NCBI_EXCEPTION_DEFAULT(CWinHookException, CCoreException); 67 }; 68 69 70 /////////////////////////////////////////////////////////////////////////////// 71 /// class CHookedFunctions 72 /// 73 class CHookedFunction; 74 75 int my_stricmp(const char* left, const char* right); 76 77 // !!! Not thred-safe class !!! 78 class CHookedFunctions 79 { 80 public: 81 CHookedFunctions(void); 82 ~CHookedFunctions(void); 83 84 public: 85 /// Return the address of an CHookedFunction object 86 CRef<CHookedFunction> GetHookedFunction( 87 PCSTR pszCalleeModName, 88 PCSTR pszFuncName 89 ) const; 90 91 /// Return the address of an CHookedFunction object 92 CRef<CHookedFunction> GetHookedFunction( 93 HMODULE hmod, 94 PCSTR pszFuncName 95 ) const; 96 97 /// Add a new object to the container 98 BOOL AddHook(const CRef<CHookedFunction> pHook); 99 /// Remove exising object pointer from the container 100 BOOL RemoveHook(const CRef<CHookedFunction> pHook); 101 102 void UnHookAllFuncs(void); 103 HaveHookedFunctions(void) const104 bool HaveHookedFunctions(void) const 105 { 106 // return(m_FunctionList.size() > 0); 107 size_t num = 0; 108 109 ITERATE(TModuleList, it, m_ModuleList) { 110 num += it->second.size(); 111 } 112 113 return (num > 0); 114 } 115 116 private: 117 /// Return the name of the function from EAT by its ordinal value 118 BOOL x_GetFunctionNameFromExportSection( 119 HMODULE hmodOriginal, 120 DWORD dwFuncOrdinalNum, 121 PSTR pszFuncName 122 ) const; 123 /// Return the name of the function by its ordinal value 124 void x_GetFunctionNameByOrdinal( 125 PCSTR pszCalleeModName, 126 DWORD dwFuncOrdinalNum, 127 PSTR pszFuncName 128 ) const; 129 void x_GetFunctionNameByOrdinal( 130 HMODULE hmodOriginal, 131 DWORD dwFuncOrdinalNum, 132 PSTR pszFuncName 133 ) const; 134 135 private: 136 struct SNocaseCmp { operator ()NWinHook::CHookedFunctions::SNocaseCmp137 bool operator()(const string& x, const string& y) const { 138 return my_stricmp(x.c_str(), y.c_str()) < 0; 139 } 140 }; 141 typedef map<string, CRef<CHookedFunction>, SNocaseCmp> TFunctionList; 142 typedef map<void*, TFunctionList> TModuleList; 143 typedef map<string, TFunctionList, SNocaseCmp> TModuleNameList; 144 145 // TFunctionList m_FunctionList; 146 TModuleList m_ModuleList; 147 TModuleNameList m_ModuleNameList; 148 149 // Because of CApiHookMgr::HackModuleOnLoad 150 friend class CApiHookMgr; 151 }; 152 153 154 /////////////////////////////////////////////////////////////////////////////// 155 /// class CApiHookMgr 156 /// 157 class CApiHookMgr { 158 private: 159 CApiHookMgr(void); 160 ~CApiHookMgr(void); 161 void operator =(const CApiHookMgr&); 162 163 public: 164 static CApiHookMgr& GetInstance(void); 165 166 /// Hook up an API 167 BOOL HookImport(PCSTR pszCalleeModName, 168 PCSTR pszFuncName, 169 PROC pfnHook 170 ); 171 172 /// Restore hooked up API function 173 BOOL UnHookImport(PCSTR pszCalleeModName, 174 PCSTR pszFuncName 175 ); 176 177 /// Used when a DLL is newly loaded after hooking a function 178 void WINAPI HackModuleOnLoad(HMODULE hmod, 179 DWORD dwFlags 180 ); 181 182 /// Return the address of an CHookedFunction object 183 /// Protected version. 184 CRef<CHookedFunction> GetHookedFunction(HMODULE hmod, 185 PCSTR pszFuncName 186 ) const; 187 188 /// Indicates whether there is hooked function 189 bool HaveHookedFunctions(void) const; 190 191 private: 192 /// Hook all needed system functions in order to trap loading libraries 193 BOOL x_HookSystemFuncs(void); 194 195 /// Unhook all functions and restore original ones 196 void x_UnHookAllFuncs(void); 197 198 /// Used to trap events when DLLs are loaded 199 static HMODULE WINAPI MyLoadLibraryA(PCSTR pszModuleName); 200 /// Used to trap events when DLLs are loaded 201 static HMODULE WINAPI MyLoadLibraryW(PCWSTR pszModuleName); 202 /// Used to trap events when DLLs are loaded 203 static HMODULE WINAPI MyLoadLibraryExA(PCSTR pszModuleName, 204 HANDLE hFile, 205 DWORD dwFlags 206 ); 207 /// Used to trap events when DLLs are loaded 208 static HMODULE WINAPI MyLoadLibraryExW(PCWSTR pszModuleName, 209 HANDLE hFile, 210 DWORD dwFlags 211 ); 212 /// Returns address of replacement function if hooked function is 213 /// requested 214 static FARPROC WINAPI MyGetProcAddress(HMODULE hmod, 215 PCSTR pszProcName 216 ); 217 218 /// Returns original address of the API function 219 static FARPROC WINAPI xs_GetProcAddressWindows( 220 HMODULE hmod, 221 PCSTR pszProcName 222 ); 223 224 /// Add a newly intercepted function to the container 225 BOOL x_AddHook(PCSTR pszCalleeModName, 226 PCSTR pszFuncName, 227 PROC pfnOrig, 228 PROC pfnHook 229 ); 230 231 /// Remove intercepted function from the container 232 BOOL x_RemoveHook(PCSTR pszCalleeModName, 233 PCSTR pszFuncName 234 ); 235 236 mutable CFastMutex m_Mutex; 237 /// Container keeps track of all hacked functions 238 CHookedFunctions m_pHookedFunctions; 239 /// Determines whether all system functions has been successfuly hacked 240 BOOL m_bSystemFuncsHooked; 241 242 friend class CSafeStatic_Allocator<CApiHookMgr>; 243 }; 244 245 246 class NCBI_DBAPIDRIVER_EXPORT COnExitProcess 247 { 248 public: 249 typedef void (*TFunct) (void); 250 251 static COnExitProcess& Instance(void); 252 253 // Return true in case of success. 254 bool Add(TFunct funct); 255 void Remove(TFunct funct); 256 void ClearAll(void); 257 258 private: 259 COnExitProcess(void); 260 ~COnExitProcess(void); 261 262 // Hook function prototype 263 static void WINAPI xs_ExitProcess(UINT uExitCode); 264 265 private: 266 typedef vector<TFunct> TRegistry; 267 268 CFastMutex m_Mutex; 269 TRegistry m_Registry; 270 bool m_Hooked; 271 272 friend class CSafeStatic_Allocator<COnExitProcess>; 273 }; 274 } 275 276 END_NCBI_SCOPE 277 278 #endif // NCBI_OS_MSWIN 279 280 /* @} */ 281 282 #endif // NCBI_WIN_HOOK__HPP 283