ModuleScope.cpp
上传用户:jstlsd
上传日期:2007-01-13
资源大小:186k
文件大小:12k
源码类别:

钩子与API截获

开发平台:

Visual C++

  1. //---------------------------------------------------------------------------
  2. //
  3. // ModuleScope.h
  4. //
  5. // SUBSYSTEM:   Hook system
  6. //
  7. // MODULE:      Hook tool
  8. //
  9. // DESCRIPTION: Implementation of the CModuleScope class.
  10. //              This class is designed to provide single interface for 
  11. //              all hook related activities.
  12. // 
  13. //             
  14. // AUTHOR: Ivo Ivanov (ivopi@hotmail.com)
  15. // DATE: 2001 December v1.00
  16. //
  17. //---------------------------------------------------------------------------
  18. #include "..CommonCommon.h"
  19. #include "ModuleScope.h"
  20. #include "..CommonSysUtils.h"
  21. #include "..CommonIniFile.h"
  22. #include "..CommonCustomMessages.h"
  23. #include "Injector.h"
  24. //---------------------------------------------------------------------------
  25. //
  26. // class CModuleScope 
  27. //
  28. //---------------------------------------------------------------------------
  29. //---------------------------------------------------------------------------
  30. //
  31. // Static memeber declarations
  32. //
  33. //---------------------------------------------------------------------------
  34. CModuleScope* CModuleScope::sm_pInstance      = NULL;
  35. CLogFile*     CModuleScope::sm_pLogFile       = NULL;
  36. CApiHookMgr*  CModuleScope::sm_pHookMgr       = NULL;
  37. //---------------------------------------------------------------------------
  38. //
  39. // Constructor
  40. //
  41. //---------------------------------------------------------------------------
  42. CModuleScope::CModuleScope(
  43. HWND*  phwndServer,
  44. BOOL*  pbHookInstalled,
  45. HHOOK* pHook
  46. ):
  47. m_phwndServer(phwndServer),
  48. m_bTraceEnabledInitialized(FALSE),
  49. m_bTraceEnabled(FALSE),
  50. m_bUseWindowsHookInitialized(FALSE),
  51. m_bUseWindowsHook(TRUE),
  52. m_pInjector(NULL),
  53. m_pbHookInstalled(pbHookInstalled),
  54. m_pWhenZero(NULL)
  55. {
  56. //
  57. // Make sure we now where we are.
  58. //
  59. m_bIsThisServerProcess = (NULL == *phwndServer);
  60. // 
  61. // Instantiate the object that looks after DLL ref counting
  62. //
  63. m_pWhenZero = new CWhenZeroDword(m_bIsThisServerProcess);
  64. //
  65. // Get the name of the current process
  66. //
  67. GetProcessHostName(m_szProcessName);
  68. //
  69. // and its process id
  70. //
  71. m_dwProcessId = ::GetCurrentProcessId();
  72. //
  73. // Create instance of the log file manager
  74. //
  75. sm_pLogFile = new CLogFile(GetTraceEnabled());
  76. //
  77. // Instantiate the only one hook manager
  78. //
  79. sm_pHookMgr = new CApiHookMgr(this);
  80. //
  81. // Which kind of injection we would like to use?
  82. //
  83. if (IsWindows9x() || UseWindowsHook())
  84. m_pInjector = new CWinHookInjector(m_bIsThisServerProcess, pHook);
  85. else
  86. m_pInjector = new CRemThreadInjector(m_bIsThisServerProcess);
  87. }
  88. //---------------------------------------------------------------------------
  89. //
  90. // Destructor 
  91. //
  92. //---------------------------------------------------------------------------
  93. CModuleScope::~CModuleScope()
  94. {
  95. delete m_pInjector;
  96. delete m_pWhenZero;
  97. delete sm_pHookMgr;
  98. delete sm_pLogFile;
  99. }
  100. //---------------------------------------------------------------------------
  101. //
  102. // Copy constructor
  103. //
  104. //---------------------------------------------------------------------------
  105. CModuleScope::CModuleScope(const CModuleScope& rhs)
  106. {
  107. }
  108. //---------------------------------------------------------------------------
  109. //
  110. // Assignment operator
  111. //
  112. //---------------------------------------------------------------------------
  113. CModuleScope& CModuleScope::operator=(const CModuleScope& rhs)
  114. {
  115. if (this == &rhs) 
  116. return *this;
  117. return *this; // return reference to left-hand object
  118. }
  119. //---------------------------------------------------------------------------
  120. // GetInstance
  121. //
  122. // Implements the "double-checking" locking pattern combined with 
  123. // Scott Meyers single instance
  124. // For more details see - 
  125. // 1. "Modern C++ Design" by Andrei Alexandrescu - 6.9 Living in a 
  126. //     Multithreaded World
  127. // 2. "More Effective C++" by Scott Meyers - Item 26
  128. //---------------------------------------------------------------------------
  129. CModuleScope* CModuleScope::GetInstance(
  130. HWND*  phwndServer,
  131. BOOL*  pbHookInstalled,
  132. HHOOK* pHook
  133. )
  134. {
  135. if (!sm_pInstance)
  136. {
  137. CLockMgr<CCSWrapper> guard(g_ModuleSingeltonLock, TRUE);
  138. if (!sm_pInstance)
  139. {
  140. static CModuleScope instance(phwndServer, pbHookInstalled, pHook);
  141. sm_pInstance = &instance;
  142. char  szFileName[MAX_PATH];
  143. char  *pdest;
  144. ::GetModuleFileName(
  145. ModuleFromAddress(CModuleScope::GetInstance), 
  146. szFileName, 
  147. MAX_PATH
  148. );
  149. pdest = &szFileName[strlen(szFileName) - 4];
  150. strcpy(pdest, ".log");
  151. sm_pLogFile->InitializeFileName(szFileName);
  152. }
  153. } // if
  154. return sm_pInstance;
  155. }
  156. //
  157. // Called on DLL_PROCESS_ATTACH DLL notification
  158. //
  159. BOOL CModuleScope::ManageModuleEnlistment()
  160. {
  161. BOOL bResult = FALSE;
  162. //
  163. // Check if it is the hook server we should allow mapping of the DLL into
  164. // its address space
  165. //
  166. if (FALSE == *m_pbHookInstalled)
  167. {
  168. LogMessage( "------- Hook server loads HookTool library -------" );
  169. //
  170. // Set the flag, thus we will know that the server has been installed
  171. //
  172. *m_pbHookInstalled = TRUE;
  173. //
  174. // and return success error code
  175. //
  176. bResult = TRUE;
  177. }
  178. //
  179. // and any other process should be examined whether it should be
  180. // hooked up by the DLL
  181. //
  182. else
  183. {
  184. bResult = m_pInjector->IsProcessForHooking(m_szProcessName);
  185. if (bResult)
  186. InitializeHookManagement();
  187. //
  188. // DLL is about to be mapped
  189. //
  190. //
  191. // Notify the server process the DLL will be mapped
  192. //
  193. ::PostMessage(
  194. *m_phwndServer, 
  195. UWM_HOOKTOOL_DLL_LOADED, 
  196. 0, 
  197. ::GetCurrentProcessId()
  198. );
  199. }
  200. return bResult;
  201. }
  202. //
  203. // Called on DLL_PROCESS_DETACH notification
  204. //
  205. void CModuleScope::ManageModuleDetachment()
  206. {
  207. //
  208. // Check if the request comes from hooked up application
  209. //
  210. if ( !m_bIsThisServerProcess )
  211. {
  212. FinalizeHookManagement();
  213. //
  214. // Is the server still running ?
  215. //
  216. if (NULL != *m_phwndServer)
  217. //
  218. // Notify the server process the DLL is about to be unmapped
  219. //
  220. ::PostMessage(
  221. *m_phwndServer, 
  222. UWM_HOOKTOOL_DLL_UNLOADED, 
  223. 0, 
  224. ::GetCurrentProcessId()
  225. );
  226. } // if
  227. else
  228. {
  229. //
  230. // attempt to eject the dll
  231. //
  232. m_pInjector->EjectModuleFromAllProcesses(m_pWhenZero->GetZeroHandle());
  233. LogMessage( "------- Hook server shuts down and unloads HookTool library -------");
  234. }
  235. }
  236. //
  237. // Activate/Deactivate hooking engine
  238. //
  239. BOOL CModuleScope::InstallHookMethod(
  240. BOOL bActivate, 
  241. HWND hWndServer
  242. )
  243. {
  244. BOOL bResult;
  245. if (bActivate)
  246. {
  247. *m_phwndServer = hWndServer;
  248. bResult = m_pInjector->InjectModuleIntoAllProcesses();
  249. }
  250. else
  251. {
  252. m_pInjector->EjectModuleFromAllProcesses(m_pWhenZero->GetZeroHandle());
  253. *m_phwndServer = NULL;
  254. bResult = TRUE;
  255. }
  256. return bResult;
  257. }
  258. //
  259. // 
  260. //
  261. void CModuleScope::LogMessage(const char* pszBuffer)
  262. {
  263. char    szPrintBuffer[MAX_PATH];
  264. sprintf(
  265. szPrintBuffer, 
  266. "%s(%u) - %s", 
  267. m_szProcessName, 
  268. m_dwProcessId, 
  269. pszBuffer
  270. );
  271. sm_pLogFile->DoLogMessage(szPrintBuffer);
  272. }
  273. //
  274. // Accessor method
  275. //
  276. char* CModuleScope::GetProcessName() const
  277. {
  278. return const_cast<char*>(m_szProcessName);
  279. }
  280. //
  281. // Accessor method
  282. //
  283. DWORD CModuleScope::GetProcessId() const
  284. {
  285. return m_dwProcessId;
  286. }
  287. //
  288. // Return the name of the INI file
  289. //
  290. void CModuleScope::GetIniFile(char* pszIniFile)
  291. {
  292. char  *pdest;
  293. ::GetModuleFileName(
  294. ModuleFromAddress(CModuleScope::GetInstance), 
  295. pszIniFile, 
  296. MAX_PATH
  297. );
  298. pdest = &pszIniFile[strlen(pszIniFile) - 4];
  299. strcpy(pdest, ".ini");
  300. }
  301. //
  302. // Get the value of [Trace] / Enabled from the INI file
  303. //
  304. BOOL CModuleScope::GetTraceEnabled()
  305. {
  306. if (!m_bTraceEnabledInitialized)
  307. {
  308. m_bTraceEnabled = FALSE;
  309. char szIniFile[MAX_PATH];
  310. GetIniFile(szIniFile);
  311. CIniFile iniFile(szIniFile);
  312. m_bTraceEnabled = iniFile.ReadBool(
  313. "Trace",
  314. "Enabled",
  315. FALSE
  316. );
  317. m_bTraceEnabledInitialized = TRUE;
  318. } // if
  319. return m_bTraceEnabled;
  320. }
  321. //
  322. // Determines whether Windows hook is going to be used
  323. //
  324. BOOL CModuleScope::UseWindowsHook()
  325. {
  326. if (!m_bUseWindowsHookInitialized)
  327. {
  328. char szIniFile[MAX_PATH];
  329. GetIniFile(szIniFile);
  330. CIniFile iniFile(szIniFile);
  331. m_bUseWindowsHook = iniFile.ReadBool(
  332. "Scope",
  333. "UseWindowsHook",
  334. TRUE
  335. );
  336. m_bUseWindowsHookInitialized = TRUE;
  337. }
  338. return m_bUseWindowsHook;
  339. }
  340. //
  341. // Hooks up an API function
  342. //
  343. BOOL CModuleScope::HookImport(
  344. PCSTR pszCalleeModName, 
  345. PCSTR pszFuncName, 
  346. PROC  pfnHook
  347. )
  348. {
  349. return sm_pHookMgr->HookImport(
  350. pszCalleeModName,
  351. pszFuncName,
  352. pfnHook
  353. );
  354. }
  355. //
  356. // Restores the original API function pointer
  357. //
  358. BOOL CModuleScope::UnHookImport(
  359. PCSTR pszCalleeModName, 
  360. PCSTR pszFuncName
  361. )
  362. {
  363. return sm_pHookMgr->UnHookImport(
  364. pszCalleeModName,
  365. pszFuncName
  366. );
  367. }
  368. //
  369. // Initialize hook engine
  370. //
  371. void CModuleScope::InitializeHookManagement()
  372. {
  373. //
  374. // Initially we must hook a few important functions
  375. //
  376. sm_pHookMgr->HookSystemFuncs();
  377. //
  378. // and now we can set-up some custom (demonstration) hooks
  379. //
  380. sm_pHookMgr->HookImport("Gdi32.DLL", "TextOutA", (PROC)CModuleScope::MyTextOutA);
  381. sm_pHookMgr->HookImport("Gdi32.DLL", "TextOutW", (PROC)CModuleScope::MyTextOutW);
  382. sm_pHookMgr->HookImport("Kernel32.DLL", "ExitProcess", (PROC)CModuleScope::MyExitProcess);
  383. LogMessage("The hook engine has been activated.");
  384. }
  385. //
  386. // Release all resource required by the hooking engine
  387. //
  388. void CModuleScope::FinalizeHookManagement()
  389. {
  390. if (sm_pHookMgr->AreThereHookedFunctions())
  391. LogMessage("The hook engine has been deactivated.");
  392. sm_pHookMgr->UnHookAllFuncs();
  393. }
  394. //
  395. // Our own TextOutA
  396. //
  397. BOOL WINAPI CModuleScope::MyTextOutA(
  398. HDC   hdc,           // handle to DC
  399. int   nXStart,       // x-coordinate of starting position
  400. int   nYStart,       // y-coordinate of starting position
  401. LPSTR lpString,      // character string
  402. int   cbString       // number of characters
  403. )
  404. {
  405. BOOL bResult;
  406. char szBuffer[1024];
  407. ::ZeroMemory((PBYTE)szBuffer, sizeof(szBuffer));
  408. if (0 == stricmp(lpString, "Hello from TestApp!"))
  409. {
  410. strcpy(szBuffer, "Do you recon this is the original text ?");
  411. cbString = strlen(szBuffer);
  412. } // if
  413. else
  414. memcpy((PBYTE)szBuffer, (PBYTE)lpString, cbString*sizeof(char));
  415. bResult = ::TextOutA(
  416. hdc,        // handle to DC
  417. nXStart,    // x-coordinate of starting position
  418. nYStart,    // y-coordinate of starting position
  419. szBuffer,   // character string
  420. cbString    // number of characters
  421. );
  422. return bResult;
  423. }
  424. //
  425. // Our own TextOutA
  426. //
  427. BOOL WINAPI CModuleScope::MyTextOutW(
  428. HDC   hdc,           // handle to DC
  429. int   nXStart,       // x-coordinate of starting position
  430. int   nYStart,       // y-coordinate of starting position
  431. LPWSTR lpString,     // character string
  432. int   cbString       // number of characters
  433. )
  434. {
  435. BOOL    bResult;
  436. wchar_t szBuffer[1024];
  437. ::ZeroMemory((PBYTE)szBuffer, sizeof(szBuffer));
  438. if (0 == wcsicmp(lpString, L"Hello from TestApp!"))
  439. {
  440. wcscpy(szBuffer, L"Do you recon this is the original text ?");
  441. cbString = wcslen(szBuffer);
  442. } // if
  443. else
  444. memcpy((PBYTE)szBuffer, (PBYTE)lpString, cbString*sizeof(wchar_t));
  445. bResult = ::TextOutW(
  446. hdc,        // handle to DC
  447. nXStart,    // x-coordinate of starting position
  448. nYStart,    // y-coordinate of starting position
  449. szBuffer,   // character string
  450. cbString    // number of characters
  451. );
  452. return bResult;
  453. }
  454. //
  455. // Our own ExitProcess
  456. //
  457. VOID WINAPI CModuleScope::MyExitProcess(
  458. UINT uExitCode   // exit code for all threads
  459. )
  460. {
  461. char szBuffer[MAX_PATH];
  462. sprintf(szBuffer, "Process (%u) shuts down.", ::GetCurrentProcessId());
  463. sm_pInstance->LogMessage(szBuffer);
  464. ::ExitProcess(uExitCode);
  465. return;
  466. }
  467. //----------------------------End of the file -------------------------------