Esempio n. 1
0
VOID
ValidateCallAgainstRop(
	IN ULONG_PTR lpEspAddress,
	IN ROP_CALLEE RopCallee,
	IN LPVOID lpAddress, 
	IN DWORD flProtect,
	IN ULONG GeneralRegisters /* edi, esi, ebp, esp, ebx, edx, ecx, eax */
	)
{
	PNT_TIB ThreadInfo;

	if ( DbgGetRopFlag() == MCEDP_STATUS_ROP_FLAG_NOT_SET )
	{
		/* get the thread stack range from TIB. */
		ThreadInfo = (PNT_TIB) __readfsdword( 0x18 );

		/* monitor esp value if we supposed to */
		if ( MCEDP_REGCONFIG.ROP.STACK_MONITOR )
		{
			/* check if thread is passing the actual stack boundaries */
			if ( lpEspAddress < (DWORD)ThreadInfo->StackLimit || lpEspAddress >= (DWORD)ThreadInfo->StackBase ) 
			{
				/* set ROP flags */
				DbgSetRopFlag();
				DEBUG_PRINTF(LDBG,NULL,"ROP Detected by STACK_MONITOR, out of bound stack!\n");
			}
		}

		/* Monitor stack page permission change value if we supposed to */
		if ( MCEDP_REGCONFIG.MEM.STACK_RWX )
		{
			if ( lpAddress > ThreadInfo->StackLimit || lpAddress <= ThreadInfo->StackBase )
			{
				/* if it is going to make the stack executable */
				if ( ( flProtect & PAGE_EXECUTE )           ||  
						( flProtect & PAGE_EXECUTE_READWRITE ) || 
						( flProtect & PAGE_EXECUTE_READ )      ||
						( flProtect & PAGE_EXECUTE_WRITECOPY ) )
				{
					/* set ROP flag */
					DbgSetRopFlag();
					DEBUG_PRINTF(LDBG,NULL,"ROP Detected by STACK_RWX, stack permission changed to be executable!\n");
				}
			}
		}

		if ( MCEDP_REGCONFIG.ROP.PIVOT_DETECTION )
		{
			/* NOT IMPLEMENTED */
		}

		if ( MCEDP_REGCONFIG.ROP.CALL_VALIDATION )
		{
			/*
				* Performing following checks on the caller
				*  - The address of [esp - 4] could not be the starting address of current function,
				*	  otherwise this function is reached via retn instead of a call
				*	- The returning point must points to an executable space
				*  - A 'call' instruction should be existing preceeding to the returning point
				*  - Under most cases, the 'call' instruction should (in)directly points to the start
				*	  of current function
				*/

			ULONG_PTR* lpPreviousStackPointer = (ULONG_PTR*)(lpEspAddress - sizeof(ULONG));
			if(*lpPreviousStackPointer == 
				(ULONG_PTR)GetCriticalFunctionAddress(RopCallee))
			{
				/* Set ROP flag */
				DbgSetRopFlag();
				DEBUG_PRINTF(LDBG, NULL, "ROP detected by CALL_VALIDATION, "
					"the address before [esp] points to function start."
					" [esp] = 0x%x, FunctionStart = 0x%x\n", *lpPreviousStackPointer, GetCriticalFunctionAddress(RopCallee));
			}

			ULONG_PTR lpReturningAddress = *(ULONG_PTR*)lpEspAddress;
			
			// TODO: Cache it!
			MEMORY_BASIC_INFORMATION MemInfo = {0};
			if(!VirtualQuery((VOID*)lpReturningAddress, &MemInfo, sizeof(MemInfo)))
			{
				DEBUG_PRINTF(LDBG, NULL, "Error in calling VirtualQuery() in ValidateCallAgainstRop().\n");
			}
			else
			{
				if(!((MemInfo.Protect & PAGE_EXECUTE) ||
					(MemInfo.Protect & PAGE_EXECUTE_READ) ||
					(MemInfo.Protect & PAGE_EXECUTE_READWRITE) ||
					(MemInfo.Protect & PAGE_EXECUTE_WRITECOPY)))
				{
					// The target page cannot be executed
					DbgSetRopFlag();
					DEBUG_PRINTF(LDBG, NULL, "ROP detected by CALL_VALIDATION, "
						"the returning address 0x%08x cannot be executed.\n",
						lpReturningAddress);
				}
			}
			
			// Is there a call instruction preceeding to the returning address?
			if(!CheckCaller(
				lpReturningAddress, 
				TRUE,
				RopCallee, 
				&GeneralRegisters))
			{
				/* Set ROP flag */
				DbgSetRopFlag();
				DEBUG_PRINTF(LDBG, NULL, "ROP detected by CALL_VALIDATION, "
					"the returning address 0x%08x is not preceeded by a valid call instruction.\n",
					lpReturningAddress);
			}
		}

		if ( MCEDP_REGCONFIG.ROP.FORWARD_EXECUTION )
		{
			/* Start simulation from the ret of current call */
			ULONG* pGeneralRegisters = &GeneralRegisters;
			STATUS statSimulation;
			if((statSimulation = SimulateExecution(
				*(ULONG_PTR*)lpEspAddress,
				lpEspAddress, 
				GENERAL_REGISTER(R_EBP),
				GetCriticalFunctionPoppingDwordsBeforeRet(RopCallee)
				)) == MCEDP_STATUS_POSSIBLE_ROP_CHAIN)
			{
				/* Set ROP flag */
				DbgSetRopFlag();
				DEBUG_PRINTF(LDBG, NULL, "ROP detected by FORWARD_EXECUTION\n");
			}
			else if(statSimulation != MCEDP_STATUS_SUCCESS)
			{
				/* Other errors occured */
				switch(statSimulation)
				{
				case MCEDP_STATUS_INSUFFICIENT_BUFFER:
					DEBUG_PRINTF(LDBG, NULL, "FORWARD_EXECUTION returns MCEDP_STATUS_INSUFFICIENT_BUFFER, "
						"the stack space is not enough.\n");
					break;
				case MCEDP_STATUS_INTERNAL_ERROR:
					DEBUG_PRINTF(LDBG, NULL, "FORWARD_EXECUTION returns MCEDP_STATUS_INTERNAL_ERROR.\n");
					break;
				case MCEDP_ERROR_NOT_DECODABLE:
					DEBUG_PRINTF(LDBG, NULL, "FORWARD_EXECUTION returns MCEDP_ERROR_NOT_DECODABLE, "
						"we came across an undecodable instruction.\n");
					break;
				default:
					DEBUG_PRINTF(LDBG, NULL, "FORWARD_EXECUTION returns %x.\n",
						statSimulation);
					break;
				}
			}
		}

		if ( DbgGetRopFlag() == MCEDP_STATUS_ROP_FLAG_SET )
		{
			if ( MCEDP_REGCONFIG.ROP.DUMP_ROP )
				DbgReportRop((PVOID)lpEspAddress, RopCallee);

			if ( MCEDP_REGCONFIG.ROP.KILL_ROP)
				TerminateProcess(GetCurrentProcess(), STATUS_ACCESS_VIOLATION);
		}
	}
}
Esempio n. 2
0
BOOL
WINAPI
HookedCreateProcessInternalW(
	HANDLE hToken,
	LPCWSTR lpApplicationName,
	LPWSTR lpCommandLine,
	LPSECURITY_ATTRIBUTES lpProcessAttributes,
	LPSECURITY_ATTRIBUTES lpThreadAttributes,
	BOOL bInheritHandles,
	DWORD dwCreationFlags,
	LPVOID lpEnvironment,
	LPCWSTR lpCurrentDirectory,
	LPSTARTUPINFOW lpStartupInfo,
	LPPROCESS_INFORMATION lpProcessInformation,
	PHANDLE hNewToken
	)
{
	BOOL bReturn;
	CHAR szDllFullPath[MAX_PATH];

	/* apply config rules if shellcode or ROP detected */
	if ( DbgGetShellcodeFlag() == MCEDP_STATUS_SHELLCODE_FLAG_SET || DbgGetRopFlag() == MCEDP_STATUS_ROP_FLAG_SET )
	{
		if ( MCEDP_REGCONFIG.SHELLCODE.ANALYSIS_SHELLCODE )
		{
			CHAR *szApplicationNameA = (CHAR *)LocalAlloc(LMEM_ZEROINIT, 1024);
			CHAR *szCommandLineA     = (CHAR *)LocalAlloc(LMEM_ZEROINIT, 1024);
			PXMLNODE XmlLogNode;
			PXMLNODE XmlIDLogNode;

			if ( lpApplicationName != NULL )
				wcstombs( szApplicationNameA, lpApplicationName, 1024);

			if ( lpCommandLine != NULL )
				wcstombs( szCommandLineA, lpCommandLine, 1024);

			XmlIDLogNode = mxmlNewElement( XmlShellcode, "row");
			/* type */
			XmlLogNode = mxmlNewElement( XmlIDLogNode, "type");
			mxmlNewText( XmlLogNode, 0, "1");
			/* exec */
			XmlLogNode = mxmlNewElement( XmlIDLogNode, "exec_process");
			mxmlNewText( XmlLogNode, 0, szApplicationNameA);
			XmlLogNode = mxmlNewElement( XmlIDLogNode, "exec_cmd");
			mxmlNewText( XmlLogNode, 0, szCommandLineA);
			/* save */
			SaveXml( XmlLog );

			LocalFree(szApplicationNameA);
			LocalFree(szCommandLineA);
		}

        /* if malware execution is not allowd then terminate the process */
		if ( MCEDP_REGCONFIG.GENERAL.ALLOW_MALWARE_EXEC == FALSE )
			TerminateProcess(GetCurrentProcess(), STATUS_ACCESS_VIOLATION);

        /* let the malware execute */
		return (CreateProcessInternalW_( hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken));
	}
	
	/* if the process is creating with CREATE_SUSPENDED flag, let it do its job */
	if ( IsBitSet(dwCreationFlags, 2) )
	{
		bReturn = CreateProcessInternalW_( hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);

		if ( bReturn != FALSE )
		{
           
			strncpy( szDllFullPath, MCEDP_REGCONFIG.MCEDP_MODULE_PATH, MAX_PATH );
			if ( InjectDLLIntoProcess( szDllFullPath, lpProcessInformation->hProcess ) != MCEDP_STATUS_SUCCESS )
			{
				DEBUG_PRINTF(LDBG, NULL, "Module failed to inject itself into newly created process , PID : %d\n", lpProcessInformation->dwProcessId);
				return bReturn;
			}

			DEBUG_PRINTF(LDBG, NULL, "Module injected itself into newly created process , PID : %d\n", lpProcessInformation->dwProcessId);
			/* Sleep for INIT_WAIT_TIME sec and let MCEDP init itself in newly created process
			   TODO : use a messaging mechanism and resume process after init finished instead of sleeping! */
			Sleep(INIT_WAIT_TIME);
			return bReturn;
		}
	} 
	else
	{
		/* if the process is not creating with CREATE_SUSPENDED flag, force it do it */
		bReturn = CreateProcessInternalW_( hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags | CREATE_SUSPENDED , lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);
		
		if ( bReturn != FALSE )
		{
             /* TODO : We dont need this if ther process is already added into Protection List in registry, so we should remove this lines  */
			strncpy( szDllFullPath, MCEDP_REGCONFIG.MCEDP_MODULE_PATH, MAX_PATH );
			if ( InjectDLLIntoProcess( szDllFullPath, lpProcessInformation->hProcess ) != MCEDP_STATUS_SUCCESS )
			{
				DEBUG_PRINTF(LDBG, NULL, "Module failed to inject itself into newly created process , PID : %d\n", lpProcessInformation->dwProcessId);
				ResumeThread(lpProcessInformation->hThread);
				return bReturn;
			}

			DEBUG_PRINTF(LDBG, NULL, "Module injected itself into newly created process , PID : %d\n", lpProcessInformation->dwProcessId);
			/* Sleep for INIT_WAIT_TIME sec and let MCEDP init itself in newly created process
			   TODO : use a messaging mechanism and resume process after init finished instead of sleeping! */
			Sleep(INIT_WAIT_TIME);
			ResumeThread(lpProcessInformation->hThread);
			return bReturn;
		}
	}

	return bReturn;
}
Esempio n. 3
0
VOID
ValidateCallAgainstRop(
	IN ULONG_PTR lpEspAddress,
	IN ROP_CALLEE RopCallee,
	IN LPVOID lpAddress, 
	IN DWORD flProtect
	)
{
	PNT_TIB ThreadInfo;
	
	if ( DbgGetRopFlag() == MCEDP_STATUS_ROP_FLAG_NOT_SET )
	{
		/* get the thread stack range from TIB. */
		ThreadInfo = (PNT_TIB) __readfsdword( 0x18 );

		/* monitor esp value if we supposed to */
		if ( MCEDP_REGCONFIG.ROP.STACK_MONITOR )
		{
			/* check if thread is passing the actual stack boundaries */
			if ( lpEspAddress < (DWORD)ThreadInfo->StackLimit || lpEspAddress >= (DWORD)ThreadInfo->StackBase ) 
			{
				/* set ROP flags */
				DbgSetRopFlag();
				DEBUG_PRINTF(LDBG,NULL,"ROP Detected by STACK_MONITOR, out of bound stack!\n");
			}
		}

		/* Monitor stack page permission change value if we supposed to */
		if ( MCEDP_REGCONFIG.MEM.STACK_RWX )
		{
			if ( lpAddress > ThreadInfo->StackLimit || lpAddress <= ThreadInfo->StackBase )
			{
				/* if it is going to make the stack executable */
				if ( ( flProtect & PAGE_EXECUTE )           ||  
					 ( flProtect & PAGE_EXECUTE_READWRITE ) || 
					 ( flProtect & PAGE_EXECUTE_READ )      ||
					 ( flProtect & PAGE_EXECUTE_WRITECOPY ) )
				{
					/* set ROP flag */
					DbgSetRopFlag();
					DEBUG_PRINTF(LDBG,NULL,"ROP Detected by STACK_RWX, stack permission changed to be executable!\n");
				}
			}
		}

		if ( MCEDP_REGCONFIG.ROP.PIVOTE_DETECTION )
		{
			/* NOT IMPLEMENTED */
		}

		if ( MCEDP_REGCONFIG.ROP.CALL_VALIDATION )
		{
			/* NOT IMPLEMENTED */
		}

		if ( MCEDP_REGCONFIG.ROP.FORWARD_EXECUTION )
		{
			/* NOT IMPLEMENTED */
		}

		if ( DbgGetRopFlag() == MCEDP_STATUS_ROP_FLAG_SET )
		{
			if ( MCEDP_REGCONFIG.ROP.DUMP_ROP )
				DbgReportRop((PVOID)lpEspAddress,RopCallee);

			if ( MCEDP_REGCONFIG.ROP.KILL_ROP)
				TerminateProcess(GetCurrentProcess(), STATUS_ACCESS_VIOLATION);
		}
	}
}