我的 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:
从管理员帐户运行应用程序。
调用 IsUserAdmin() => 返回
TRUE
(好)调用 impersonate ("non-admin-user", "domain", "password") => 返回
FALSE
(很好!)
场景 2:
从非管理员帐户运行应用程序,使用管理员帐户的 runas.exe
。
调用 IsUserAdmin() => 返回
FALSE
(好)调用 impersonate ("administrator", "domain", "password") => 返回
FALSE
(不好!)
场景 3:
从非管理员帐户直接运行应用程序。
调用 IsUserAdmin() => 返回
FALSE
(好)调用 impersonate ("administrator", "domain", "password") => 返回
FALSE
(不好!)
所有场景都打印step 1
和step 2
。
据我所知,如果提供合法凭据,以上内容应该可以确保模拟。我在这里错过了什么?
最佳答案
在执行需要管理员权限的任务之前,您真的不应该以编程方式检查管理员权限。只需无条件地尝试任务,让 API 告诉您任务是否因权限不足而失败,如果是,那么您可以决定是让任务因错误而失败,还是提示用户输入凭据并再次尝试任务。
如果你想和 UAC 玩得开心,你应该做的是将你的管理代码实现为一个单独的进程或 COM 对象,然后你可以在需要时以提升的状态运行该进程/COM,而不必提升你的主要过程。让操作系统在操作系统需要时提示用户输入管理员凭据(并决定该提示的外观),不要自己手动执行。
关于c++ - Windows模拟的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20480402/