返回列表 发帖

[原创]通用拦截api源代码

[原创]:通用拦截api源代码 [来源]:黑色海岸线安全技术论坛 http://www.thysea.com/lb/cgi-bin/leobbs.cgi [作者]:默数悲伤 [时间]:2006.5.27 经常在看到网上好多人好多帖子寻找拦截某某api的源代码,但是要想做到真正的通用拦截api的代码几乎是不可能的.因为不同的api其最关键的参数不同,地址也不相同,而且编译选项不同,拦截代码也会有一些不同.所以,这里所谓的通用只是尽量把与要拦截的api的个别因素不考虑,而只把公共部分做了出来,当然大家可以参考程序注释轻松写出自己的拦截某个api的程序出来. 该通用代码做成一个头文件的形式,使用的时候把他添加到工程即可.在需要修改的地方,代码中都会有提示.如有错误,欢迎给我留言:) 可以编译成debug或者release程序,只是需要在程序做些简单的修改.这里模拟的是拦截的connect函数,效果是每当被拦截的进程使用connect函数的时候,立即弹出一个对话框提示已经被Hook. 可能需要被修改的地方: 1:函数参数大小 2:被拦截的api的函数指针的定义 3:拦截函数中的自定义功能的函数和变量的定义 4:在拦截函数的参数中由于3的原因而需要做的响应的修改
  1. &#35;include <windows.h>
  2. &#35;include <tchar.h>
  3. &#35;define HOOKFUCTIONSIZE 4096 //定义拦截函数体的大小,以字节为单位,且以4kb为基本单位
  4. &#35;define HOOKEDAPIPARAMNUMINBYTE 12 //定义被拦截的api的函数的参数的大小,以字节为单位
  5. //定义拦截函数的参数
  6. typedef struct _RemoteParam {
  7. LPVOID FunAddr;
  8. LPVOID lpGetCurrentProcess;
  9. LPVOID lpWriteProcessMemory;
  10. unsigned char szOldCode[10];
  11. unsigned char szNewCode[10];
  12. char szCaption[8];
  13. char szMessage[12];
  14. LPVOID lpMessageBox;
  15. } RemoteParam, * PRemoteParam;
  16. typedef BOOL (__stdcall * PFN_WRITEPROCESSMEMORY)(HANDLE,LPVOID,LPCVOID,SIZE_T,SIZE_T*);
  17. typedef HANDLE (__stdcall * PFN_GETCURRENTPROCESS)(void);
  18. //这里为演示而添加的一个函数指针的声明,可以根据拦截功能的需要添加自己要使用的函数指针的定义
  19. typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, DWORD);
  20. //这里为要拦截的api的函数指针的定义
  21. typedef int (__stdcall * PFN_CONNECT)(SOCKET,struct sockaddr *,int);
  22. //实施拦截的函数体,这里以拦截connect为目标,参数个数为3,其总大小为12字节
  23. VOID HooKApi(LPVOID lParam)
  24. {
  25. RemoteParam* Rpm = (RemoteParam*)lParam;
  26. PFN_GETCURRENTPROCESS pfnGetCurrentProcess = (PFN_GETCURRENTPROCESS)Rpm->lpGetCurrentProcess;
  27. PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory = (PFN_WRITEPROCESSMEMORY)Rpm->lpWriteProcessMemory;
  28. int RetValue = 0; //定义要拦截的api的默认返回植
  29. DWORD NextIpAddr = 0;
  30. DWORD dwParamaAddr = 0;
  31. //保存原api的参数
  32. SOCKET s;
  33. struct sockaddr * name;
  34. int namelen;
  35. __asm
  36. {
  37. MOV EAX,[EBP+12]
  38. MOV [NextIpAddr], EAX
  39. MOV EAX,[EBP+16]
  40. MOV [s], EAX
  41. MOV EAX,[EBP+20]
  42. MOV [name],EAX
  43. MOV EAX,[EBP+24]
  44. MOV [namelen],EAX
  45. }
  46. //这里可以做你的事情了,比如我只想弹出一个对话框,其实也可以在让api完成之后再做些东西
  47. PFN_MESSAGEBOX pfnMessageBox = (PFN_MESSAGEBOX)Rpm->lpMessageBox;
  48. pfnMessageBox(NULL, Rpm->szMessage, Rpm->szCaption, 0);
  49. //现在你要做的已经完成了,让api恢复吧,完成他本来的任务
  50. PFN_CONNECT pfnConnect = (PFN_CONNECT)Rpm->FunAddr;
  51. pfnWriteProcessMemory(pfnGetCurrentProcess(),
  52. Rpm->FunAddr,
  53. (LPCVOID)Rpm->szOldCode,
  54. 10,
  55. NULL);
  56. //让api真正执行,这里换成你要拦截的api
  57. RetValue = pfnConnect(s, name, namelen);
  58. //再次恢复对他的拦截
  59. pfnWriteProcessMemory(pfnGetCurrentProcess(),
  60. Rpm->FunAddr,
  61. (LPCVOID)Rpm->szNewCode,
  62. 10,
  63. NULL);
  64. DWORD dwStackSize = 12 + HOOKEDAPIPARAMNUMINBYTE;
  65. //这里对拦截函数堆栈的恢复,必须放在最后
  66. __asm
  67. {
  68. //POP EDI //注意如果你编译生成的debug版本的程序则需要把这
  69. //POP ESI //三个注释去掉
  70. //POP EBX
  71. MOV ECX, [dwStackSize]
  72. MOV EDX, [NextIpAddr]
  73. MOV EAX, [RetValue]
  74. MOV ESP, EBP
  75. POP EBP
  76. ADD ESP, ECX //12 + HOOKEDAPIPARAMNUMINBYTE //恢复堆栈
  77. PUSH EDX
  78. RET
  79. }
  80. }
  81. VOID GetErrorToInfo(void)
  82. {
  83. LPVOID lpMsgBuf;
  84. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(),
  85. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  86. (LPTSTR)&lpMsgBuf, 0, NULL );
  87. MessageBox(0, (LPCTSTR)lpMsgBuf, TEXT("HOOK ERROR"), MB_OK|MB_ICONINFORMATION );
  88. LocalFree(lpMsgBuf);
  89. return;
  90. }
  91. //////////////////////////////////////////////////////////////////////////
  92. //************************************************************************
  93. //模块名字:AdjustProcessPrivileges(LPCSTR)
  94. //模块功能:修改调用进程的权限
  95. //返回数值:成功返回TRUE,失败返回FALSE
  96. //参数可以为下列值:
  97. // &#35;define SE_BACKUP_NAME TEXT("SeBackupPrivilege")
  98. // &#35;define SE_RESTORE_NAME TEXT("SeRestorePrivilege")
  99. // &#35;define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege")
  100. // &#35;define SE_DEBUG_NAME TEXT("SeDebugPrivilege")
  101. //////////////////////////////////////////////////////////////////////////
  102. BOOL AdjustProcessPrivileges(LPCSTR lpPrivilegesName)
  103. {
  104. HANDLE hToken;
  105. TOKEN_PRIVILEGES tkp;
  106. if(!OpenProcessToken(GetCurrentProcess(),
  107. TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
  108. {
  109. GetErrorToInfo();
  110. return FALSE;
  111. }
  112. if(!LookupPrivilegeV&#97;lue(NULL,lpPrivilegesName,
  113. &tkp.Privileges[0].Luid))
  114. {
  115. GetErrorToInfo();
  116. CloseHandle(hToken);
  117. return FALSE;
  118. }
  119. tkp.PrivilegeCount = 1;
  120. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  121. if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(tkp),NULL,NULL))
  122. {
  123. GetErrorToInfo();
  124. CloseHandle(hToken);
  125. return FALSE;
  126. }
  127. CloseHandle(hToken);
  128. return TRUE;
  129. }
  130. int SetHook(DWORD dwPid, LPCTSTR lpApiName, LPCTSTR lpExportDllName, LPVOID lpHookFunAddr)
  131. {
  132. //获取要拦截的api的地址
  133. HMODULE hExportDll = LoadLibrary(lpExportDllName);
  134. if(hExportDll == NULL)
  135. {
  136. GetErrorToInfo();
  137. return -1;
  138. }
  139. LPVOID lpApiAddr = GetProcAddress(hExportDll, lpApiName);
  140. if(lpApiAddr == NULL)
  141. {
  142. GetErrorToInfo();
  143. FreeLibrary(hExportDll);
  144. return -1;
  145. }
  146. //打开进程句柄
  147. HANDLE hTargetProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
  148. FALSE, dwPid);
  149. if(hTargetProcess == NULL)
  150. {
  151. GetErrorToInfo();
  152. FreeLibrary(hExportDll);
  153. return -1;
  154. }
  155. //申请拦截函数内存空间
  156. LPVOID lpFunAddr = VirtualAllocEx(hTargetProcess, NULL, HOOKFUCTIONSIZE,
  157. MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  158. if(lpFunAddr == NULL)
  159. {
  160. GetErrorToInfo();
  161. FreeLibrary(hExportDll);
  162. CloseHandle(hTargetProcess);
  163. return -1;
  164. }
  165. //申请远程参数空间
  166. LPVOID lpParamaAddr = VirtualAllocEx(hTargetProcess, NULL, sizeof(RemoteParam),
  167. MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  168. if(lpParamaAddr == NULL)
  169. {
  170. GetErrorToInfo();
  171. FreeLibrary(hExportDll);
  172. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  173. CloseHandle(hTargetProcess);
  174. return -1;
  175. }
  176. //把拦截函数体写入目标进程地址空间
  177. DWORD dwError = 0;
  178. if(!WriteProcessMemory(hTargetProcess, lpFunAddr, lpHookFunAddr, HOOKFUCTIONSIZE, &dwError))
  179. {
  180. MessageBox(NULL, "a", "a", 0);
  181. GetErrorToInfo();
  182. FreeLibrary(hExportDll);
  183. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  184. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  185. CloseHandle(hTargetProcess);
  186. return -1;
  187. }
  188. //设置远程参数,下一步要把参数写入眼要拦截的远程进程地址空间
  189. RemoteParam RParam;
  190. ZeroMemory(&RParam, sizeof(RParam));
  191. unsigned char oldcode[10];
  192. unsigned char newcode[10];
  193. if(!ReadProcessMemory(GetCurrentProcess(),
  194. lpApiAddr,
  195. oldcode,
  196. 10,
  197. &dwError))
  198. {
  199. GetErrorToInfo();
  200. FreeLibrary(hExportDll);
  201. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  202. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  203. CloseHandle(hTargetProcess);
  204. return -1;
  205. }
  206. //生成跳转指令,这将覆盖要拦截的api的前十个字节
  207. int praadd = (int)lpParamaAddr;
  208. int threadadd = (int)lpFunAddr;
  209. newcode[4] = praadd>>24;
  210. newcode[3] = (praadd<<8)>>24;
  211. newcode[2] = (praadd<<16)>>24;
  212. newcode[1] = (praadd<<24)>>24;
  213. newcode[0] = 0x68; //PUSH lpParamaAddr
  214. int offsetaddr = threadadd - (int)lpApiAddr - 10 ;
  215. newcode[9] = offsetaddr>>24;
  216. newcode[8] = (offsetaddr<<8)>>24;
  217. newcode[7] = (offsetaddr<<16)>>24;
  218. newcode[6] = (offsetaddr<<24)>>24;
  219. newcode[5] = 0xE8; //CALL lpFunAddr
  220. strcat((char*)RParam.szOldCode, (char*)oldcode);
  221. strcat((char*)RParam.szNewCode, (char*)newcode);
  222. RParam.FunAddr = lpApiAddr;
  223. HMODULE hKernel32 = LoadLibrary("Kernel32.dll");
  224. if(hKernel32 == NULL)
  225. {
  226. GetErrorToInfo();
  227. FreeLibrary(hExportDll);
  228. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  229. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  230. CloseHandle(hTargetProcess);
  231. return -1;
  232. }
  233. RParam.lpGetCurrentProcess = GetProcAddress(hKernel32, "GetCurrentProcess");
  234. RParam.lpWriteProcessMemory = GetProcAddress(hKernel32, "WriteProcessMemory");
  235. if(RParam.lpGetCurrentProcess == NULL || RParam.lpWriteProcessMemory == NULL)
  236. {
  237. GetErrorToInfo();
  238. FreeLibrary(hExportDll);
  239. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  240. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  241. CloseHandle(hTargetProcess);
  242. FreeLibrary(hKernel32);
  243. return -1;
  244. }
  245. //以上皆为必须,下面可以为自己的拦截函数中所需要用的一些变量以及系统api放到参数中去
  246. //比如我在拦截函数中只是弹出一个对话框,标题为"HOOK",内容为"Now,hook:)",这样定义
  247. HMODULE hUser32 = LoadLibrary("User32.dll");
  248. if(hUser32 == NULL)
  249. {
  250. GetErrorToInfo();
  251. FreeLibrary(hExportDll);
  252. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  253. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  254. CloseHandle(hTargetProcess);
  255. FreeLibrary(hKernel32);
  256. return -1;
  257. }
  258. RParam.lpMessageBox = GetProcAddress(hUser32, "MessageBoxA");
  259. if(RParam.lpMessageBox == NULL)
  260. {
  261. GetErrorToInfo();
  262. FreeLibrary(hExportDll);
  263. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  264. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  265. CloseHandle(hTargetProcess);
  266. FreeLibrary(hKernel32);
  267. FreeLibrary(hUser32);
  268. return -1;
  269. }
  270. strcat((char*)RParam.szCaption, "HOOK\0");
  271. strcat((char*)RParam.szMessage, "Now,hook:)\0");
  272. FreeLibrary(hUser32);
  273. //下面为必须部分
  274. //把参数写入要拦截的远程进程地址空间
  275. if(!WriteProcessMemory(hTargetProcess, lpParamaAddr, (LPVOID)&RParam, sizeof(RParam), &dwError))
  276. {
  277. GetErrorToInfo();
  278. FreeLibrary(hExportDll);
  279. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  280. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  281. CloseHandle(hTargetProcess);
  282. FreeLibrary(hKernel32);
  283. return -1;
  284. }
  285. //把新的跳转指令写入要拦截的目标进程的要拦截的api的函数的前十字节
  286. if(!WriteProcessMemory(hTargetProcess, lpApiAddr , (LPVOID)newcode, 10, &dwError))
  287. {
  288. GetErrorToInfo();
  289. FreeLibrary(hExportDll);
  290. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  291. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  292. CloseHandle(hTargetProcess);
  293. FreeLibrary(hKernel32);
  294. return -1;
  295. }
  296. //完成,收工,清理资源
  297. FreeLibrary(hExportDll);
  298. CloseHandle(hTargetProcess);
  299. FreeLibrary(hKernel32);
  300. return 0;
  301. }
复制代码
调用代码:
  1. &#35;include "CommonHook.h"
  2. int main(void)
  3. {
  4. if(!AdjustProcessPrivileges(SE_DEBUG_NAME))
  5. return -1;
  6. SetHook(832, "connect", "Ws2_32.dll", &HooKApi);
  7. return 0;
  8. }
复制代码

返回列表 回复 发帖