管理员以标准用户权限运行时

本文深入探讨了用户账户控制(UAC)技术在应用程序开发中的影响,详细解释了如何通过各种方法提升应用程序权限,包括右键菜单选项、manifest文件配置、属性对话框、手动提升权限以及使用ShellExecuteEx函数实现。同时介绍了如何在按钮上显示盾牌图标以提示提升权限的需求,并提供了实际应用代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里介绍一个对于应用程序开发人员影响最大的技术:用户账户控制(UAC)

Windows操作系统会创建一个安全令牌(security token).每当有代码试图访问一个受保护的安全资源时时,操作系统就会使用(出示)这个安全令牌,

从Windows在内的第一个进程开始,这个令牌会与新建的所有进程关联,这样如果新下载了一个恶意程序,就会继承管理员的高权限,------因此可以肆无忌惮的修改机器上的任何内容,甚至启动同一个高特权的进程

那么从vista开始,如果用户使用管理员帐号来登录这样一个被授予高特权的账户登录,那么除了与这个账户登录对应的安全令牌之外,还会创建一个进过筛选的令牌(filtered token)后者只给标准用户的权限(Standard User).以后包括Windows资源管理器在内的第一个进程开始,这个筛选后的令牌会与系统表示最终用户启动启动的所有新进程关联,权限受限制的进程无法访问需要更高权限才能访问的安全资源.

下面介绍如何提升权限:

----------------------------------------------------------------------------------------------

首先,我们可以要求操作系统提升权限,但只能是进程边界提升权限

(1)单击右键 Run As Administrator
如果应用程序是操作系统的一部分  那么会显示一个蓝色的横幅
如果引用程序进行了签名,对话框中将显示一个灰色的横幅,表明Windows没有足够的把握来确定应用程序是安全了
如果应用程序没有进行签名,系统会在对话框中显示一个橙色的横幅,并且要求用户谨慎回答
如果用户没有以一个管理员帐号来登录系统,那么Windows会弹出一个要求用户输入管理员权限的帐号密码,这样应用程序才能以管理员权限来运行,这被称为over-the-shoulder登录

(2)manifest文件

  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="highestAvailable"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>


如上   被称为一种特殊的资源RT_MANIFEST特殊资源,将其编译到exe资源节区中,系统会按照requestedExecutionLevel节来判断进程的权限,并执行一些操作

requireAdministrator -->应用程序必须以管理员权限启动,否则不会运行
highestAvailable-->应用程序以当前可用的最高权限运行
                        -->如果用户使用管理员帐号登录,就会出现一个要求批准提升权限的对话框
                        -->如果用户使用普通用户账户登录系统,就使用标准权限来启动
asInvoker         -->应用程序以主调应用程序一样的权限来启动

(3).还可以在应用程序的属性对话框中选中对应的复选框

(4)手动提升权限进程的权限
在CreateProcess函数中,没有专门提供神马标记参数来指定对这种权限的提升
相反,我们可以调用ShellExecuteEx函数

BOOL ShellExecuteEx(
    LPSHELLEXECUTEINFO lpExecInfo
);

typedef struct _SHELLEXECUTEINFO{
    DWORD cbSize;
    ULONG fMask;
    HWND hwnd;
    LPCTSTR lpVerb;
    LPCTSTR lpFile;
    LPCTSTR lpParameters;
    LPCTSTR lpDirectory;
    int nShow;
    HINSTANCE hInstApp;
 
    // Optional members
    LPVOID lpIDList;
    LPCSTR lpClass;
    HKEY hkeyClass;
    DWORD dwHotKey;
 union {
  HANDLE hIcon;
  HANDLE hMonitor;
 };
    HANDLE hProcess;
} SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;

这个结构体唯一有趣的2个字段是lpVerb和lpFile,前者必须被设置为"runas",后者必须包含使用提升后的权限来启动的一个可执行文件的路径,如下代码:

SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)};
sei.lpVerb = TEXT("runas");
sei.lpFile = TEXT("cmd.exe");
sei.nShow = SW_NORMAL;
if (!ShellExecuteEx(&sei))
{
 DWORD dwStatus = GetLastError();
 if (dwStatus == ERROR_CANCELLED)
 {
  printf("没有以管理员权限运行");
 }
 else
  if(dwStatus == ERROR_FILE_NOT_FOUND)
 {
  printf("没有找到该文件");
 }
}

如果用户拒绝提升权限ShellExecuteEx会返回FALSE,可以通过GetLastError()使用一个ERROR_CANCELLED值来指出这种情况

注意当一个进程使用一个提升后的权限启动时,它每次使用CreateProcess来生成另一个进程时,子进程都会获取和它父进程一样的提升后的权限,假如一个应用程序是使用一个筛选后的令牌来运行的,那么一旦试图调用CreateProcess来生成一个要求提升权限的可执行文件,这个调用就会失败,GetLastError会返回ERROR_ELFVATION_REQUIRED

(5)按钮上显示一个盾牌图标

①.首先我们需要解决的事情是获取当前进程是否以管理员权限运行的.
②.Button_SetElevationRequiredState宏可以帮助我们来设置或者隐藏小盾牌图标
实质上是:
#define Button_SetElevationRequiredState(hwnd, fRequired) (LRESULT)SNDMSG((hwnd), BCM_SETSHIELD, 0, (LPARAM)fRequired)
SendMessage((hwnd), BCM_SETSHIELD, 0, (LPARAM)fRequired);
SendMessage(hwnd, 0x160C, 0, 0xFFFFFFFF);
③.在按钮点击事件中使用ShellExecuteEx,以管理员权限重新调用自己

原文出处:来自百度互联网

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值