HOOK 的 WSASEND函数对lpBuffers.buf 数据进行修改后发送如果修改后的数据长度小于或等于原来的长度,发送一切正常,程序无任何问题但是如果修改后的数据大于原数据长度,发送也是正常的(接收端接收到了完整的数据包),但是程序就不再继续发包了...不知道大家看明白没有百度  谷歌翻遍了  遇到此问题的也不在少数  但没找到答案希望高人解答

解决方案 »

  1.   

    ............HookAPI('wsock32.dll','WSASocket',@WSASocketHook,@WSASocketOrigin);     HookAPI('ws2_32.dll','WSASend',@WSASendHook,@WSASendOrigin);     HookAPI('ws2_32.dll','Send',@mylogSend,@oldsend);     HookAPI('wsock32.dll','Send',@mylogSend,@oldsend);     HookAPI('ws2_32.dll','Recv',@mylogrecv,@oldrecv);     HookAPI('ws2_32.dll','WSARecv',@WSARecvHook,@WSARecvOrigin);     HookAPI('ws2_32.dll','Socket',@SocketHook,@SocketOrigin);     这些是madcodehook中的函数     我HOOK了这些函数。其中wsarecv可以获得,别的不能获得     其中,wsarecv和send的函数定义及实现为以下,其中wsarecv可以捕获,send不能捕获     var   WSARecvOrigin:function(s:TSocket;lpBuffers:LPWSABUF;                         dwBufferCount:dword;lpNumberOfBytesRecvd:LPDWORD;                         dwFlags:DWORD;lpOverlapped:LPWSAOVERLAPPED;                         lpCompletionROUTINE:LPWSAOVERLAPPED_COMPLETION_ROUTINE):integer;stdcall;         function   WSARecvHook(s:TSocket;lpBuffers:LPWSABUF;                         dwBufferCount:dword;lpNumberOfBytesRecvd:LPDWORD;                         dwFlags:DWORD;lpOverlapped:LPWSAOVERLAPPED;                         lpCompletionROUTINE:LPWSAOVERLAPPED_COMPLETION_ROUTINE):integer;stdcall;     begin       WSARecvHook:=WSARecvOrigin(s,lpBuffers,dwBufferCount,                         lpNumberOfBytesRecvd,dwFlags,lpOverlapped,lpCompletionROUTINE);       MyRecv(lpBuffers.buf,lpNumberOfBytesRecvd^);           if   GameSocket<>s   then         GameSocket:=s;     end;     这个可以获得     var       oldsend:function   (s:   TSocket;   var   Buf:pchar;   len,   flags:   Integer):   Integer;   stdcall;     function   MylogSend(s:   TSocket;   var   Buf:pchar;   len,   flags:   Integer):   Integer;   stdcall;     var       dwSize:   cardinal;     begin       MessageBeep(1000);    //简单的响一声       //调用直正的Send函数       mylogsend:=oldsend(s,buf,len,flags);       if   GameSocket<>s   then         GameSocket:=s;     end;         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;     { }     {函数功能:Send函数的HOOK     {函数参数:同Send     {函数返回值:integer     { }     function   MySend(s:   TSocket;   var   Buf:pchar;   len,   flags:   Integer):   Integer;   stdcall;     var       x1,dwSize:   cardinal;       text:array[0..128]   of   char;     begin     //hooksend(buf,len);     copychar(@text[0],buf,len);     prolog(@text[0],len);       //这儿进行发送的数据处理       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;   
    ...........................
      

  2.   

    to 居士我不是在问如何HOOK  我是问如何修改HOOK到得lpBuffers.buf数据  可以正常通讯遇到的问题适当修改后的数据长度小于或等于原数据时一切正常但是修改后的数据长度大于原数据时 就不能正常通讯了
      

  3.   

    你還是找找關於madCodeHook方面的東東確認有沒有没有madCHook.dll這個文件...
      

  4.   

    TO 居士我根本不是用的madCodeHook 找madCodeHook.dll有何用
      

  5.   

    如果我的表达不够清楚你可以看看类似的问题http://topic.csdn.net/u/20100730/09/a20494a9-961b-48b9-8886-17acffaf36af.htmlhttp://topic.csdn.net/u/20081011/12/9fa946f1-3f20-4701-a2ae-e2c12fa9a907.html
      

  6.   

    解决方案
    1.只处理一次能发出的包,也就是尽量避免会产生WSAEWOULDBLOCK的包。具体,可咨询我。
    2.Send以后,返回值,仍使用原始包长度,而不要使用改变后的包长度。
      

  7.   

    to CaesarDM能详细说下吗1.只处理一次能发出的包,也就是尽量避免会产生WSAEWOULDBLOCK的包。具体,可咨询我。
    2.Send以后,返回值,仍使用原始包长度,而不要使用改变后的包长度。我就是只处理了一次啊  返回值是哪个参数呢 通过跟踪发现 正常情况下 和我现在不正常情况的返回值都是-1
    function MyWSASEND(s: TSocket; lpBuffers: LPWSABUF; dwBufferCount: DWORD; var lpNumberOfBytesSent: DWORD; dwFlags: DWORD; lpOverlapped: LPWSAOVERLAPPED; lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE): Integer; stdcall;
    var
      dwSize: cardinal;
      tmp: AnsiString;
      newlpBuffers: LPWSABUF;
      tmplength: DWORD;
    begin
      setlength(tmp, lpBuffers.len);
      move(lpBuffers.buf^, tmp[1], lpBuffers.len);
      tmp := tmp + 'aaaa'; //随便举个例子  增加封包长度
      New(newlpBuffers);
      newlpBuffers.len := Length(tmp); //写回现在的长度
      GetMem(newlpBuffers.buf, newlpBuffers.len);
      Move(tmp[1], newlpBuffers.buf^, newlpBuffers.len); //写回改变后的封包  //调用直正的Send函数
      WriteProcessMemory(ProcessHandle, AddSend, @OldProc[0], 8, dwSize);
      Result := OldSend(s, newlpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine);
      DebugOutStr('Result:' + inttostr(Result)); //此处的返回值 全都是 -1
      JmpCode.Address := @MyWSASEND;
      WriteProcessMemory(ProcessHandle, AddSend, @JmpCode, 8, dwSize);
      FreeMem(newlpBuffers.buf);
      Dispose(newlpBuffers);
    end;
      

  8.   

    var
      pData, pOldData:PChar;
      dwLen, dwOldLen:DWORD;
      bDataChanged:Boolean;
    begin
      bDataChanged := False;
      //多个包的情况,不改变。因为。危险 。
      if dwBufferCount=1 then
      begin
        //太大的包也不处理
        pData := nil;
        if LPWSABUFS(lpBuffers)[0].len<=1500 then
        begin
          dwLen := LPWSABUFS(lpBuffers)[0].len +5;
          //增加5个字节长度
          pData := AllocMem(dwLen);
          ....  //给pData赋值
          pOldData := LPWSABUFS(lpBuffers)[0].buf;
          dwOldLen := LPWSABUFS(lpBuffers)[0].len;
          LPWSABUFS(lpBuffers)[0].buf = pData;
          LPWSABUFS(lpBuffers)[0].len = dwLen;      //标识数据已改变
          bDataChanged := True;
        end;  end;  Result := OldSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine);  if bDataChanged then
      begin
        lpNumberOfBytesSent := dwLen;
        LPWSABUFS(lpBuffers)[0].buf = pOldData;
        LPWSABUFS(lpBuffers)[0].len = dwOldLen;
      end;  if pData<>nil then
        FreeMemory(pData);
    end;
      

  9.   

    感谢CaesarDM回复,我先测试下你的例子有问题再来请教
      

  10.   

    请教大大LPWSABUFS是在哪里定义的 结构是什么  我的WinSock2里面没有这个定义还有
      if bDataChanged then
      begin
      lpNumberOfBytesSent := dwLen;
      LPWSABUFS(lpBuffers)[0].buf = pOldData;
      LPWSABUFS(lpBuffers)[0].len = dwOldLen;
      end;
    你不是说2.Send以后,返回值,仍使用原始包长度,而不要使用改变后的包长度。怎么会是改变后的长度而且我通过跟踪发现 不论成功与否这个参数的值是不变的  就是说赋值多少 下次还是多少,没有赋值的话始终是0
      

  11.   

    CaesarDM大大的例子是否做过测试呢   还是只是随手写的?测试无效果  还是跟我的一样发包之后  返回的包  他并不处理...
      

  12.   

    错了,是
    WSABUFS=array[0..0] of WSABUF;
    LPWSABUFS = ^WSABUFS;
      

  13.   

    跟踪过了  所有的包数量都是只有一个  bDataChanged := False;
      //多个包的情况,不改变。因为。危险 。
      if dwBufferCount=1 then
      begin
      //太大的包也不处理
      pData := nil;
      if lpBuffers.len<=1500 then
      begin
        setlength(tmp, lpBuffers.len);
        move(lpBuffers.buf^, tmp[1], lpBuffers.len);
        tmp := tmp + 'aaaa'; //测试增大封包
        dwLen := Length(tmp);
        pData := AllocMem(dwLen);
        Move(tmp[1], pData^, dwLen); //写回加密后的封包    pOldData := lpBuffers.buf;
        dwOldLen := lpBuffers.len;
        lpBuffers.buf := pData;
        lpBuffers.len := dwLen;    //标识数据已改变
        bDataChanged := True;
      end;
      end;
      WriteProcessMemory(ProcessHandle, AddSend, @OldProc[0], 8, dwSize);
      Result := OldSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine);
      if bDataChanged then
      begin
        lpNumberOfBytesSent := dwOldLen;
        lpBuffers.buf := pOldData;
        lpBuffers.len := dwOldLen;
      end;
      if pData <> nil then FreeMemory(pData);
      JmpCode.Address := @MySend;
      WriteProcessMemory(ProcessHandle, AddSend, @JmpCode, 8, dwSize);
    IdWinSock2单元并没有LPWSABUFS的定义我是Delphi2010 Indy 10.5.5
      

  14.   

    恩 如果那样的话 LPWSABUFS(lpBuffers)[0].buf  跟我写的不就是一样的!!
      

  15.   

    很不一样,请参阅MSDN,以后慢慢体会
      

  16.   

    想问下CaesarDM大大是否有做过测试 或做过这方面的程序呢?还是说仅仅是根据理论书写的代码?
      

  17.   

    WSABUFS=array[0..0] of WSABUF;
    LPWSABUFS = ^WSABUFS;lpBuffers: LPWSABUF;LPWSABUFS(lpBuffers)[0].buf 和 lpBuffers.buf  有何不同了
      

  18.   

    写错了  是lpBuffers.buf^
      

  19.   

    Send可以一次发多个缓冲,所以,嗯,那啥。
    其实MSDN文档里描述的很清楚这种方式一个潜在的问题是使用IOCP的程序,可能会受影响。非理论。
      

  20.   

    这是我记录的正常通讯各参数返回值18:19:21 包数量:1
    18:19:21 原长度lpBuffers.len:64
    18:19:21 Result:-1
    18:19:21 lpNumberOfBytesSent:0
    18:19:21 dwFlags:0
    18:19:21 lpOverlapped.Internal:0
    18:19:21 lpOverlapped.InternalHigh:64
    18:19:21 lpOverlapped.Offset:0
    18:19:21 lpOverlapped.OffsetHigh:0
    18:19:21 lpOverlapped.hEvent:46818:19:21 包数量:1
    18:19:21 原长度lpBuffers.len:10
    18:19:21 Result:-1
    18:19:21 lpNumberOfBytesSent:0
    18:19:21 dwFlags:0
    18:19:21 lpOverlapped.Internal:0
    18:19:21 lpOverlapped.InternalHigh:10
    18:19:21 lpOverlapped.Offset:0
    18:19:21 lpOverlapped.OffsetHigh:0
    18:19:21 lpOverlapped.hEvent:468你的例子中修改lpNumberOfBytesSent参数  不知道意义何在 正常通讯全部返回值是0  唯一一处有包长纪录的lpOverlapped.InternalHigh  我也试着改过了 依然无效
      

  21.   

    这是改过包长后的记录18:31:32 包数量:1
    18:31:32 原长度lpBuffers.len:64
    18:31:32 Result:-1
    18:31:32 lpNumberOfBytesSent:0
    18:31:32 dwFlags:0
    18:31:32 lpOverlapped.Internal:0
    18:31:32 lpOverlapped.InternalHigh:128
    18:31:32 lpOverlapped.Offset:0
    18:31:32 lpOverlapped.OffsetHigh:0
    18:31:32 lpOverlapped.hEvent:468
    18:31:32 lpOverlapped.InternalHigh改:6418:31:32 包数量:1
    18:31:32 原长度lpBuffers.len:4294967232
    18:31:32 Result:-1
    18:31:32 lpNumberOfBytesSent:0第一个包正常  第二个包就变了