管理员以标准权限运行时

来源:互联网 发布:耳机品牌 知乎 编辑:程序博客网 时间:2024/05/16 02:54

在XP时代,大多数用户都用一个管理员(administrator)帐号来登录Windows
利用这个账户,用户几乎能没有任何限制的访问重要的系统资源,因为该账户被授予了很高的权限,一旦用这个帐号登录了xp以及xp之前的操作系统,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,以管理员权限重新调用自己


详细代码打包传网盘  请猛点击下面下载 (Win32 SDK)


http://dl.dbank.com/c0rcubga3h