Exemple #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);
		}
	}
}
Exemple #2
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);
		}
	}
}