截取程序的网络封包(Delphi Hook API)

2017/08/12 19:01
阅读数 452

有时候我们需要对其它应用程序发送和接收的网络数据进行拦截,比如要对IE发送的**头进行分析,得到请求的地址等.这次我们可以用一些例如WPE, Sniffer之类的工具来达到目的.但是工具功能有限,要想实现更强大的功能,还是我们自己动手来DIY吧. 

拦截网络数据封包的方法有三种,一是将网卡设为混杂模式,这次就可以监视到局域网上所有的数据包,二是HOOK目标进程的发送和接收的API函数,第三种方法是自己实现一个代理的DLL.在这里我们使用HOOK API的方法,这样易于实现,而且也不会得到大量的无用数据(如第一种方法就会监视到所有的网络数据). 

下面是一个尽量简化了的API HOOK的模版,原理是利用消息钩子将DLL中的代码注入到目标进程中,再用GetProcAddress得到API函数入口地址,将函数入口址改为自己定义的函数入口,这样就得到了API函数的相应参数,处理完后,再改回真实API函数入口地址,并调用它. 
HOOK.DLL的代码:

Delphi代码 

 收藏代码

  1. library Hook;   
  2.   
  3. uses   
  4. SysUtils,   
  5. windows,   
  6. Messages,   
  7. APIHook in 'APIHook.pas';   
  8.   
  9. type   
  10. PData = ^TData;   
  11. TData = record   
  12. Hook: THandle;   
  13. Hooked: Boolean;   
  14. end;   
  15.   
  16. var   
  17. DLLData: PData;   
  18.   
  19. {------------------------------------}   
  20. {过程名:HookProc   
  21. {过程功能:HOOK过程   
  22. {过程参数:nCode, wParam, lParam消息的相   
  23. { 关参数   
  24. {------------------------------------}   
  25. procedure HookProc(nCode, wParam, lParam: LongWORD);stdcall;   
  26. begin   
  27. if not DLLData^.Hooked then   
  28. begin   
  29. HookAPI;   
  30. DLLData^.Hooked := True;   
  31. end;   
  32. //调用下一个Hook   
  33. CallNextHookEx(DLLData^.Hook, nCode, wParam, lParam);   
  34. end;   
  35.   
  36.   
  37. {------------------------------------}   
  38. {函数名:InstallHook   
  39. {函数功能:在指定窗口上安装HOOK   
  40. {函数参数:sWindow:要安装HOOK的窗口   
  41. {返回值:成功返回TRUE,失败返回FALSE   
  42. {------------------------------------}   
  43. function InstallHook(SWindow: LongWORD):Boolean;stdcall;   
  44. var   
  45. ThreadID: LongWORD;   
  46. begin   
  47. Result := False;   
  48. DLLData^.Hook := 0;   
  49. ThreadID := GetWindowThreadProcessId(sWindow, nil);   
  50. //给指定窗口挂上钩子   
  51. DLLData^.Hook := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, Hinstance, ThreadID);   
  52. if DLLData^.Hook > 0 then   
  53. Result := True //是否成功HOOK   
  54. else   
  55. exit;   
  56. end;   
  57.   
  58. {------------------------------------}   
  59. {过程名:UnHook   
  60. {过程功能:卸载HOOK   
  61. {过程参数:无   
  62. {------------------------------------}   
  63. procedure UnHook;stdcall;   
  64. begin   
  65. UnHookAPI;   
  66. //卸载Hook   
  67. UnhookWindowsHookEx(DLLData^.Hook);   
  68. end;   
  69.   
  70. {------------------------------------}   
  71. {过程名:DLL入口函数   
  72. {过程功能:进行DLL初始化,释放等   
  73. {过程参数:DLL状态   
  74. {------------------------------------}   
  75. procedure MyDLLHandler(Reason: Integer);   
  76. var   
  77. FHandle: LongWORD;   
  78. begin   
  79. case Reason of   
  80. DLL_PROCESS_ATTACH:   
  81. begin //建立文件映射,以实现DLL中的全局变量   
  82. FHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, $ffff, 'MYDLLDATA');   
  83. if FHandle = 0 then   
  84. if GetLastError = ERROR_ALREADY_EXISTS then   
  85. begin   
  86. FHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MYDLLDATA');   
  87. if FHandle = 0 then Exit;   
  88. end else Exit;   
  89. DLLData := MapViewOfFile(FHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);   
  90. if DLLData = nil then   
  91. CloseHandle(FHandle);   
  92. end;   
  93. DLL_PROCESS_DETACH:   
  94. begin   
  95. if Assigned(DLLData) then   
  96. begin   
  97. UnmapViewOfFile(DLLData);   
  98. DLLData := nil;   
  99. end;   
  100. end;   
  101. end;   
  102. end;   
  103.   
  104. {$R *.res}   
  105. exports   
  106. InstallHook, UnHook, HookProc;   
  107.   
  108. begin   
  109. DLLProc := @MyDLLHandler;   
  110. MyDLLhandler(DLL_PROCESS_ATTACH);   
  111. DLLData^.Hooked := False;   
  112. end.   
  113.   
  114. ----------------------------------------------------------------------------------------   
  115. APIHook.Pas的代码:   
  116.   
  117. unit APIHook;   
  118.   
  119. interface   
  120.   
  121. uses   
  122. SysUtils,   
  123. Windows, WinSock;   
  124.   
  125. type   
  126. //要HOOK的API函数定义   
  127. TSockProc = function (s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;   
  128.   
  129. PJmpCode = ^TJmpCode;   
  130. TJmpCode = packed record   
  131. JmpCode: BYTE;   
  132. Address: TSockProc;   
  133. MovEAX: Array [0..2] of BYTE;   
  134. end;   
  135.   
  136. //--------------------函数声明---------------------------   
  137. procedure HookAPI;   
  138. procedure UnHookAPI;   
  139.   
  140. var   
  141. OldSend, OldRecv: TSockProc; //原来的API地址   
  142. JmpCode: TJmpCode;   
  143. OldProc: array [0..1] of TJmpCode;   
  144. AddSend, AddRecv: pointer; //API地址   
  145. TmpJmp: TJmpCode;   
  146. ProcessHandle: THandle;   
  147. implementation   
  148.   
  149. {---------------------------------------}   
  150. {函数功能:Send函数的HOOK   
  151. {函数参数:同Send   
  152. {函数返回值:integer   
  153. {---------------------------------------}   
  154. function MySend(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;   
  155. var   
  156. dwSize: cardinal;   
  157. begin   
  158. //这儿进行发送的数据处理   
  159. MessageBeep(1000); //简单的响一声   
  160. //调用直正的Send函数   
  161. WriteProcessMemory(ProcessHandle, AddSend, @OldProc[0], 8, dwSize);   
  162. Result := OldSend(S, Buf, len, flags);   
  163. JmpCode.Address := @MySend;   
  164. WriteProcessMemory(ProcessHandle, AddSend, @JmpCode, 8, dwSize);   
  165. end;   
  166.   
  167. {---------------------------------------}   
  168. {函数功能:Recv函数的HOOK   
  169. {函数参数:同Recv   
  170. {函数返回值:integer   
  171. {---------------------------------------}   
  172. function MyRecv(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall;   
  173. var   
  174. dwSize: cardinal;   
  175. begin   
  176. //这儿进行接收的数据处理   
  177. MessageBeep(1000); //简单的响一声   
  178. //调用直正的Recv函数   
  179. WriteProcessMemory(ProcessHandle, AddRecv, @OldProc[1], 8, dwSize);   
  180. Result := OldRecv(S, Buf, len, flags);   
  181. JmpCode.Address := @MyRecv;   
  182. WriteProcessMemory(ProcessHandle, AddRecv, @JmpCode, 8, dwSize);   
  183. end;   
  184.   
  185. {------------------------------------}   
  186. {过程功能:HookAPI   
  187. {过程参数:无   
  188. {------------------------------------}   
  189. procedure HookAPI;   
  190. var   
  191. DLLModule: THandle;   
  192. dwSize: cardinal;   
  193. begin   
  194. ProcessHandle := GetCurrentProcess;   
  195. DLLModule := LoadLibrary('ws2_32.dll');   
  196. AddSend := GetProcAddress(DLLModule, 'send'); //取得API地址   
  197. AddRecv := GetProcAddress(DLLModule, 'recv');   
  198. JmpCode.JmpCode := $B8;   
  199. JmpCode.MovEAX[0] := $FF;   
  200. JmpCode.MovEAX[1] := $E0;   
  201. JmpCode.MovEAX[2] := 0;   
  202. ReadProcessMemory(ProcessHandle, AddSend, @OldProc[0], 8, dwSize);   
  203. JmpCode.Address := @MySend;   
  204. WriteProcessMemory(ProcessHandle, AddSend, @JmpCode, 8, dwSize); //修改Send入口   
  205. ReadProcessMemory(ProcessHandle, AddRecv, @OldProc[1], 8, dwSize);   
  206. JmpCode.Address := @MyRecv;   
  207. WriteProcessMemory(ProcessHandle, AddRecv, @JmpCode, 8, dwSize); //修改Recv入口   
  208. OldSend := AddSend;   
  209. OldRecv := AddRecv;   
  210. end;   
  211.   
  212. {------------------------------------}   
  213. {过程功能:取消HOOKAPI   
  214. {过程参数:无   
  215. {------------------------------------}   
  216. procedure UnHookAPI;   
  217. var   
  218. dwSize: Cardinal;   
  219. begin   
  220. WriteProcessMemory(ProcessHandle, AddSend, @OldProc[0], 8, dwSize);   
  221. WriteProcessMemory(ProcessHandle, AddRecv, @OldProc[1], 8, dwSize);   
  222. end;   
  223.   
  224. end.   

 

--------------------------------------------------------------------------------------------- 
编译这个DLL后,再新建一个程序调用这个DLL的InstallHook并传入目标进程的主窗口句柄就可:

Delphi代码 

 收藏代码

  1. unit fmMain;   
  2.   
  3. interface   
  4.   
  5. uses   
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,   
  7. Dialogs, StdCtrls;   
  8.   
  9. type   
  10. TForm1 = class(TForm)   
  11. Button1: TButton;   
  12. Button2: TButton;   
  13. Edit1: TEdit;   
  14. procedure Button1Click(Sender: TObject);   
  15. procedure Button2Click(Sender: TObject);   
  16. private   
  17. { Private declarations }   
  18. public   
  19. { Public declarations }   
  20. end;   
  21.   
  22. var   
  23. Form1: TForm1;   
  24. InstallHook: function (SWindow: THandle):Boolean;stdcall;   
  25. UnHook: procedure;stdcall;   
  26. implementation   
  27.   
  28. {$R *.dfm}   
  29.   
  30. procedure TForm1.Button1Click(Sender: TObject);   
  31. var   
  32. ModuleHandle: THandle;   
  33. TmpWndHandle: THandle;   
  34. begin   
  35. TmpWndHandle := 0;   
  36. TmpWndHandle := FindWindow(nil, '目标窗口的标题');   
  37. if not isWindow(TmpWndHandle) then   
  38. begin   
  39. MessageBox(self.Handle, '没有找到窗口', '!!!', MB_OK);   
  40. exit;   
  41. end;   
  42. ModuleHandle := LoadLibrary('Hook.dll');   
  43. @InstallHook := GetProcAddress(ModuleHandle, 'InstallHook');   
  44. @UnHook := GetProcAddress(ModuleHandle, 'UnHook');   
  45. if InstallHook(FindWindow(nil, 'Untitled')) then   
  46. ShowMessage('Hook OK');   
  47. end;   
  48.   
  49. procedure TForm1.Button2Click(Sender: TObject);   
  50. begin   
  51. UnHook   
  52. end;   
  53.   
  54. end.  
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部