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.
//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:
UIA 程序设计用于代表用户与 Windows 和应用程序交互。该设置允许 UIA 程序在某些情况下绕过安全桌面以提高可用性,但允许提升请求出现在交互式桌面而不是安全桌面上,这增加了安全风险。
由于 UIA 程序必须能够响应有关安全问题的提示(如 UAC 提升提示),因此必须为 UIA 程序执行数字签名(这个exe想要可以执行的话 必须要用有效证书进行数字签名)。默认情况下,只能从以下受保护的路径运行 UIA 程序:
那么问题来了, 如何创建一个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;
}