Commits

Alexander Konovalov  committed d8bb784

Comments fixed, unique pipe name.

  • Participants
  • Parent commits 1d1246c

Comments (0)

Files changed (2)

File src/winsock-sniffer-dll/main.cpp

 #include <cstdio>
 #include <cstdlib>
+#include <cstdarg>
 
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
   return true;
 }
 
-/*
-
-
-void LogFunctionCall(SocketFunctions funcType, SOCKET socket, const char* buf, int len) {
-  SharedGuard guard;
-
-  if (g_clientWindowHandle == NULL || !IsWindow(g_clientWindowHandle)) {
-    return;
-  }
-
-  if ((funcType & g_activeLoggingMask) == 0) {
-    return;
-  }
-
-  if (len <= 0) {
-    return;
-  }
-
-  std::string srcAddr = "unknown";
-  uint16_t srcPort = 0;
-  std::string dstAddr = "unknown";
-  uint16_t dstPort = 0;
-
-  if (funcType == SOCK_FUNC_SEND || funcType == SOCK_FUNC_SENDTO || 
-    funcType == SOCK_FUNC_WSASEND || funcType == SOCK_FUNC_WSASENDTO) {
-      GetSocketAddress(true, socket, srcAddr, srcPort);
-      GetSocketAddress(false, socket, dstAddr, dstPort);    
-  } else {
-    GetSocketAddress(false, socket, srcAddr, srcPort);
-    GetSocketAddress(true, socket, dstAddr, dstPort);  
-  }
-
-  DWORD pid = GetCurrentProcessId();
-
-  FunctionLogData* data = MakeFunctionLogData(funcType, pid, socket, srcAddr, srcPort, dstAddr, dstPort, buf, len);
-  SendRawDataToClient(data, len + sizeof(FunctionLogData));
-  ::free(data);
-}
-
-HANDLE g_mutex = 0;
-HWND g_wndHandle = 0;
-
-void SetClientWindowHandle(HWND hWnd) {
-  WaitForSingleObject(g_mutex, INFINITE);
-  g_wndHandle = hWnd;
-  ReleaseMutex(g_mutex);
-}*/
-
 typedef int (PASCAL FAR *SendFuncPtr) (SOCKET s, const char FAR * buf, int len, int flags);
 typedef int (PASCAL FAR  *RecvFuncPtr) (SOCKET s, char FAR * buf, int len, int flags);
 SendFuncPtr sendFunc;
 RecvFuncPtr recvFunc;
 
-HANDLE g_pipe;
-HANDLE g_threadHandle;
-DWORD g_threadId;
+volatile HANDLE g_pipe = INVALID_HANDLE_VALUE;
+volatile HANDLE g_threadHandle = INVALID_HANDLE_VALUE;
+volatile DWORD g_threadId = 0;
 
 struct Packet {
   static const uint8_t SEND = 0x01;
   };
 };
 
+BOOL SendData(const void* buf, size_t len) {
+  HANDLE hPipe = g_pipe;
+
+  if (hPipe != INVALID_HANDLE_VALUE) {
+    DWORD dwTotalWritten = 0;
+        
+    while (dwTotalWritten < len) {
+      DWORD dwWritten = 0;
+      DWORD dwRemaining = len - dwTotalWritten;
+      LPBYTE lpData = ((LPBYTE) buf) + dwTotalWritten;
+      
+      BOOL bOk = WriteFile(hPipe, lpData, dwRemaining, &dwWritten, NULL);
+      if (!bOk) {
+        return FALSE;
+      }
+      
+      dwTotalWritten += dwWritten;
+    }
+  }
+  
+  return TRUE;
+}
+
 int PASCAL FAR SendHook(IN SOCKET s, IN const char FAR * buf, IN int len, IN int flags) {
   int sent = sendFunc(s, buf, len, flags);
   
   packet.dataLength = sent;
   packet.flags = flags;
   
-  DWORD dwWritten;
-  WriteFile(g_pipe, &packet, sizeof(packet), &dwWritten, NULL);
-  WriteFile(g_pipe, buf, packet.dataLength, &dwWritten, NULL);
+  if (!SendData(&packet, sizeof(packet))) {
+    CloseHandle(g_pipe);
+    g_pipe = INVALID_HANDLE_VALUE;
+  }
+  
+  if (!SendData(buf, packet.dataLength)) {
+    CloseHandle(g_pipe);
+    g_pipe = INVALID_HANDLE_VALUE;
+  }
   
   return sent;
 }
   packet.dataLength = recieved;
   packet.flags = flags;
 
-  DWORD dwWritten;
-  WriteFile(g_pipe, &packet, sizeof(packet), &dwWritten, NULL);
-  WriteFile(g_pipe, buf, packet.dataLength, &dwWritten, NULL);
+  if (!SendData(&packet, sizeof(packet))) {
+    CloseHandle(g_pipe);
+    g_pipe = INVALID_HANDLE_VALUE;
+  }
+
+  if (!SendData(buf, packet.dataLength)) {
+    CloseHandle(g_pipe);
+    g_pipe = INVALID_HANDLE_VALUE;
+  }
   
   return recieved;
 }
 }
 
 int WINAPI DllMain(HMODULE hDLL, DWORD fdwReason, LPVOID lpReserved) {
-	return TRUE;
+  return TRUE;
 }

File src/winsock-sniffer/main.cpp

   return true;
 }
 
-template<class T> bool RemoteRead(HANDLE hProcess, LPCVOID pRemote, T& value) {
-  return RemoteRead(hProcess, pRemote, &value, sizeof(T));
-}
-
 bool RemoteWrite(HANDLE hProcess, LPVOID pRemote, LPCVOID pBuf, SIZE_T szLen) {
   SIZE_T dwWritten = 0;
   BOOL bResult = FALSE;
   return true;
 }
 
-template<class T> bool RemoteWrite(HANDLE hProcess, LPVOID pRemote, const T& value) {
-  return RemoteWrite(hProcess, pRemote, &value, sizeof(T));
-}
-
 LPCBYTE GetFileHeaderPtr(HANDLE hProcess, HMODULE hModule) {  
-  // Read old dos header.
+  // Read the old dos header.
   IMAGE_DOS_HEADER dosHeader;
-  if (RemoteRead(hProcess, hModule, dosHeader) == false) {
+  if (RemoteRead(hProcess, hModule, &dosHeader, sizeof(dosHeader)) == false) {
     return NULL;
   }
 
   LPCBYTE ntHeaderPtr = (LPCBYTE) (LPCVOID) hModule + dosHeader.e_lfanew;
   DWORD dwSignature = 0;
   
-  if (RemoteRead(hProcess, ntHeaderPtr, dwSignature) == false) {
+  if (RemoteRead(hProcess, ntHeaderPtr, &dwSignature, sizeof(dwSignature)) == false) {
     return NULL;
   }
   
 
   // Read the file header.
   IMAGE_FILE_HEADER fileHeader;
-  if (RemoteRead(hProcess, fileHeaderPtr, fileHeader) == false) {
+  if (RemoteRead(hProcess, fileHeaderPtr, &fileHeader, sizeof(fileHeader)) == false) {
     return NULL;
   }
 
   // Read optional header magic number.
   LPCBYTE optionalHeaderPtr = fileHeaderPtr + sizeof(IMAGE_FILE_HEADER);
   WORD optionalHeaderMagic;
-  if (RemoteRead(hProcess, optionalHeaderPtr, optionalHeaderMagic) == false) {
+  if (RemoteRead(hProcess, optionalHeaderPtr, &optionalHeaderMagic, sizeof(optionalHeaderMagic)) == false) {
     return NULL;
   }
 
   assert(optionalHeaderMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC);
 
   IMAGE_OPTIONAL_HEADER32 optionalHeader;
-  if (RemoteRead(hProcess, optionalHeaderPtr, optionalHeader) == false) {
+  if (RemoteRead(hProcess, optionalHeaderPtr, &optionalHeader, sizeof(optionalHeader)) == false) {
     return NULL;
   }
 
 
   for (size_t i = 0; i < cbFunc; i++) {
     DWORD funcNameRVA = 0;
-    if (RemoteRead(hProcess, lpFuncTable + sizeof(DWORD) * i, funcNameRVA) == false) {
+    if (RemoteRead(hProcess, lpFuncTable + sizeof(DWORD) * i, &funcNameRVA, sizeof(funcNameRVA)) == false) {
       delete[] buf;
       return 0xFFFFFFFF;
     }
 
   LPCBYTE exportDirectoryPtr = GetExportDirectory(hProcess, hModule);
   IMAGE_EXPORT_DIRECTORY exportDirectory;
-  if (RemoteRead(hProcess, exportDirectoryPtr, exportDirectory) == false) {
+  if (RemoteRead(hProcess, exportDirectoryPtr, &exportDirectory, sizeof(exportDirectory)) == false) {
     return NULL;
   }
   
   
   WORD funcIndex;
   if (RemoteRead(hProcess, (LPCBYTE) hModule + exportDirectory.AddressOfNameOrdinals + sizeof(WORD) * nameIndex, 
-                 funcIndex) == false) {
+                 &funcIndex, sizeof(funcIndex)) == false) {
     return NULL;
   }
   
   DWORD funcRVA;
   if (RemoteRead(hProcess, (LPCBYTE) hModule + exportDirectory.AddressOfFunctions + sizeof(DWORD) * funcIndex, 
-                 funcRVA) == false) {
+                 &funcRVA, sizeof(funcRVA)) == false) {
       return NULL;
   }
   
   assert(relPath != NULL);
   assert(strlen(relPath) <= MAX_PATH);
   
-  // intermediate buffer
+  // Intermediate buffer.
   char buffer[MAX_PATH * 2 + 2];
   
-  // get current working directory
+  // Get current working directory.
   DWORD nLength = GetCurrentDirectoryA(sizeof(buffer), buffer);
   
-  // check that there is enough space for the whole path
+  // Check that there is enough space for the whole path.
   assert(nLength + strlen(relPath) + 2 <= sizeof(buffer));
   
-  // concat paths
+  // Concat paths.
   strcat(buffer, "\\");
   strcat(buffer, relPath);
   
-  // duplicate buffer
+  // Duplicate the buffer.
   return _strdup(buffer);
 }
 
   };
 };
 
+// Makes a random valid pipe name. 
+void MakeRandomPipeName(LPSTR lpName, SIZE_T szName, HANDLE hProcess) {
+  DWORD dwCurrentProcessId = GetCurrentProcessId();
+  DWORD dwProcessId = GetProcessId(hProcess);
+  _snprintf(lpName, szName, "\\\\.\\pipe\\winsock_sniffer_%x_%x", dwCurrentProcessId, dwProcessId);
+}
+
+void ReportError(DWORD errCode) {
+  LPSTR lpMsgBuf;
+
+  BOOL bOk = FormatMessageA(
+    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+    NULL,
+    errCode,
+    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+    (LPSTR) &lpMsgBuf,
+    0,
+    NULL
+    );
+
+  if (!bOk) {
+    fprintf(stderr, "Win32Error: Could not format last win32 error.\n");
+    return;
+  }
+
+  LPSTR p = strchr(lpMsgBuf, '\r');
+  if (p != NULL) {
+    *p = '\0';
+    if (p != lpMsgBuf) {
+      p = p - 1;
+      if (*p == '.') {
+        *p = '\0';
+      }
+    }
+  }
+  
+  fprintf(stderr, "Win32Error: %s.\n", lpMsgBuf);
+  
+  LocalFree((HLOCAL) lpMsgBuf);
+}
+
+// Read pipe.
+// Returns FALSE if there was an error.
+VOID ReadPipe(HANDLE hPipe, LPBYTE lpData, SIZE_T szData, BOOL* lpbReadError, BOOL* lpbBroken) {
+  assert(hPipe != NULL);
+  assert(lpData != NULL);
+  assert(lpbBroken != NULL);
+  assert(lpbReadError != NULL);
+
+  SIZE_T dwTotalRead = 0;
+  DWORD dwLastRead = 0;
+  
+  *lpbBroken = FALSE;
+  *lpbReadError = FALSE;
+  
+  while (dwTotalRead < szData) {
+    DWORD dwToRead = szData - dwTotalRead;
+    LPBYTE lpBuf = lpData + dwTotalRead;
+    
+    BOOL bResult = ReadFile(hPipe, lpBuf, dwToRead, &dwLastRead, NULL);
+    
+    if (!bResult || dwLastRead == 0) {
+      DWORD dwLastError = GetLastError();
+
+      if (dwLastError == ERROR_BROKEN_PIPE) {
+        *lpbBroken = TRUE;
+        break;
+      } else {
+        *lpbReadError = TRUE;
+        break;
+      }
+    }
+    
+    dwTotalRead += dwLastRead;
+  }
+}
+
+bool ReadPacketDataAndPrint(HANDLE hPipe, size_t dataLength) {
+  BYTE buffer[4096];
+  BOOL bBroken = FALSE;
+  BOOL bReadError = FALSE;
+  
+  size_t totalCount = 0;
+  size_t lineCount = 0;
+
+  while (totalCount < dataLength) {
+    size_t remaining = dataLength - totalCount;
+    size_t toRead = min(sizeof(buffer), remaining);
+
+    ReadPipe(hPipe, buffer, toRead, &bReadError, &bBroken);
+
+    if (bReadError) {
+      ReportError(GetLastError());
+      fprintf(stderr, "Pipe error.\n");
+      CloseHandle(hPipe);
+      return false;
+    }
+
+    if (bBroken) {
+      printf("Pipe was closed on the other end.\n");
+      CloseHandle(hPipe);
+      return true;
+    }
+
+    for (size_t i = 0; i < toRead; i++, lineCount++) {
+      if (lineCount == 16 || totalCount + i == dataLength) {
+        fprintf(stdout, "\n");
+        lineCount = 0;
+      }
+    
+      if (lineCount == 0) {
+        // Print the offset of the first byte on the line
+        fprintf(stdout, "%.8X  ", totalCount + i);
+      }
+
+      fprintf(stdout, "%.2X ", buffer[i]);
+    }
+    
+    totalCount += toRead;
+  }
+  
+  return true;
+}
+
 int main(int argc, char** argv) {
   if (argc != 2) {
     printf("Invalid arguments.");
   PROCESS_INFORMATION pi;
   
   if (!CreateProcess(lpCmdLine, TRUE, &pi)) {
-    printf("Could not create process.");
+    ReportError(GetLastError());
+    fprintf(stderr, "Could not create process.\n");
     return EXIT_FAILURE;
   }
   
   HMODULE hModule = RemoteLoadLibrary(pi.hProcess, lpDLLName);
   if (hModule == NULL) {
-    printf("Could not load library.");
+    ReportError(GetLastError());
+    fprintf(stderr, "Could not load library.\n");
     return EXIT_FAILURE;
   }
   
-  LPCSTR lpPipeName = "\\\\.\\pipe\\rqz";
+  CHAR lpPipeName[MAX_PATH + 1];
+  MakeRandomPipeName(lpPipeName, MAX_PATH, pi.hProcess);
   
   FARPROC openPipe = RemoteGetProcAddress(pi.hProcess, hModule, "OpenPipe");
   
   LPVOID lpAddress = RemoteAllocateAndCopy(pi.hProcess, lpPipeName, lstrlenA(lpPipeName) + 1);
   DWORD dwResult = 0;
   if (!RemoteSynchronousCall(pi.hProcess, openPipe, lpAddress, &dwResult) || dwResult != TRUE) {
-    printf("Could not call OpenPipe in the remote process.");
+    ReportError(GetLastError());
+    fprintf(stderr, "Could not call OpenPipe in the remote process.\n");
     return EXIT_FAILURE;
   }
   
   ResumeThread(pi.hThread);
+  CloseHandle(pi.hThread);
+  CloseHandle(pi.hProcess);
+  pi.hThread = INVALID_HANDLE_VALUE;
+  pi.hProcess = INVALID_HANDLE_VALUE;
   
   while (true) {
     Packet packet;
-    BYTE buf[4096];
     
-    DWORD dwRead;
-    BOOL bResult = ReadFile(hPipe, &packet, sizeof(packet), &dwRead, NULL);
+    BOOL bBroken = FALSE;
+    BOOL bReadError = FALSE;
     
-    if (!bResult || dwRead == 0) {
-      printf("Pipe error.\n");
+    ReadPipe(hPipe, (LPBYTE) &packet, sizeof(packet), &bReadError, &bBroken);
+    
+    if (bReadError) {
+      ReportError(GetLastError());
+      fprintf(stderr, "Pipe error.\n");
+      CloseHandle(hPipe);
+      return EXIT_FAILURE;
+    }
+    
+    if (bBroken) {
+      printf("Pipe was closed on the other end.\n");
+      CloseHandle(hPipe);
       return EXIT_SUCCESS;
     }
     
     printf("## %s %s:%d -> %s:%d\n", packet.packetType == Packet::SEND ? "SEND" : "RECV",
-                                      packet.srcAddr, packet.srcPort, packet.dstAddr, packet.dstPort);
+      packet.srcAddr, packet.srcPort, packet.dstAddr, packet.dstPort);
     printf("   socket : %d\n", packet.socket);
-    printf("   flags : %d\n", packet.flags);
-    printf("   data (%d bytes) :\n", packet.packetLength);
+    printf("   flags  : %d\n", packet.flags);
+    printf("   size   : %d\n\n", packet.packetLength);
     
-    size_t read = 0;
+    if (!ReadPacketDataAndPrint(hPipe, packet.dataLength)) {
+      return EXIT_FAILURE;
+    }
     
-    size_t lineCount = 0;
-    
-    while (read < packet.dataLength) {
-      size_t remaining = packet.dataLength - read;
-      BOOL bResult = ReadFile(hPipe, buf, min(sizeof(buf), remaining), &dwRead, NULL);
-      if (!bResult || dwRead == 0) {
-        printf("Pipe error.\n");
-        return EXIT_SUCCESS;
-      }
-      
-      size_t count = 0;
-      while (count != dwRead) {
-        if (lineCount == 0) {
-          // Print the offset of the first byte on the line
-          fprintf(stdout, "%.8X  ", count);
-        }
-
-        fprintf(stdout, "%.2X ", buf[count]);
-        count += 1;
-        lineCount += 1;
-
-        if (lineCount == 16 || read + count == packet.dataLength) {
-          fprintf(stdout, "\n");
-          lineCount = 0;
-        }
-      }
-      
-      read += dwRead;
-    }
+    printf("\n\n");
   }
   
   return EXIT_SUCCESS;