程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 攔截其它程序的網絡數據封包

攔截其它程序的網絡數據封包

編輯:Delphi

  有時候我們需要對其它應用程序發送和接收的網絡數據進行攔截,比如要對IE發送的HTTP頭進行分析,得到請求的地址等.這次我們可以用一些例如WPE, Sniffer之類的工具來達到目的.但是工具功能有限,要想實現更強大的功能,還是我們自己動手來DIY吧.
  

  攔截網絡數據封包的方法有三種,一是將網卡設為混雜模式,這次就可以監視到局域網上所有的數據包,二是HOOK目標進程的發送和接收的API函數,第三種方法是自己實現一個代理的DLL.在這裡我們使用HOOK API的方法,這樣易於實現,而且也不會得到大量的無用數據(如第一種方法就會監視到所有的網絡數據).

  
  下面是一個盡量簡化了的API HOOK的模版,原理是利用消息鉤子將DLL中的代碼注入到目標進程中,再用GetProcAddress得到API函數入口地址,將函數入口址改為自己定義的函數入口,這樣就得到了API函數的相應參數,處理完後,再改回真實API函數入口地址,並調用它.

  HOOK.DLL的代碼:
  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並傳入目標進程的主窗口句柄就可:
  unit fmMain;

  interface

  uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;

  type
    TForm1 = class(TForm)
      Button1: TButton;
      Button2: TButton;
      Edit1: TEdit;
      procedure Button1Click(Sender: TObject);
      procedure Button2Click(Sender: TObject);
    private
      { Private declarations }
    public
      { Public declarations }
    end;
   
  var
    Form1: TForm1;
    InstallHook: function (SWindow: THandle):Boolean;stdcall;
    UnHook: procedure;stdcall;
  implementation

  {$R *.dfm}

  procedure TForm1.Button1Click(Sender: TObject);
  var
    ModuleHandle: THandle;
    TmpWndHandle: THandle;
  begin
    TmpWndHandle := 0;
    TmpWndHandle := FindWindow(nil, '目標窗口的標題');
    if not isWindow(TmpWndHandle) then
    begin
      MessageBox(self.Handle, '沒有找到窗口', '!!!', MB_OK);
      exit;
    end;
    ModuleHandle := LoadLibrary('Hook.dll');
    @InstallHook := GetProcAddress(ModuleHandle, 'InstallHook');
    @UnHook := GetProcAddress(ModuleHandle, 'UnHook');
    if InstallHook(FindWindow(nil, 'Untitled')) then
      ShowMessage('Hook OK');
  end;

  procedure TForm1.Button2Click(Sender: TObject);
  begin
    UnHook
  end;

  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved