在 Windows 上,用户对权限并不敏感,可能最为直观的是 UAC ,但相信很多人已经关掉了它的提示。
但其实安全性早已深入了 Windows 的方方面面。Windows Vista 引入了一个称为强制完整性控制(Mandatory Integrity Controls,MIC)的新安全结构,类似于 Linux/Unix 中可用的完整性功能。在 Windows Vista 以及后续版本如Windows 11/10和Windows 8/7中,所有安全主体(用户、计算机、服务等)和对象(文件、注册表键、文件夹和资源)都被赋予MIC标签。
权限由高到低分别为Low、Medium、High、System。
如果登录用户是管理员账户,且开启了UAC,那么默认情况下双击一个程序时是以medium权限运行,称为受限的管理员权限,如果右键程序“以管理员权限运行”,那么程序是high权限,称为不受限的管理员权限。Low权限很少见,浏览器的某些进程就是Low权限的。Windows服务一般是System权限。
创建进程
当用户尝试启动可执行文件时,会使用最低用户完整性级别和文件完整性级别创建新进程。 这意味着新进程永远不会以比可执行文件更高的完整性执行。 如果管理员用户执行低完整性程序,则新进程的令牌会以低完整性级别运行。
简单来说,进程启动的子进程,默认情况下权限只会等于或小于其父进程。
如何以编程方式控制进程的执行级别?当用户启动应用程序时,其提升级别由其清单中 requestedExecutionLevel 属性的值确定,Windows 的用户帐户控制 (UAC) 会根据它采取适当的操作(例如,在需要时显示提升提示等)。但是,如果应用程序需要启动与应用程序本身执行级别不同的新进程,该怎么办?
获取当前进程执行级别
通过 GetTokenInformation 即可获取 TOKEN_ELEVATION_TYPE。
HANDLE hToken = NULL;
TOKEN_ELEVATION_TYPE tet_{};
if (::OpenProcessToken(
::GetCurrentProcess(),
TOKEN_QUERY,
&hToken))
{
DWORD dwReturnLength = 0;
if (::GetTokenInformation(
hToken,
TokenElevationType,
&tet_,
sizeof(*ptet),
&dwReturnLength)) {
//
}
}
::CloseHandle(hToken);
TOKEN_ELEVATION_TYPE 的取值分别是:
TokenElevationTypeDefault The token does not have a linked token.
UAC 已禁用,或者进程由标准用户(不是 Administrators 组的成员)启动。
TokenElevationTypeFull The token is an elevated token.
进程正在提升运行。
TokenElevationTypeLimited The token is a limited token.
进程未提升运行。
仅当 UAC 都已启用且用户是管理员组的成员(即用户具有“拆分”令牌)时,才能返回最后两个值。
提权
有的时候我们需要子进程以较高的权限执行以完成其功能。于是,我们需要提升子进程的权限。
以产品更新为例,大部分时候产品主程序以在标准(非提升)级别运行,为了能够自我更新,它需要启动一个单独的更新进程,该更新进程需要提升才能正确执行升级。在这种情况下,非提升进程需要启动新的提升进程,则需要提权。
提升到管理员权限
ShellExecute
很简单,通过 ShellExecute ,将 lpOperation 参数设置为 "runas" 即可
HINSTANCE hRet = ::ShellExecute(NULL, L"runas", pszFileName, NULL, NULL, SW_SHOWNORMAL);
if (32 < (DWORD)hRet)
{
return TRUE;
}
return FALSE;
当然,如果当前用户不属于管理员组,则会弹出 UAC 提示 -- 我们并不是为了绕过系统限制,仅仅是合理的请求高权限执行。
提升到 System 权限
PsExec 工具
PsExec 是一个轻量级的 telnet-replacement,允许您在其他系统上执行进程。PsExec 最强大的用途包括在远程系统上启动交互式命令提示符。
<