home *** CD-ROM | disk | FTP | other *** search
/ DEFCON 15 / DefCon15.bin / Speakers / Jennings / Extras / incognito / remote_connection.c < prev    next >
C/C++ Source or Header  |  2007-03-12  |  12KB  |  378 lines

  1. #define _CRT_SECURE_NO_DEPRECATE 1
  2. #include <windows.h>
  3. #include <initguid.h>
  4. #include <stdio.h>
  5. #include <Lm.h>
  6. #include <signal.h>
  7. #include "handle_arguments.h"
  8.  
  9. #define PIPE_FORMAT        "%s\\pipe\\%s"
  10. #define PIPE_TIMEOUT    1000
  11. #define BUFSIZE            1500
  12. #define CHARS_IN_GUID    39
  13. #define MESSAGESIZE        1000
  14.  
  15. BOOL GetPhysicalPathForShare(char* szServer, char* lpszShare, char** lpszPhysicalPath, int nBufferSize);
  16. BOOL GetAvailableWriteableShare(char* szServer, int nPhysicalBufferSize, char** lplpPhysicalPath, int nUNCPathSize, char** lplpUNCPath);
  17. void connect_to_named_pipe(char *lpszServer);
  18. DWORD WINAPI ReadFromNamedPipe(LPVOID p);
  19. DWORD WINAPI WriteToNamedPipe(LPVOID p);
  20. void handle_interrupt(int signal);
  21.  
  22. static HANDLE hPipeR, hPipeW;
  23. static GUID guidPipe;
  24. static WCHAR wszGUID[CHARS_IN_GUID + 1];
  25. static char szGUID[CHARS_IN_GUID + 1], rExename[MAX_PATH];
  26. static SC_HANDLE hscm = NULL;
  27. static SC_HANDLE hsvc = NULL;
  28. static SERVICE_STATUS sStatus;
  29.  
  30. void connect_to_machine(char *server_name, char *username, char *password, int argc, char *argv[])
  31. {
  32.     DWORD i, rc;
  33.     char *szWritableShare = NULL, *szWritableSharePhysical = NULL, machineName[MAX_PATH],
  34.             resourceName[MAX_PATH], szFullServicePath[MAX_PATH], localPath[MAX_PATH], **varg;
  35.  
  36.     NETRESOURCE rec;
  37.     rec.dwType = RESOURCETYPE_DISK;
  38.     rec.lpLocalName = NULL;
  39.     rec.lpProvider = NULL;
  40.  
  41.     if (_snprintf(machineName, MAX_PATH, "\\\\%s", server_name) == -1)
  42.         machineName[sizeof(machineName)-1] = '\0';    
  43.     szWritableShare = (char*)calloc(MAX_PATH + 1, sizeof(char));
  44.     szWritableSharePhysical = (char*)calloc(MAX_PATH + 1, sizeof(char));
  45.  
  46.     // Make copies of arguments to pass to remote service
  47.     varg = (char**)calloc(argc, sizeof(char*));
  48.     for (i=1;i<(unsigned int)argc;i++)
  49.         varg[i] = argv[i];
  50.  
  51.     // Register signal handlers and get local path
  52.     signal(SIGINT, handle_interrupt);
  53.     signal(SIGTERM, handle_interrupt);
  54.     signal(SIGABRT, handle_interrupt);
  55.     GetModuleFileNameA(NULL, localPath, MAX_PATH);
  56.  
  57.     // Need to establish a connection to enumerate shares sometimes
  58.     sprintf(resourceName, "%s\\IPC$", machineName);
  59.     rec.lpRemoteName = resourceName;
  60.  
  61.     // Connect to remote host if username and password supplied
  62.     if (username && password)
  63.     {
  64.         output_string("[*] Attempting to establish new connection to %s\n", resourceName);
  65.  
  66.         WNetCancelConnection2A(rec.lpRemoteName, 0, TRUE);
  67.  
  68.         if ((rc = WNetAddConnection2A(&rec, password, username, 0)))
  69.             output_string("[-] Logon to %s failed: error %d\n", resourceName, rc);
  70.         else
  71.             output_string("[+] Logon to %s succeeded\n", resourceName);
  72.     }
  73.     else
  74.         output_string("[-] No username and password supplied\n");
  75.  
  76.     if (!GetAvailableWriteableShare(machineName, MAX_PATH, &szWritableSharePhysical, MAX_PATH, &szWritableShare))
  77.     {
  78.         output_string("[-] Unable to find writable share on %s\n", machineName);
  79.         return;
  80.     }
  81.     if (strlen(szWritableShare) <= 0 || strlen(szWritableSharePhysical) <= 0)
  82.     {
  83.         output_string("[-] Unable to find a writable share on %s\n", machineName);
  84.         return;
  85.     }
  86.     if (_snprintf(szFullServicePath, MAX_PATH,"%s\\%s", szWritableSharePhysical, "incognito_service.exe") == -1)
  87.         szFullServicePath[sizeof(szFullServicePath)-1] = '\0';
  88.  
  89.     // copy exe file to remote machine
  90.     output_string("[*] Copying service to %s\n", machineName);
  91.     strncpy(strrchr(localPath, '\\') + 1, "incognito_service.exe", MAX_PATH-1-(strrchr(localPath, '\\') + 1 - localPath));
  92.     localPath[MAX_PATH-1] = '\0';
  93.     strncpy(rExename, szWritableShare, MAX_PATH-1);
  94.     rExename[MAX_PATH-1] = '\0';
  95.     strncat(rExename, "\\incognito_service.exe", MAX_PATH-strlen(rExename));
  96.  
  97.     if (!CopyFileA(localPath, rExename, FALSE))
  98.     {
  99.         if (GetLastError() == ERROR_FILE_EXISTS)
  100.             output_string("[-] File already exists");
  101.         else 
  102.         {
  103.             output_string("[-] Couldn't copy %s to destination %s: %d\n", localPath, rExename, GetLastError());
  104.             return;
  105.         }
  106.     }
  107.     else
  108.         output_string("[+] Copied service successfully\n");
  109.  
  110.     // Need to create a guid for the pipe name
  111.     memset(wszGUID, 0, CHARS_IN_GUID + 1);
  112.     memset(szGUID, 0, CHARS_IN_GUID + 1);
  113.  
  114.     CoCreateGuid(&guidPipe);
  115.     StringFromGUID2(&guidPipe, wszGUID, CHARS_IN_GUID);
  116.     wcstombs(szGUID, wszGUID, CHARS_IN_GUID+1);
  117.  
  118.     // establish the service on remote machine
  119.     hscm = OpenSCManagerA(machineName, NULL, SC_MANAGER_CREATE_SERVICE); 
  120.  
  121.     if(!hscm)
  122.     {
  123.         output_string("[-] Failed to open service control manager\n");
  124.         return;
  125.     }
  126.  
  127.     // Create service
  128.     output_string("[*] Creating incognito service on remote host\n");
  129.     hsvc = CreateServiceA(hscm, "incognito_service", "Incognito Service", SERVICE_ALL_ACCESS, 
  130.                                 SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE,
  131.                                 szFullServicePath, NULL, NULL, NULL, NULL, NULL);
  132.  
  133.     if(!hsvc)
  134.     {
  135.         output_string("[-] Failed to create service. Attempting to open pre-existing service: %d\n", GetLastError());
  136.         hsvc = OpenServiceA(hscm, "incognito_service", SERVICE_ALL_ACCESS);
  137.         if(!hsvc)
  138.         {
  139.             output_string("[-] Failed to open service: %d\n", GetLastError());
  140.             return;
  141.         }
  142.         else 
  143.             output_string("[+] Existing service found and opened successfully\n");
  144.     }
  145.     else
  146.         output_string("[+] Created service successfully\n");
  147.  
  148.     // run service
  149.     varg[0] = szGUID;
  150.  
  151.     output_string("[*] Starting service\n");
  152.     if(!StartService(hsvc, argc, (const char**)varg))
  153.     {
  154.         output_string("[-] Service start failed: %d\n", GetLastError());
  155.         return;
  156.     }
  157.     else
  158.         output_string("[+] Service started\n");
  159.  
  160.     // Connect to named pipe
  161.     connect_to_named_pipe(machineName);        
  162.  
  163.     // when the executable is finished running, it can be deleted - clean up
  164.     while (1)
  165.     {
  166.         Sleep(100);
  167.  
  168.         if (rExename[0] != 0)
  169.             if(DeleteFileA(rExename))
  170.             {
  171.                 Sleep(100);
  172.                 output_string("\n[*] Service shutdown detected. Service executable file deleted\n");
  173.                 break;
  174.             }
  175.     }
  176.  
  177.     output_string("[*] Deleting service\n");
  178.     DeleteService(hsvc);
  179. }
  180.  
  181. static void connect_to_named_pipe(char *lpszServer)
  182. {
  183.     char szOutputBuffer[2 * MAX_PATH], szPipeName[MAX_PATH];
  184.     int nError = 2;
  185.     DWORD dwThreadId[2], dwMode;
  186.  
  187.     ZeroMemory(szPipeName, MAX_PATH);
  188.     ZeroMemory(szOutputBuffer, 2 * MAX_PATH);
  189.  
  190.     if (_snprintf(szPipeName, MAX_PATH, PIPE_FORMAT, lpszServer, szGUID) == -1)
  191.         szPipeName[sizeof(szPipeName)-1] = '\0';
  192.  
  193.     while (nError == 2)
  194.     {
  195.         BOOL bPipe;
  196.  
  197.         bPipe = WaitNamedPipeA(szPipeName, 30000);
  198.         if (!bPipe)
  199.         {
  200.             // Error 2 means the pipe is not yet available, keep trying
  201.             nError = GetLastError();
  202.             Sleep(100);
  203.         }
  204.         else
  205.             nError = 0;
  206.         break;
  207.     }
  208.  
  209.     output_string("[*] Connecting to incognito service named pipe\n");
  210.     hPipeR = CreateFileA(szPipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);    
  211.  
  212.     while(GetLastError() == ERROR_PIPE_BUSY)
  213.     { 
  214.         Sleep(100);
  215.         hPipeR = CreateFileA(szPipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);    
  216.     }
  217.  
  218.     if(hPipeR == INVALID_HANDLE_VALUE)
  219.     { 
  220.         output_string("[-] Failed to create a new client-side pipe: error %d\n", GetLastError());
  221.         return;
  222.     }
  223.  
  224.     hPipeW = CreateFileA(szPipeName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);    
  225.  
  226.     while(GetLastError() == ERROR_PIPE_BUSY)
  227.     { 
  228.         Sleep(100);
  229.         hPipeW = CreateFileA(szPipeName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);    
  230.     }
  231.  
  232.     if(hPipeW == INVALID_HANDLE_VALUE)
  233.     { 
  234.         output_string("[-] Failed to create a new client-side pipe: error %d\n", GetLastError());
  235.         return;
  236.     }
  237.  
  238.    dwMode = PIPE_READMODE_MESSAGE; 
  239.    SetNamedPipeHandleState( 
  240.       hPipeR,    // pipe handle 
  241.       &dwMode,  // new pipe mode 
  242.       NULL,     // don't set maximum bytes 
  243.       NULL);    // don't set maximum time 
  244.    SetNamedPipeHandleState( 
  245.       hPipeW,    // pipe handle 
  246.       &dwMode,  // new pipe mode 
  247.       NULL,     // don't set maximum bytes 
  248.       NULL);    // don't set maximum time 
  249.  
  250.     output_string("[+] Successfully connected to named pipe %s\n", szGUID);
  251.     output_string("[*] Redirecting I/O to remote process\n\n");
  252.  
  253.       CreateThread(
  254.         NULL,              // default security attributes
  255.         0,                 // use default stack size
  256.         ReadFromNamedPipe,        // thread function
  257.         NULL,             // argument to thread function
  258.         0,                 // use default creation flags
  259.         &dwThreadId[0]);   // returns the thread identifier
  260.  
  261.       CreateThread(
  262.         NULL,              // default security attributes
  263.         0,                 // use default stack size
  264.         WriteToNamedPipe,        // thread function
  265.         NULL,             // argument to thread function
  266.         0,                 // use default creation flags
  267.         &dwThreadId[1]);   // returns the thread identifier
  268.  
  269. }
  270.  
  271. static DWORD WINAPI ReadFromNamedPipe(LPVOID p)
  272. {
  273.     DWORD dwRead;
  274.     CHAR chBuf[BUFSIZE];
  275.  
  276.     while (1)
  277.     {
  278.         if (!ReadFile(hPipeR, chBuf, BUFSIZE, &dwRead, NULL) && GetLastError() != ERROR_MORE_DATA) 
  279.                 break;
  280.         fwrite(chBuf, sizeof(char), dwRead, OUTPUT);
  281.     }
  282.     return 0;
  283. }
  284.  
  285. static DWORD WINAPI WriteToNamedPipe(LPVOID p)
  286. {
  287.     DWORD dwRead, dwWritten;
  288.     CHAR chBuf[BUFSIZE];
  289.  
  290.     while (gets(chBuf))
  291.     {
  292.         dwRead = strlen(chBuf);
  293.         WriteFile(hPipeW, chBuf, dwRead+1, &dwWritten, NULL);
  294.     }    
  295.  
  296.     return 0;
  297. }
  298.  
  299. static void handle_interrupt(int signal)
  300. {
  301.     output_string("\n\n");
  302.     output_string("[*] Caught interrupt signal, cleaning up\n");
  303.     
  304.     output_string("[*] Stopping Service\n");
  305.     if (!ControlService(hsvc, SERVICE_CONTROL_STOP, &sStatus))
  306.         output_string("[-] Failed to stop service: %d\n", GetLastError());
  307.  
  308.     Sleep(200);
  309.  
  310.     exit(signal);
  311. }
  312.  
  313. static BOOL GetAvailableWriteableShare(char* szServer, int nPhysicalBufferSize, char** lplpPhysicalPath, int nUNCPathSize, char** lplpUNCPath)
  314. {
  315.     // Returns the drive letter if successful, otherwise 0
  316.     PSHARE_INFO_2 BufPtr, p;
  317.     NET_API_STATUS res;
  318.     DWORD er = 0, tr = 0, resume = 0, i;
  319.     wchar_t server[MAX_PATH];
  320.     char szTemp[MAX_PATH], szTemp2[MAX_PATH];
  321.     BOOL bFound = FALSE;
  322.     char szServerWithSlashes[MAX_PATH];
  323.  
  324.     ZeroMemory(server, MAX_PATH);
  325.     ZeroMemory(szServerWithSlashes, MAX_PATH);
  326.     ZeroMemory(*lplpPhysicalPath, nPhysicalBufferSize);
  327.     ZeroMemory(*lplpUNCPath, nUNCPathSize);
  328.     //_snprintf(szServerWithSlashes, MAX_PATH, "\\\\%s", szServer);
  329.     if (_snprintf(szServerWithSlashes, MAX_PATH, "%s", szServer) == -1)
  330.         szServerWithSlashes[sizeof(szServerWithSlashes)-1] = '\0';
  331.     mbstowcs(server, szServerWithSlashes, strlen(szServerWithSlashes));
  332.  
  333.     do
  334.     {
  335.         res = NetShareEnum((LPSTR)server, 2, (LPBYTE*)&BufPtr, -1, &er, &tr, &resume);
  336.         if(res == ERROR_SUCCESS || res == ERROR_MORE_DATA)
  337.         {
  338.             p = BufPtr;
  339.             for(i = 1; i <= er; i++)
  340.             {
  341.                 ZeroMemory(szTemp, MAX_PATH);
  342.                 wcstombs(szTemp, (LPWSTR)(p->shi2_netname), MAX_PATH);
  343.  
  344.                 // Look for shares that are not SYSVOL or NETLOGON, and that have a physical path 
  345.                 if (/* added admin$ fudge*/ !_stricmp(szTemp, "ADMIN$") && _stricmp(szTemp, "SYSVOL") != 0 && _stricmp(szTemp, "NETLOGON") != 0 && wcslen((LPWSTR)(p->shi2_path)) > 0)
  346.                 {
  347.                     // If this is a potentially workable share, try uploading something
  348.                     memset(szTemp2, 0, MAX_PATH);
  349.                     if (_snprintf(szTemp2, MAX_PATH, "%s\\%s", szServerWithSlashes, szTemp) == -1)
  350.                         szTemp2[sizeof(szTemp2)-1] = '\0';
  351.                     if (1/*CanUpload(szTemp2)*/)
  352.                     {
  353.                         // Success!
  354.                         // Copy the physical path to the out variable
  355.                         wcstombs(szTemp, (LPWSTR)(p->shi2_path), MAX_PATH);
  356.                         strncpy(*lplpPhysicalPath, szTemp, nPhysicalBufferSize);
  357.  
  358.                         // Also copy the UNC path to the out variable
  359.                         strncpy(*lplpUNCPath, szTemp2, nUNCPathSize);
  360.                         bFound = TRUE;
  361.                         break;
  362.                     }
  363.  
  364.                     // Otherwise continue and try another share
  365.                 }
  366.                 
  367.                 p++;
  368.             }
  369.  
  370.             NetApiBufferFree(BufPtr);
  371.         }
  372.         else 
  373.             output_string("[-] Error accessing ADMIN$ share: %ld\n",res);
  374.     }
  375.     while (res == ERROR_MORE_DATA); // end do
  376.  
  377.     return bFound;
  378. }