默认以管理员权限运行的程序如何用ShellExecute以普通权限打开URL
高权限进程以普通权限调用ShellExecute打开URL的实现方案
ShellExecute 内置runas参数,可用于申请UAC提升权限启动进程,该参数的作用说明如下:
以管理员身份启动应用程序,用户账户控制(UAC)将提示用户同意提升权限运行应用,或输入用于运行该应用的管理员账户凭据。
当前存在反向需求:本身已默认以提升权限运行的应用,需要支持用户点击触发打开URL的操作。如果直接调用ShellExecute,会继承当前进程的高权限启动系统默认浏览器,存在恶意程序被注册为默认浏览器后拿到高权限执行恶意操作的安全隐患。
此前同类需求的验证结论表明CreateProcessAsUser无法直接用于打开URL,可通过模拟普通用户上下文的方案实现需求,具体实现步骤如下:
实现步骤
- 获取当前活动普通用户的令牌
先通过WTSGetActiveConsoleSessionId获取当前登录用户的会话ID,再调用WTSQueryUserToken获取该会话对应的未提升普通用户权限令牌,不使用当前高权限进程自身的令牌。 - 模拟普通用户环境调用ShellExecute
调用ImpersonateLoggedOnUser接口,使用上一步获取的普通用户令牌模拟用户登录状态,在该状态下调用ShellExecute打开目标URL,此时启动的默认浏览器会继承普通用户的权限,不会拿到当前进程的高权限。 - 清理模拟状态
URL调用完成后,调用RevertToSelf接口终止用户模拟,恢复进程原有高权限状态,避免影响后续其他功能的正常运行。
注意事项
- 调用
WTSQueryUserToken需要进程持有SE_TCB_NAME特权,本身以高权限运行的进程默认已持有该特权,无需额外申请。 - 该方案兼容性较强,不需要篡改当前进程的自身权限,不会引发系统资源访问异常的问题。
- 若需兼容Windows 7及更早版本系统,需要额外处理会话0隔离的特殊场景,对会话ID为0的情况做兼容判断。
内容的提问来源于stack exchange,提问作者Sergey Kolesnik
相关产品推荐
相关产品推荐

