title: C++ - Detours WinSock Hooking
body: <p>What I am trying to do is use <a href="http://research.microsoft.com/en-us/projects/detours/" rel="nofollow noreferrer" title="Detours - Microsoft Research">the Detours library</a> to hook into an applications WinSock2 send() and recv() functions (a packet logger).</p>
  
  <p>While it does work for the send() function, it does not, however, work for the recv() function.</p>
  
  <p>Here is my relevant code:</p>
  
  <pre><code>#include &lt;cstdio&gt;
  #include &lt;ctime&gt;
  #include &lt;fstream&gt;
  #include &lt;iomanip&gt;
  #include &lt;string&gt;
  #include &lt;windows.h&gt;
  #include &lt;detours.h&gt;
  
  #pragma comment( lib, "Ws2_32.lib" )
  #pragma comment( lib, "detours.lib" )
  #pragma comment( lib, "detoured.lib" )
  #pragma comment( lib, "Mswsock.lib" )
  
  std::ofstream Logger;
  
  std::string NowToString() {
      time_t rawtime;
      tm *timeinfo = new tm();
      char buffer[32];
  
      time( &amp;rawtime );
      localtime_s( timeinfo, &amp;rawtime );
  
      strftime( buffer, 32, "%m/%d/%Y %I:%M:%S %p", timeinfo );
  
      delete timeinfo;
  
      return std::string( buffer );
  }
  
  std::string TimeToString() {
      time_t rawtime;
      tm *timeinfo = new tm();
      char buffer[32];
  
      time( &amp;rawtime );
      localtime_s( timeinfo, &amp;rawtime );
  
      strftime( buffer, 32, "%I:%M:%S %p", timeinfo );
  
      delete timeinfo;
  
      return std::string( buffer );
  }
  
  void LogPacket( const char *buf, int len ) {
      Logger &lt;&lt; "        0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F\n";
      Logger &lt;&lt; "       -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- --\n";
      Logger &lt;&lt; "0000   ";
  
      for ( int i = 0; i &lt; len; ++i ) {
          if ( i != 0 &amp;&amp; i % 16 == 0 ) {
              Logger &lt;&lt; "  ";
  
              int line = ( i / 16 ) - 1;
  
              for ( int j = 0; j &lt; 16; ++j ) {
                  char c = buf[line * 16 + j];
  
                  if ( c &gt;= 32 &amp;&amp; c &lt;= 126 ) {
                      Logger &lt;&lt; c;
                  } else {
                      Logger &lt;&lt; '.';
                  }
              }
  
              Logger &lt;&lt; "\n" &lt;&lt; std::hex &lt;&lt; std::setw( 4 ) &lt;&lt; std::setfill( '0' ) &lt;&lt; i &lt;&lt; std::dec &lt;&lt; std::setw( 0 ) &lt;&lt; "   ";
          } else if ( i % 16 == 8 ) {
              Logger &lt;&lt; ' ';
          }
  
          Logger &lt;&lt; std::hex &lt;&lt; std::setw( 2 ) &lt;&lt; std::setfill( '0' ) &lt;&lt; ( int( buf[i] ) &amp; 0xFF ) &lt;&lt; ' ';
          Logger &lt;&lt; std::dec &lt;&lt; std::setw( 0 );
  
          if ( i == len - 1 ) {
              int remaining = 16 - ( len % 16 );
              int fill = ( remaining * 3 ) + 2;
  
              if ( remaining &gt;= 8 ) {
                  ++fill;
              }
  
              for ( int j = 0; j &lt; fill; ++j ) {
                  Logger &lt;&lt; ' ';
              }
  
              int line = ( i - ( ( len % 16 ) - 1 ) ) / 16 ;
  
              for ( int k = 0; k &lt; ( len % 16 ); ++k ) {
                  char c = buf[line * 16 + k];
  
                  if ( c &gt;= 32 &amp;&amp; c &lt;= 126 ) {
                      Logger &lt;&lt; c;
                  } else {
                      Logger &lt;&lt; '.';
                  }
              }
          }
      }
  
      Logger &lt;&lt; "\n\n";
  }
  
  int ( WINAPI *Real_Send )( SOCKET s, const char *buf, int len, int flags ) = send;
  int ( WINAPI *Real_Recv )( SOCKET s, char *buf, int len, int flags ) = recv;
  int ( WINAPI *Real_RecvFrom )( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen ) = recvfrom;
  int ( WINAPI *Real_WSARecvEx )( SOCKET s, char *buf, int len, int *flags ) = WSARecvEx;
  
  int WINAPI Mine_Send( SOCKET s, const char* buf, int len, int flags );
  int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags );
  int WINAPI Mine_RecvFrom( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen );
  int WINAPI Mine_WSARecvEx( SOCKET s, char *buf, int len, int *flags );
  
  int WINAPI Mine_Send( SOCKET s, const char *buf, int len, int flags ) {
      Logger &lt;&lt; TimeToString() &lt;&lt; ": Client -&gt; Server (Length: " &lt;&lt; len &lt;&lt; " bytes)\n\n";
      LogPacket( buf, len );
      Logger &lt;&lt; std::endl;
  
      return Real_Send( s, buf, len, flags );
  }
  
  int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags ) {
      Logger &lt;&lt; TimeToString() &lt;&lt; ": Server -&gt; Client (Length: " &lt;&lt; len &lt;&lt; " bytes)\n\n";
      LogPacket( buf, len );
      Logger &lt;&lt; std::endl;
  
      return Real_Recv( s, buf, len, flags );
  }
  
  int WINAPI Mine_RecvFrom( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen ) {
      Logger &lt;&lt; TimeToString() &lt;&lt; ": Server -&gt; Client (Length: " &lt;&lt; len &lt;&lt; " bytes)*\n\n";
      LogPacket( buf, len );
      Logger &lt;&lt; std::endl;
  
      return Real_RecvFrom( s, buf, len, flags, from, fromlen );
  }
  
  int WINAPI Mine_WSARecvEx( SOCKET s, char *buf, int len, int *flags ) {
      Logger &lt;&lt; TimeToString() &lt;&lt; ": Server -&gt; Client (Length: " &lt;&lt; len &lt;&lt; " bytes)**\n\n";
      LogPacket( buf, len );
      Logger &lt;&lt; std::endl;
  
      return Real_WSARecvEx( s, buf, len, flags );
  }
  
  BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) {
      switch ( dwReason ) {
          case DLL_PROCESS_ATTACH:    
              Logger.open( "C:\\Packets.txt", std::ios::out | std::ios::app | std::ios::ate );
  
              if ( Logger.tellp() &gt; 0 ) {
                  Logger &lt;&lt; "\n\n\n";
              }
  
              Logger &lt;&lt; "##\n## Logging Started (" &lt;&lt; NowToString() &lt;&lt; ")\n##\n\n\n";
  
              DetourTransactionBegin();
              DetourUpdateThread( GetCurrentThread() );
              DetourAttach( &amp;(PVOID &amp;)Real_Send, Mine_Send );
              DetourAttach( &amp;(PVOID &amp;)Real_Recv, Mine_Recv );
              DetourAttach( &amp;(PVOID &amp;)Real_RecvFrom, Mine_RecvFrom );
              DetourAttach( &amp;(PVOID &amp;)Real_WSARecvEx, Mine_WSARecvEx );
              DetourTransactionCommit();
  
              break;
  
          case DLL_PROCESS_DETACH:
              Logger &lt;&lt; "##\n## Logging Stopped (" &lt;&lt; NowToString() &lt;&lt; ")\n##";
              Logger.close();
  
              DetourTransactionBegin();
              DetourUpdateThread( GetCurrentThread() );
              DetourDetach( &amp;(PVOID &amp;)Real_Send, Mine_Send );
              DetourDetach( &amp;(PVOID &amp;)Real_Recv, Mine_Recv );
              DetourDetach( &amp;(PVOID &amp;)Real_RecvFrom, Mine_RecvFrom );
              DetourDetach( &amp;(PVOID &amp;)Real_WSARecvEx, Mine_WSARecvEx );
              DetourTransactionCommit();
  
              break;
      }
  
      return TRUE;
  }
  </code></pre>
  
  <p>Any ideas?</p>
  
  <p><strong>EDIT:</strong> So I've hooked recvfrom(), and WSARecvEx() as well, and it still doesn't log the outgoing packets! I've updated my code with my exact code.</p>