我想监听一个应用程序与网络的交互过程.查了些资料,就愣愣的用delphi的Socket控件监听,但是总没有结果.仔细查了查,原来那个程序在用4002端口,我的监听程序启动后,那个程序就自己跳到4001,或者4003端口去了.是跟本就不能用Socket控件监听呢?还是我犯了其他的错?请高手帮帮忙......顺便给个例子我开开眼......

解决方案 »

  1.   

    這個, 自己編寫比較麻煩,最好直接用工具,下面這個不錯:WinSock Expert
    Sniffer Pro 也不錯
      

  2.   

    挂接这程序的socket的函数,send,recv
      

  3.   

    标题     拦截其它程序的网络数据封包    pankun(原作)  
      
    关键字     Hook API 数据包 send recv 
      
    有时候我们需要对其它应用程序发送和接收的网络数据进行拦截,比如要对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.
      

  4.   

    APIHook.Pas的代码:unit APIHook;interfaceuses
      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;interfaceuses
      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;end.
     
    这段代码讲解;找到winsock 中send和Recv 地址来回替换,send和recv是封包发送,接受的函数,其中参数,buf为其中的数据封包,就是本段程序要的,自己定义myseng和myrecv来替换。处理数据就在自己定义的的这两个函数中,这个方法听说过,没想到这么简单,作者厉害呀!在myseng和myrecv中加如下代码就可以看到发送出去什么受到什么了。 var tmp:string; begin setlength(tmp,len); move(buf,tmp[1],len); showmessage(tmp); end; 关于hook函数就不讲了相信,能把文看完的,就回略知一 二 如果你知道怎么解密网络游戏封包的话,游戏外挂的原理你就明白了。