Windows Application UIAccess

Windows Application UIAccess
windows Vista之后 应用程序引入了一个新的属性UIAccess。

UIAccess for UI automation applications

Microsoft UI automation is the Windows Vista model to support accessibility requirements with improvements over the earlier model, known as Microsoft Active Accessibility (MSAA). Applications designed to support accessible user experience control the behavior of other Windows applications on behalf of the user. When all applications (the automation client and server) are running as a standard user, that is, at a medium integrity level, the UIPI restrictions do not interfere with the UI automation model.

However, there may be times when an administrative user runs an application with elevated privilege based on UAC in Admin Approval Mode. The UI automation program will not be able to drive the graphics UI of elevated applications on the desktop without the ability to bypass restrictions that UIPI implements. The ability to bypass UIPI restrictions on SendMessage across privilege levels is available for UI automation programs using a special security attribute in the program’s application manifest, known asUIAccess.

The following is an example of an application manifest entry for a UIAccess program.

 
   
     
     
     
   


我们可以再project的属性里面找到它:
如下图
Windows Application UIAccess_第1张图片

这个属性到底有什么作用呢?
用户帐户控制:允许 UIAccess 应用程序在提升时进行提示,而无需使用安全桌面
简单来说就是提高应用程序UI处理方面的权限
比如发送窗口消息给以管理员权限在运行的进程,模拟按键发送给其他窗口等等。
比如以下代码
//Ctrl+C
	/*keybd_event(VK_CONTROL,0,0,0);
	keybd_event(_T('C'), 0, 0, 0);
	Sleep(50);
	keybd_event(_T('C'), 0, KEYEVENTF_KEYUP, 0);
	keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
	*/

A process that is launched with UIAccess rights:

  • Has the ability to set the foreground window.
  • Can drive any application window using SendInput function.
  • Has read input for all integrity levels using low-level hooks, raw input, GetKeyState, GetAsyncKeyState, and GetKeyboardInput.
  • Can set journal hooks.
  • Uses AttachThreadInput to attach a thread to a higher integrity input queue

注意

UIA 程序设计用于代表用户与 Windows 和应用程序交互。该设置允许 UIA 程序在某些情况下绕过安全桌面以提高可用性,但允许提升请求出现在交互式桌面而不是安全桌面上,这增加了安全风险。

由于 UIA 程序必须能够响应有关安全问题的提示(如 UAC 提升提示),因此必须为 UIA 程序执行数字签名(这个exe想要可以执行的话 必须要用有效证书进行数字签名)。默认情况下,只能从以下受保护的路径运行 UIA 程序:

  • …\Program Files(包括子文件夹)

  • …\Program Files (x86)(包括与 64 位版本的 Windows 对应的子文件夹)

  • …\Windows\System32
UIA 程序设计用于代表用户与 Windows 和应用程序交互。该设置允许 UIA 程序在某些情况下绕过安全桌面以提高可用性,但允许提升请求出现在交互式桌面而不是安全桌面上,这增加了安全风险。

Applications that are launched with UIAccess rights for a standard user are assigned a slightly higher integrity level value in the access token. The access token integrity level for the UIAccess application for a standard user is the value of medium integrity level, plus an increment of 0x10. The higher integrity level for UIAccess applications prevents other processes on the same desktop at the medium integrity level from opening the UIAccess process object.

这里面提到了integrity level 可以参考以下文献
可以通过process exploer 工具来查看
Windows Application UIAccess_第2张图片

Windows Integrity Mechanism Design

那么问题来了, 如何创建一个integrity level 低于自己的process 呢?

有的时候我们需要创建一个子进程,但是我们不需要它拥有父进程的这些“权利”

可参考如下代码

BOOL CreateLowProcess(LPCTSTR lpFile, LPTSTR lpParam)
{

	BOOL                  fRet;
	HANDLE                hToken = NULL;
	HANDLE                hNewToken = NULL;
	PSID                  pIntegritySid = NULL;
	TOKEN_MANDATORY_LABEL TIL = { 0 };
	PROCESS_INFORMATION   ProcInfo = { 0 };
	STARTUPINFO           StartupInfo = { 0 };

	// Notepad is used as an example
	TCHAR szProcessName[MAX_PATH] = { 0 };
	StringCchPrintf(szProcessName, RTL_NUMBER_OF(szProcessName), lpFile);

	// Low integrity SID
	TCHAR szIntegritySid[20] = _T("S-1-16-4096");
	//PSID pIntegritySid = NULL;

	fRet = OpenProcessToken(GetCurrentProcess(),
		TOKEN_DUPLICATE |
		TOKEN_ADJUST_DEFAULT |
		TOKEN_QUERY |
		TOKEN_ASSIGN_PRIMARY,
		&hToken);

	if (!fRet)
	{
		goto CleanExit;
	}

	fRet = DuplicateTokenEx(hToken,
		0,
		NULL,
		SecurityImpersonation,
		TokenPrimary,
		&hNewToken);

	if (!fRet)
	{
		goto CleanExit;
	}

	fRet = ConvertStringSidToSid(szIntegritySid, &pIntegritySid);

	if (!fRet)
	{
		goto CleanExit;
	}

	TIL.Label.Attributes = SE_GROUP_INTEGRITY;
	TIL.Label.Sid = pIntegritySid;

	//
	// Set the process integrity level
	//

	fRet = SetTokenInformation(hNewToken,
		TokenIntegrityLevel,
		&TIL,
		sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(pIntegritySid));

	if (!fRet)
	{
		goto CleanExit;
	}

	//
	// Create the new process at Low integrity
	//

	//fRet = MyCreateProcessAsUser(hNewToken, szProcessName, lpParam);
	DWORD dwSessionID = WTSGetActiveConsoleSessionId();
	StartupInfo.cb = sizeof(STARTUPINFO);
	StartupInfo.lpDesktop = L"WinSta0\\Default";
	StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
	StartupInfo.wShowWindow = SW_SHOWNORMAL;

	fRet = ::CreateProcessAsUser(hNewToken,
		szProcessName,
		lpParam,
		NULL,
		NULL,
		FALSE,
		0,
		NULL,
		NULL,
		&StartupInfo,
		&ProcInfo);

CleanExit:

	if (ProcInfo.hProcess != NULL)
	{
		CloseHandle(ProcInfo.hProcess);
	}

	if (ProcInfo.hThread != NULL)
	{
		CloseHandle(ProcInfo.hThread);
	}

	LocalFree(pIntegritySid);

	if (hNewToken != NULL)
	{
		CloseHandle(hNewToken);
	}

	if (hToken != NULL)
	{
		CloseHandle(hToken);
	}

	return fRet;
}

修改自MSDN的例子,那个例子有些过时了。

代码出处


你可能感兴趣的:(C++)