• 截取程序的网络封包(Delphi Hook API) 转自 http://peirenlei.javaeye.com/blog/417993


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

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

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

      

    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, 000);    
    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.   
    library Hook; 
    
    uses 
    SysUtils, 
    windows, 
    Messages, 
    APIHook in 'APIHook.pas'; 
    
    type 
    PData = ^TData; 
    TData = record 
    Hook: THandle; 
    Hooked: Boolean; 
    end; 
    
    var 
    DLLData: PData; 
    
    {------------------------------------} 
    {过程名:HookProc 
    {过程功能:HOOK过程 
    {过程参数:nCode, wParam, lParam消息的相 
    { 关参数 
    {------------------------------------} 
    procedure HookProc(nCode, wParam, lParam: LongWORD);stdcall; 
    begin 
    if not DLLData^.Hooked then 
    begin 
    HookAPI; 
    DLLData^.Hooked := True; 
    end; 
    //调用下一个Hook 
    CallNextHookEx(DLLData^.Hook, nCode, wParam, lParam); 
    end; 
    
    
    {------------------------------------} 
    {函数名:InstallHook 
    {函数功能:在指定窗口上安装HOOK 
    {函数参数:sWindow:要安装HOOK的窗口 
    {返回值:成功返回TRUE,失败返回FALSE 
    {------------------------------------} 
    function InstallHook(SWindow: LongWORD):Boolean;stdcall; 
    var 
    ThreadID: LongWORD; 
    begin 
    Result := False; 
    DLLData^.Hook := 0; 
    ThreadID := GetWindowThreadProcessId(sWindow, nil); 
    //给指定窗口挂上钩子 
    DLLData^.Hook := SetWindowsHookEx(WH_GETMESSAGE, @HookProc, Hinstance, ThreadID); 
    if DLLData^.Hook > 0 then 
    Result := True //是否成功HOOK 
    else 
    exit; 
    end; 
    
    {------------------------------------} 
    {过程名:UnHook 
    {过程功能:卸载HOOK 
    {过程参数:无 
    {------------------------------------} 
    procedure UnHook;stdcall; 
    begin 
    UnHookAPI; 
    //卸载Hook 
    UnhookWindowsHookEx(DLLData^.Hook); 
    end; 
    
    {------------------------------------} 
    {过程名:DLL入口函数 
    {过程功能:进行DLL初始化,释放等 
    {过程参数:DLL状态 
    {------------------------------------} 
    procedure MyDLLHandler(Reason: Integer); 
    var 
    FHandle: LongWORD; 
    begin 
    case Reason of 
    DLL_PROCESS_ATTACH: 
    begin //建立文件映射,以实现DLL中的全局变量 
    FHandle := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, $ffff, 'MYDLLDATA'); 
    if FHandle = 0 then 
    if GetLastError = ERROR_ALREADY_EXISTS then 
    begin 
    FHandle := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, 'MYDLLDATA'); 
    if FHandle = 0 then Exit; 
    end else Exit; 
    DLLData := MapViewOfFile(FHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0); 
    if DLLData = nil then 
    CloseHandle(FHandle); 
    end; 
    DLL_PROCESS_DETACH: 
    begin 
    if Assigned(DLLData) then 
    begin 
    UnmapViewOfFile(DLLData); 
    DLLData := nil; 
    end; 
    end; 
    end; 
    end; 
    
    {$R *.res} 
    exports 
    InstallHook, UnHook, HookProc; 
    
    begin 
    DLLProc := @MyDLLHandler; 
    MyDLLhandler(DLL_PROCESS_ATTACH); 
    DLLData^.Hooked := False; 
    end. 
    
    ---------------------------------------------------------------------------------------- 
    APIHook.Pas的代码: 
    
    unit APIHook; 
    
    interface 
    
    uses 
    SysUtils, 
    Windows, WinSock; 
    
    type 
    //要HOOK的API函数定义 
    TSockProc = function (s: TSocket; var Buf; len, flags: Integer): Integer; stdcall; 
    
    PJmpCode = ^TJmpCode; 
    TJmpCode = packed record 
    JmpCode: BYTE; 
    Address: TSockProc; 
    MovEAX: Array [0..2] of BYTE; 
    end; 
    
    //--------------------函数声明--------------------------- 
    procedure HookAPI; 
    procedure UnHookAPI; 
    
    var 
    OldSend, OldRecv: TSockProc; //原来的API地址 
    JmpCode: TJmpCode; 
    OldProc: array [0..1] of TJmpCode; 
    AddSend, AddRecv: pointer; //API地址 
    TmpJmp: TJmpCode; 
    ProcessHandle: THandle; 
    implementation 
    
    {---------------------------------------} 
    {函数功能:Send函数的HOOK 
    {函数参数:同Send 
    {函数返回值:integer 
    {---------------------------------------} 
    function MySend(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall; 
    var 
    dwSize: cardinal; 
    begin 
    //这儿进行发送的数据处理 
    MessageBeep(1000); //简单的响一声 
    //调用直正的Send函数 
    WriteProcessMemory(ProcessHandle, AddSend, @OldProc[0], 8, dwSize); 
    Result := OldSend(S, Buf, len, flags); 
    JmpCode.Address := @MySend; 
    WriteProcessMemory(ProcessHandle, AddSend, @JmpCode, 8, dwSize); 
    end; 
    
    {---------------------------------------} 
    {函数功能:Recv函数的HOOK 
    {函数参数:同Recv 
    {函数返回值:integer 
    {---------------------------------------} 
    function MyRecv(s: TSocket; var Buf; len, flags: Integer): Integer; stdcall; 
    var 
    dwSize: cardinal; 
    begin 
    //这儿进行接收的数据处理 
    MessageBeep(1000); //简单的响一声 
    //调用直正的Recv函数 
    WriteProcessMemory(ProcessHandle, AddRecv, @OldProc[1], 8, dwSize); 
    Result := OldRecv(S, Buf, len, flags); 
    JmpCode.Address := @MyRecv; 
    WriteProcessMemory(ProcessHandle, AddRecv, @JmpCode, 8, dwSize); 
    end; 
    
    {------------------------------------} 
    {过程功能:HookAPI 
    {过程参数:无 
    {------------------------------------} 
    procedure HookAPI; 
    var 
    DLLModule: THandle; 
    dwSize: cardinal; 
    begin 
    ProcessHandle := GetCurrentProcess; 
    DLLModule := LoadLibrary('ws2_32.dll'); 
    AddSend := GetProcAddress(DLLModule, 'send'); //取得API地址 
    AddRecv := GetProcAddress(DLLModule, 'recv'); 
    JmpCode.JmpCode := $B8; 
    JmpCode.MovEAX[0] := $FF; 
    JmpCode.MovEAX[1] := $E0; 
    JmpCode.MovEAX[2] := 0; 
    ReadProcessMemory(ProcessHandle, AddSend, @OldProc[0], 8, dwSize); 
    JmpCode.Address := @MySend; 
    WriteProcessMemory(ProcessHandle, AddSend, @JmpCode, 8, dwSize); //修改Send入口 
    ReadProcessMemory(ProcessHandle, AddRecv, @OldProc[1], 8, dwSize); 
    JmpCode.Address := @MyRecv; 
    WriteProcessMemory(ProcessHandle, AddRecv, @JmpCode, 8, dwSize); //修改Recv入口 
    OldSend := AddSend; 
    OldRecv := AddRecv; 
    end; 
    
    {------------------------------------} 
    {过程功能:取消HOOKAPI 
    {过程参数:无 
    {------------------------------------} 
    procedure UnHookAPI; 
    var 
    dwSize: Cardinal; 
    begin 
    WriteProcessMemory(ProcessHandle, AddSend, @OldProc[0], 8, dwSize); 
    WriteProcessMemory(ProcessHandle, AddRecv, @OldProc[1], 8, dwSize); 
    end; 
    
    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. 
  • 相关阅读:
    js 绑定事件没有触发的离奇事件
    TweenMax 中 tweenTo
    TweenMax 中 to,staggerTo 的第 4 、5 个参数
    Mongodb 数据库操作
    cocos2dx骨骼动画Armature源码分析(一)
    TexturePacker大图还原成小图工具带源码
    通过JavaScript原型链理解基于原型的编程
    webpack 之(25) output配置详解
    webpack 之(24) entry配置详解
    webpack 之(23) 优化配置 总结
  • 原文地址:https://www.cnblogs.com/linyawen/p/1948121.html
Copyright © 2020-2023  润新知