Home > front end >  hook at AcceptEx retrieve remote connection ip
hook at AcceptEx retrieve remote connection ip

Time:05-06

i'm hooking AcceptEx. how i can retrieve remote connection ip from socket? since getpeername don't show right ip.

function GetRemoteSocketAddress ( s : TSocket ) : String;
var
  Addr                  : TSockAddrIn;
  Size: integer;
begin
  Size := sizeof(Addr);
  getpeername(s, Addr, Size);
  Result := inet_ntoa(Addr.sin_addr);
end;

this code works fine for others APIS like Send, Connect, Recv, all return right ip but not with AcceptEx.

function AcceptExHookProc(sListenSocket, sAcceptSocket: TSocket;
  lpOutputBuffer: Pointer; dwReceiveDataLength, dwLocalAddressLength,
  dwRemoteAddressLength: DWORD; var lpdwBytesReceived: DWORD;
  lpOverlapped: POverlapped): BOOL; stdcall;
begin
  WriteLn(Format('[%s] Connection from IP (%s)', [TimeToStr(Now), GetRemoteSocketAddress(sAcceptSocket)]));
  Result := TrampolineAcceptEx(sListenSocket, sAcceptSocket, lpOutputBuffer,
    dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived,
    lpOverlapped);
end;

tried sAcceptSocket or sListenSocket both show wrong ip. tried retrieve ip before result, after result, always same wrong ip.

any idea?

CodePudding user response:

You are calling getpeername() too soon.

You are calling getpeername() before you call the original AcceptEx(), so there is no socket connection established yet on which to query the remote party. You can't call getpeername() until after AcceptEx() is successful. This is even stated as much in the AcceptEx() documentation:

Using a single buffer improves performance. When using AcceptEx, the GetAcceptExSockaddrs function must be called to parse the buffer into its three distinct parts (data, local socket address, and remote socket address). On Windows XP and later, once the AcceptEx function completes and the SO_UPDATE_ACCEPT_CONTEXT option is set on the accepted socket, the local address associated with the accepted socket can also be retrieved using the getsockname function. Likewise, the remote address associated with the accepted socket can be retrieved using the getpeername function.

So, you must call AcceptEx() first, wait for it to complete successfully, then set the SO_UPDATE_ACCEPT_CONTEXT state via setsockopt() (which the program calling AcceptEx() should handle, don't set that state inside your hook code, unless you are also hooking setsockopt() itself), and only then can you use getpeerename() on the accepted connection.

A better option is to have your AcceptExHookProc() call the original GetAcceptExSockaddrs() immediately after TrampolineAcceptEx() exits (if successful) to parse the lpOutputBuffer contents. But, that will only work if the lpOverlapped parameter is nil so AcceptEx() acts synchronously.

If lpOverlapped is not nil, so AcceptEx() acts asynchronously, you would have to hook GetAcceptExSockaddrs() and log the result of the original function parsing the caller's buffer. But, there is no guarantee the program will actually call GetAcceptExSockaddrs() after AcceptEx(), if it doesn't want the remote party info. In which case, you would have to resort to hooking into GetOverlappedResult/Ex() and/or GetQueuedCompletionStatus() to receive the original lpOverlapped operation result in order to then call GetAcceptExSockaddrs() yourself if the operation is successful.

CodePudding user response:

Solution:

    var
      IP            : String;
      LRet, RRet    : Winsock.PSockAddr;
      lsize, rsize  : Integer;
    begin
          Result := TrampolineAcceptEx(sListenSocket, sAcceptSocket, lpOutputBuffer,
    dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength, lpdwBytesReceived,
    lpOverlapped);

          lsize   := 32;
          rsize   := 32;
          Winsock.GetAcceptExSockaddrs(lpOutputBuffer, dwReceiveDataLength, dwLocalAddressLength, dwRemoteAddressLength, LRet, lsize, RRet, rsize);
        
          IP := Winsock.inet_ntoa(RRet.sin_addr);
        
          WriteLn(Format('[%s] Connection from IP (%s)', [TimeToStr(Now), IP]));
  • Related