c++ - Windows模拟的奇怪行为

标签 c++ windows winapi authentication impersonation

我的 Windows 应用程序可能需要某些部分的管理权限。 对于这些情况,我想要求用户提供管理员凭据,并使用以下代码来模拟管理员:

BOOL impersonate(LPTSTR lpszUsername, LPTSTR lpszDomain, LPTSTR lpszPassword) {

    BOOL ret = LogonUser(lpszUsername,
                         lpszDomain,
                         lpszPassword,
                         LOGON32_LOGON_INTERACTIVE,
                         LOGON32_PROVIDER_DEFAULT,
                         &hToken);
    if (ret != TRUE) return FALSE;

    OutputDebugString (L"step 1");

    ret = ImpersonateLoggedOnUser(hToken);
    if (ret != TRUE) return FALSE;

    OutputDebugString(L"step 2");

    return IsUserAdmin()
}

其中函数 IsUserAdmin() has been taken from MSDN , 如下所示:

BOOL IsUserAdmin(VOID) {
    BOOL b;
    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
    PSID AdministratorsGroup; 
    b = AllocateAndInitializeSid( &NtAuthority,
                                  2,
                                  SECURITY_BUILTIN_DOMAIN_RID,
                                  DOMAIN_ALIAS_RID_ADMINS,
                                  0, 0, 0, 0, 0, 0,
                                  &AdministratorsGroup); 
    if (b)  {
        if (!CheckTokenMembership(NULL, AdministratorsGroup, &b)) {
            b = FALSE;
        }
        FreeSid(AdministratorsGroup); 
    }

    return(b);
}

场景 1:
从管理员帐户运行应用程序。

  1. 调用 IsUserAdmin() => 返回 TRUE(好)

  2. 调用 impersonate ("non-admin-user", "domain", "password") => 返回 FALSE(很好!)

场景 2:
从非管理员帐户运行应用程序,使用管理员帐户的 runas.exe

  1. 调用 IsUserAdmin() => 返回 FALSE(好)

  2. 调用 impersonate ("administrator", "domain", "password") => 返回 FALSE(不好!)

场景 3:
从非管理员帐户直接运行应用程序。

  1. 调用 IsUserAdmin() => 返回 FALSE(好)

  2. 调用 impersonate ("administrator", "domain", "password") => 返回 FALSE(不好!)

所有场景都打印step 1step 2

据我所知,如果提供合法凭据,以上内容应该可以确保模拟。我在这里错过了什么?

最佳答案

在执行需要管理员权限的任务之前,您真的不应该以编程方式检查管理员权限。只需无条件地尝试任务,让 API 告诉您任务是否因权限不足而失败,如果是,那么您可以决定是让任务因错误而失败,还是提示用户输入凭据并再次尝试任务。

如果你想和 UAC 玩得开心,你应该做的是将你的管理代码实现为一个单独的进程或 COM 对象,然后你可以在需要时以提升的状态运行该进程/COM,而不必提升你的主要过程。让操作系统在操作系统需要时提示用户输入管理员凭据(并决定该提示的外观),不要自己手动执行。

关于c++ - Windows模拟的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20480402/

相关文章:

c++ - 套接字在非阻塞时不能接受连接?

windows - 什么 SCM 在 Windows 和 Linux 下支持符号链接(symbolic link)?

c++ - Windows C++ CMD窗口切换

c - 如何使用 Fiddle 和 Windows API (dll) 在 Ruby 中运行 shellcode

c++ - 清除循环内的 GDI 形状

java - 依赖项更改时强制类重新编译

C++ 可变在这种情况下合适吗?

c++ - 在包含数组中存在的所有元素的数组中找到最短的范围

windows - Hadoop on Windows 构建/安装错误

c++ - WinAPI - 具有自己回调的消息循环