HookAPI.cpp
上传用户:nbcables
上传日期:2007-01-11
资源大小:1243k
文件大小:14k
源码类别:

钩子与API截获

开发平台:

Visual C++

  1. // ------------------------------------- //
  2. // 您如果要使用本文件,请不要删除本说明  //
  3. // ------------------------------------- //
  4. //             HOOKAPI v1.6              //
  5. //   Copyright 2002 编程沙龙 Paladin     //
  6. //       www.ProgramSalon.com            //
  7. // ------------------------------------- //
  8. // 
  9. //  HookAPI.cpp
  10. //  通过取得函数地址,并在函数代码前插入call myfunc来实现调用myfunc的程序
  11. //  Last Modified: 2003.05.07, by Paladin
  12. //
  13. #include <windows.h>
  14. #include <time.h>
  15. #include <stdio.h>
  16. #include "ApiInfo.h"
  17. #include "HookApi.h"
  18. #include "util.h"
  19. #ifdef WINNT
  20. #include "injlib.h"
  21. #endif
  22. #ifdef WIN95
  23. #include "ring0.h"
  24. #endif
  25. #pragma check_stack(off)
  26. #ifdef WIN95
  27. #pragma code_seg("_INIT")
  28. #pragma comment(linker,"/SECTION:.bss,RWS /SECTION:.data,RWS /SECTION:.rdata,RWS /SECTION:.text,RWS /SECTION:_INIT,RWS ")
  29. #pragma comment(linker,"/BASE:0xBFF70000")
  30. #endif
  31. #define CALL_BYTES_SIZE 5 // CALL 0xnnnnnnnn size=5
  32. CAPIInfo g_api_info;
  33. char g_szDllPath[128];
  34. static int g_demo_count =0;
  35. #ifdef WINNT
  36. extern BOOL ObtainSeDebugPrivilege();
  37. #endif
  38. ////////////////////////
  39. CHookAPI::CHookAPI()
  40. {
  41. g_szDllPath[0] =0;
  42. //WriteLog("debug: hooked");
  43. m_hMyDll =NULL;
  44. HMODULE hMod =GetModuleHandle(HOOKAPI_DLL_NAME);
  45. if(hMod)
  46. {
  47. char fname[128];
  48. GetModuleFileName(hMod, fname, sizeof(fname));
  49. GetFilePath(fname, g_szDllPath);
  50. WriteProfileString("HookAPI", "DLL_PATH", g_szDllPath);
  51. }
  52. else GetProfileString("HookAPI", "DLL_PATH", "", g_szDllPath, sizeof(g_szDllPath));
  53. LoadMyDll();
  54. char mod_name[256], mod_name2[100];
  55. GetModuleFileName(NULL, mod_name, sizeof(mod_name));
  56. GetProfileString("HookAPI", "exe_name", "", mod_name2, sizeof(mod_name2));
  57. strupr(mod_name);
  58. strupr(mod_name2);
  59. #ifdef WINNT
  60. if(mod_name2[0] ==0 || strstr(mod_name, mod_name2) ==NULL)
  61. #endif
  62. {
  63. Init();
  64. HookAllAPI();
  65. }
  66. }
  67. CHookAPI::~CHookAPI()
  68. {
  69. UnhookAllAPI();
  70. FreeMyDll();
  71. }
  72. int CHookAPI::LoadMyDll()
  73. {
  74. if(GetModuleHandle(MY_DLL_NAME)) return 0;
  75. char fdll[128];
  76. wsprintf(fdll, "%s\%s", g_szDllPath, MY_DLL_NAME);
  77. if((m_hMyDll =LoadLibrary(fdll)) ==NULL)
  78. {
  79. WriteLog("LoadMyDll %s failed!", fdll);
  80. return -1;
  81. }
  82. return 0;
  83. }
  84. void CHookAPI::FreeMyDll()
  85. {
  86. if(m_hMyDll) FreeLibrary(m_hMyDll);
  87. m_hMyDll =NULL;
  88. }
  89. // Init hooked api info
  90. int CHookAPI::Init()
  91. {
  92. char cur_mod[200];
  93. MYAPIINFO *pMyAPIInfo;
  94. tagGetMyAPIInfo GetMyAPIInfo;
  95. APIFUNC old_api, my_api;
  96. HMODULE hmod;
  97. HINSTANCE hMyDll;
  98. // 得到要截获的api信息
  99. if(m_hMyDll ==NULL)
  100. {
  101. hMyDll =GetModuleHandle(MY_DLL_NAME);
  102. if(hMyDll ==NULL)
  103. {
  104. WriteLog("Init()::m_hMyDll ==NULL");
  105. return false;
  106. }
  107. }
  108. else
  109. hMyDll =m_hMyDll;
  110. if((GetMyAPIInfo=(tagGetMyAPIInfo)GetProcAddress(hMyDll, "GetMyAPIInfo")) ==NULL)
  111. {
  112. WriteLog("GetProcAddress GetMyAPIInfo of %s failed!", MY_DLL_NAME);
  113. return false;
  114. }
  115. pMyAPIInfo =GetMyAPIInfo();
  116. if(pMyAPIInfo ==NULL)
  117. {
  118. WriteLog("Init()::GetMyAPIInfo failed!");
  119. return false;
  120. }
  121. int count =0;
  122. //int f_hook_process =false;
  123. // 分析并保存函数和参数
  124. GetModuleFileName(NULL, cur_mod, sizeof(cur_mod));
  125. APIINFO *pinfo;
  126. //WriteLog("debug: get api info...");
  127. while (pMyAPIInfo[count].module_name !=NULL)
  128. {
  129. if((hmod =GetModuleHandle(pMyAPIInfo[count].module_name)) ==NULL)
  130. {
  131. WriteLog("Error Get module %s, so not hook this module's api", pMyAPIInfo[count].module_name);
  132. count++;
  133. continue;
  134. }
  135. if((old_api =(APIFUNC)GetProcAddress(hmod, pMyAPIInfo[count].api_name)) ==NULL)
  136. {
  137. WriteLog("Error Get ProcAddress %s of module %s, so not hook this module's api", pMyAPIInfo[count].api_name, pMyAPIInfo[count].module_name);
  138. count++;
  139. continue;
  140. }
  141. //WriteLog("debug: GetProcAddress %s %s =%x", pMyAPIInfo[count].module_name, pMyAPIInfo[count].api_name, old_api);
  142. if((my_api =(APIFUNC)GetProcAddress(hMyDll, pMyAPIInfo[count].my_api_name)) ==NULL)
  143. {
  144. WriteLog("failed to GetrProcAddress:%s", pMyAPIInfo[count].my_api_name);
  145. return false;
  146. }
  147. //WriteLog("debug: add api info:%s", pMyAPIInfo[count].api_name);
  148. if((pinfo =g_api_info.Add(pMyAPIInfo[count].module_name, pMyAPIInfo[count].api_name,
  149. pMyAPIInfo[count].my_api_name, pMyAPIInfo[count].param_count,
  150. old_api, my_api, pMyAPIInfo[count].friend_my_api_name,
  151. pMyAPIInfo[count].start_pos)) ==NULL)
  152. break;
  153. count++;
  154. }
  155. #ifdef WINNT
  156. if((hmod =GetModuleHandle("Kernel32.dll")) ==NULL)
  157. {
  158. WriteLog("Error Get module Kernel32.dll, can not hook CreateprocessA");
  159. return -1;
  160. }
  161. if((old_api =(APIFUNC)GetProcAddress(hmod, "CreateProcessA")) ==NULL)
  162. {
  163. WriteLog("Error Get ProcAddress CreateProcessA of module Kernel32.dll");
  164. return -1;
  165. }
  166. if((pinfo =g_api_info.Add("Kernel32.dll", "CreateProcessA", "myCreateprocessA2003", 10, old_api,
  167. (APIFUNC)myCreateProcessA2003)) ==NULL)
  168. {
  169. WriteLog("Error add APIINFO of CreateProcessA");
  170. return -1;
  171. }
  172. if((old_api =(APIFUNC)GetProcAddress(hmod, "CreateProcessW")) ==NULL)
  173. {
  174. WriteLog("Error Get ProcAddress CreateProcessW of module Kernel32.dll");
  175. return -1;
  176. }
  177. if((pinfo =g_api_info.Add("Kernel32.dll", "CreateProcessW", "myCreateprocessW2003", 10, old_api,
  178. (APIFUNC)myCreateProcessW2003)) ==NULL)
  179. {
  180. WriteLog("Error add APIINFO of CreateProcessW");
  181. return -1;
  182. }
  183. #endif
  184. //WriteLog("debug: Init ok!");
  185. return 0;
  186. }
  187. // hook one api
  188. int CHookAPI::HookOneAPI(APIINFO *pinfo)
  189. {
  190. //WriteLog("debug: Hook one api:%s, start_pos:%d", pinfo->api_name, pinfo->start_pos);
  191. if(pinfo->f_hooked)
  192. return 0;
  193. BYTE *papi =(BYTE *)pinfo->old_api + pinfo->start_pos;  // insert call xxxxxxxx from start_pos. lgd 2003.03.01
  194. //将函数所指内容改为可写
  195. if(!RemoveProtection(pinfo))
  196. {
  197. WriteLog("RemoveProtection failed! %s", pinfo->api_name);
  198. return -1;
  199. }
  200. // 保存源函数前5个字节,因为后面将覆盖此处
  201. memcpy(pinfo->save_bytes, papi, 5/*sizeof(pinfo->save_bytes)*/);
  202. //在源函数前插入call ProcessCall命令
  203. papi[0] =0xE8;
  204. *(DWORD *)&papi[1] =(DWORD)ProcessCall -(DWORD)papi -CALL_BYTES_SIZE;
  205. pinfo->f_hooked =true;
  206. WriteLog("debug: Hook one api ok:hmod=%x, %s-%x(%x,%x,%x,%x), start_pos:%d", 
  207. GetModuleHandle(pinfo->module_name), pinfo->api_name,
  208. papi, papi[0], papi[1], pinfo->save_bytes[0], pinfo->save_bytes[1], pinfo->start_pos);
  209. return 0;
  210. }
  211. int CHookAPI::UnhookOneAPI(APIINFO *pinfo)
  212. {
  213. if(!pinfo->f_hooked) return 0;
  214. // ligang, 2003.04.19
  215. // check if already unhooked in the first hook for same old api like that CreateProcessW are hooked in HookAPINT.dll and mydll.dll
  216. // or: unhook only once for api that hooked more than once.
  217. APIINFO *pinfo2 =g_api_info.m_pInfo;
  218. int f_already_unhooked =0;
  219. while(pinfo2)
  220. {
  221. if(pinfo2 ==pinfo)
  222. break;
  223. if(pinfo2->old_api ==pinfo->old_api)  // already unhooked
  224. {
  225. f_already_unhooked =true;
  226. break;
  227. }
  228. pinfo2 =pinfo2->pnext;
  229. }
  230. if(f_already_unhooked)  // only unhook first hook, because the next hook's save_bytes is not origion bytes of old api
  231. {
  232. pinfo->f_hooked =false;
  233. return 0;
  234. }
  235. BYTE *papi =(BYTE *)pinfo->old_api +pinfo->start_pos;
  236. //char *p =(char *)papi;
  237. //WriteLog("debug: unHook one api:%s(%x, %x,%x), start_pos:%d", pinfo->api_name, papi, papi[0], papi[1], pinfo->start_pos);
  238. if(RemoveProtection(pinfo))
  239. memcpy((PBYTE)papi, pinfo->save_bytes, CALL_BYTES_SIZE);  // 恢复原5个字节
  240. else WriteLog("UnhookAPIFunction %s RemoveProtection failed!", pinfo->save_bytes);
  241. #ifdef WIN95
  242. SetPageProtection(papi);
  243. #else
  244. DWORD dwScratch;
  245. VirtualProtect(papi, 20, pinfo->old_protection_flags, &dwScratch);
  246. #endif
  247. pinfo->f_hooked =false;
  248. return 0;
  249. }
  250. int CHookAPI::HookAllAPI()
  251. {
  252. APIINFO *pinfo =g_api_info.m_pInfo;
  253. while (pinfo !=NULL)
  254. {
  255. HookOneAPI(pinfo);
  256. pinfo =pinfo->pnext;
  257. }
  258. return 0;
  259. }
  260. void CHookAPI::UnhookAllAPI()
  261. {
  262. APIINFO *pinfo =g_api_info.m_pInfo;
  263. //ObtainSeDebugPrivilege();
  264. while (pinfo !=NULL)
  265. {
  266. UnhookOneAPI(pinfo);
  267. pinfo =pinfo->pnext;
  268. }
  269. }
  270. // 主要函数ProcessCall,所有api函数的替换函数
  271. void CHookAPI::ProcessCall()
  272. {
  273. PBYTE pbAfterCall;
  274. PDWORD pdwParam;
  275. PDWORD pdwESP;
  276. DWORD dwParamSize;
  277. void *pvReturnAddr;
  278. DWORD dwReturnValue;
  279. BYTE cl_val;
  280. BYTE *papi;
  281. DWORD errcode =0;
  282. #ifdef WINNT
  283. PROCESS_INFORMATION *pi;
  284. char fname[128];
  285. #endif
  286. _asm
  287. {
  288. Mov [cl_val], CL   // 备份CL for xxTextOutx in WIN9X
  289. Mov EAX, [EBP + 4] //前面是被替换的call xxxxxxxx命令
  290. Mov [pbAfterCall], EAX
  291. Mov EAX, [EBP + 8]
  292. Mov [pvReturnAddr], EAX // 保存上次调用位置
  293. Lea EAX, [EBP + 12]
  294. Mov [pdwParam], EAX    //取参数
  295. }
  296. APIINFO *pinfo;
  297. #ifdef DEMO_VERSION
  298. if(++g_demo_count > 200)
  299. MsgBox("This is demo version, max hook count: 20 exceed...");
  300. #endif
  301. if((pinfo =g_api_info.FindByOldAPI((APIFUNC)(pbAfterCall-CALL_BYTES_SIZE))) ==NULL)
  302. {
  303. WriteLog("ProcessCall: can not found api");
  304. goto call_ret;
  305. }
  306. g_api_info.lock(pinfo);
  307. papi =(BYTE *)pinfo->old_api+pinfo->start_pos;
  308. dwParamSize =pinfo->param_count * 4;  // 32位地址使用4个字节
  309. errcode =0;
  310. if(!RemoveProtection(pinfo))   // add 2004.03.30 for some time other program changed api's write permission
  311. {
  312. WriteLog("RemoveProtection failed! %s", pinfo->api_name);
  313. goto call_ret;
  314. }
  315. memcpy(papi, pinfo->save_bytes, CALL_BYTES_SIZE);   //还原原api函数前5字节(恢复api原函数调用)
  316. if(pinfo->my_friend_api_name[0]) // 如果此api和其他api函数共用部分代码如98中的TextOutA和TextOutW,则先恢复用到的函数的被修改的内容
  317. {
  318. WriteLog("Restore my_friend_api_name:%s", pinfo->my_friend_api_name);
  319. RestoreAPICodes(pinfo->my_friend_api_name);
  320. }
  321. // 压参数入堆栈
  322. _asm
  323. {
  324. Sub ESP, [dwParamSize]
  325. Mov [pdwESP], ESP
  326. }
  327. memcpy(pdwESP, pdwParam, dwParamSize);
  328. _asm
  329. {
  330. Mov CL, [cl_val]
  331. }
  332. // 调用mydll里的替换函数
  333. pinfo->my_api();
  334. _asm
  335. {
  336. Push EAX
  337. Mov [dwReturnValue], EAX  //构造返回值
  338. }
  339. errcode =GetLastError();
  340. //#endif
  341. //MsgBox(pAPIInfo->szAPIName);
  342. #ifdef WINNT
  343. if(!strcmp(pinfo->api_name, "CreateProcessW") || !strcmp(pinfo->api_name, "CreateProcessA") )
  344. {
  345. pi =(PROCESS_INFORMATION *)pdwParam[9];
  346. if(pi->hProcess)
  347. {
  348. //if(g_process_to_hook.Find(process_name))
  349. wsprintf(fname, "%s\HookAPINT.dll", g_szDllPath);
  350. //WaitForSingleObject(pi->hProcess, 0);
  351. //SuspendThread(pi->hThread);
  352. #ifdef WINNT
  353. ObtainSeDebugPrivilege();
  354. #endif
  355. InjectLib(pi->hProcess, fname);  // hook 新进程
  356. //ResumeThread(pi->hThread);
  357. }
  358. else WriteLog("hProcess ==NULL");
  359. }
  360. #endif
  361. if(pinfo->my_friend_api_name[0]) // 再恢复上面修改的内容
  362. {
  363. WriteLog("Restore my_friend_api_name...");
  364. RestoreAPICodes(pinfo->my_friend_api_name);
  365. }
  366. // 恢复 Call xxxx
  367. papi[0] =0xE8;
  368. *(DWORD *)&papi[1] =(DWORD)ProcessCall - (DWORD)papi - CALL_BYTES_SIZE;
  369. g_api_info.unlock(pinfo);
  370. call_ret:
  371. // 恢复错误码
  372. SetLastError(errcode);
  373. // 构造虚函数返回
  374. _asm
  375. {
  376. Pop EAX
  377. Mov ECX, [dwParamSize]
  378. Mov EDX, [pvReturnAddr]
  379. Pop EDI
  380. Pop ESI
  381. Pop EBX
  382. Mov ESP, EBP
  383. Pop EBP
  384. Add ESP, 8
  385. Add ESP, ECX  //堆栈指针加参数大小,因为ProcessCall没有参数,所以要如此
  386. Push EDX
  387. Ret
  388. }
  389. }
  390. int CHookAPI::RestoreAPICodes(char *my_api_name)
  391. {
  392. APIINFO *pinfo =g_api_info.FindByMyAPIName(my_api_name);
  393. if(pinfo ==NULL || pinfo->f_hooked ==false) return 0;
  394. g_api_info.lock(pinfo);
  395. memcpy((PBYTE)pinfo->old_api+pinfo->start_pos, pinfo->save_bytes, CALL_BYTES_SIZE/*(5>bytes)?bytes:5*/);
  396. g_api_info.unlock(pinfo);
  397. return 0;
  398. }
  399. int CHookAPI::ChangeAPICodes(char *my_api_name)
  400. {
  401. APIINFO *pinfo =g_api_info.FindByMyAPIName(my_api_name);
  402. if(pinfo==NULL) return 0;
  403. BYTE *papi =(BYTE *)pinfo->old_api+pinfo->start_pos;
  404. papi[0] =0xE8;
  405. *(DWORD *)&papi[1] =(DWORD)ProcessCall -(DWORD)papi -CALL_BYTES_SIZE;
  406. return 0;
  407. }
  408. // 使某块有写保护的内存地址(代码段内地址)为可写
  409. BOOL CHookAPI::RemoveProtection(APIINFO *pinfo)
  410. {
  411. BYTE *papi =(BYTE *)pinfo->old_api+pinfo->start_pos;
  412. BOOL ret;
  413. #ifdef WIN95
  414. ret =RemovePageProtection(papi);
  415. #endif
  416. #ifdef WINNT
  417. MEMORY_BASIC_INFORMATION mbi;
  418. DWORD dwProtectionFlags;
  419. DWORD dwScratch;
  420. VirtualQuery(papi, &mbi, sizeof(mbi));
  421. dwProtectionFlags =mbi.Protect;
  422. pinfo->old_protection_flags =dwProtectionFlags;
  423. dwProtectionFlags =PAGE_READWRITE;
  424. ret =VirtualProtect(papi, 20, dwProtectionFlags, &dwScratch);
  425. #endif
  426. if(ret ==FALSE)
  427. {
  428. char err[256];
  429. GetErrString(err, sizeof(err), GetLastError());
  430. WriteLog("Error VirtualProtect:%s", err);
  431. //WriteLog("VirtualProtect:%x,%x,%x", pvAddress, dwProtectionFlags, dwScratch);
  432. return false;
  433. }
  434. return ret;
  435. }
  436. #ifdef WINNT
  437. // to hook new process
  438. DWORD WINAPI CHookAPI::myCreateProcessW2003(
  439. LPCWSTR lpApplicationName,
  440. LPWSTR lpCommandLine, 
  441. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  442. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  443. BOOL bInheritHandles,
  444. DWORD dwCreationFlags,
  445. LPVOID lpEnvironment,
  446. LPCWSTR lpCurrentDirectory,
  447. LPSTARTUPINFOW lpStartupInfo,
  448. LPPROCESS_INFORMATION lpProcessInformation
  449. )
  450. {
  451. //WriteLog("HookAPI:CreateProcessW");
  452. DWORD aaa= CreateProcessW(lpApplicationName,
  453. lpCommandLine, lpProcessAttributes,
  454. lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
  455. lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
  456. char fname[400];
  457. int len =WideCharToMultiByte( CP_ACP, 0, lpCommandLine, -1, fname, sizeof(fname),NULL,NULL);
  458. fname[len] =0;
  459. WriteLog("HookAPI:CreateProcessW:%s", fname);
  460. return aaa;
  461. }
  462. DWORD WINAPI CHookAPI::myCreateProcessA2003(
  463. LPCSTR lpApplicationName,
  464. LPSTR lpCommandLine, 
  465. LPSECURITY_ATTRIBUTES lpProcessAttributes,
  466. LPSECURITY_ATTRIBUTES lpThreadAttributes,
  467. BOOL bInheritHandles,
  468. DWORD dwCreationFlags,
  469. LPVOID lpEnvironment,
  470. LPCSTR lpCurrentDirectory,
  471. LPSTARTUPINFO lpStartupInfo,
  472. LPPROCESS_INFORMATION lpProcessInformation
  473. )
  474. {
  475. DWORD aaa= CreateProcessA(lpApplicationName,
  476. lpCommandLine, lpProcessAttributes,
  477. lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
  478. lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
  479. WriteLog("HookAPI:CreateProcessA:%s", lpCommandLine);
  480. return aaa;
  481. }
  482. #endif