Windows 사용자에게 관리자 권한이 있는지 여부를 조건부로 (C에서 엄격히) 검사 할 수 있습니까?Windows 사용자가 C로 관리자 권한을 가지고 있는지 확인하는 방법은 무엇입니까?
프로그래밍 방식으로이 작업을 수행하고 싶습니다. 사용자에게 "관리자 권한으로 실행"이라고 말하는 것이 아닙니다.
Windows 사용자에게 관리자 권한이 있는지 여부를 조건부로 (C에서 엄격히) 검사 할 수 있습니까?Windows 사용자가 C로 관리자 권한을 가지고 있는지 확인하는 방법은 무엇입니까?
프로그래밍 방식으로이 작업을 수행하고 싶습니다. 사용자에게 "관리자 권한으로 실행"이라고 말하는 것이 아닙니다.
물론 당신이 호출 할 필요가 :
OpenThreadToken()
는 사용자의 토큰을 얻을 수 있습니다.
GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwNeeded)
토큰 그룹 정보의 크기를 얻을 수 (충분한 공간을 할당)하려면
GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwNeeded)
AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdministrators);
은 관리자의 SID를 얻을 수있는 로컬 그룹을 얻으려면
EqualSid()
공동 mpare 귀하의 로컬 그룹에있는 SID와 SID.
근본적으로 다른 두 가지 방법이 있습니다. 가장 일반적 인 은 불행히도 다소 지루합니다. 그런 다음 그룹을 발견, 현재 사용자의 SID를 찾는 포함 그가 속한하고 그 중 하나가 Administrators 그룹인지 발견되는 :
#include <windows.h>
#include <vector>
bool is_administrator() {
HANDLE access_token;
DWORD buffer_size = 0;
PSID admin_SID;
TOKEN_GROUPS *group_token = NULL;
SID_IDENTIFIER_AUTHORITY NT_authority = SECURITY_NT_AUTHORITY;
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&access_token))
return false;
GetTokenInformation(
access_token,
TokenGroups,
group_token,
0,
&buffer_size
);
std::vector<char> buffer(buffer_size);
group_token =
reinterpret_cast<TOKEN_GROUPS*>(&buffer[0]);
bool succeeded = GetTokenInformation(
access_token,
TokenGroups,
group_token,
buffer_size,
&buffer_size
);
CloseHandle(access_token);
if (!succeeded)
return false;
if (!AllocateAndInitializeSid(
&NT_authority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0,0,0,0,0,0,
&admin_SID
))
{
return false;
}
bool found=false;
for(int i=0; !found && i < group_token->GroupCount; i++)
found = EqualSid(admin_SID,group_token->Groups[i].Sid);
FreeSid(admin_SID);
return found;
}
비록 조금 간단 다른 방법이있다 :
bool is_administrator()
{
bool result;
DWORD rc;
wchar_t user_name[256];
USER_INFO_1 *info;
DWORD size = sizeof(user_name);
GetUserNameW(user_name, &size);
rc = NetUserGetInfo(NULL, user_name, 1, (byte **) &info);
if (rc != NERR_Success)
return false;
result = info->usri1_priv == USER_PRIV_ADMIN;
NetApiBufferFree(info);
return result;
}
어느 경우 든 도메인이있는 경우 일 수 있습니다. 특정 사용자가 도메인 컴퓨터의 관리자 일 수도 있고 그 반대 일 수도 있기 때문입니다. 정보를 찾으려면 이 반드시 많이 변경되지는 않지만, 조금 생각하면 은 정말로 원하는 것을 파악할 수 있습니다.
편집 : @Benj가 지적했듯이 첫 번째 방법은 실제로 약간의 업데이트를 사용할 수 있습니다. 나는 이미 명백한 누수를 수정했지만, 예외적 인 안전성과 일반적으로 오히려 시대에 뒤 떨어진 코딩 스타일을 지닌 거대한 단일 기능입니다. 아마도 작은 업데이트를 위해이다 : (? 짧은 쉽게?)
#include <windows.h>
#include <vector>
#include <algorithm>
class sid {
PSID s;
public:
sid(SID_IDENTIFIER_AUTHORITY auth, std::vector<DWORD> sub_auths) {
DWORD count = sub_auths.size();
sub_auths.resize(7, DWORD());
if (!AllocateAndInitializeSid(
&auth,
count,
sub_auths[0], sub_auths[1], sub_auths[2], sub_auths[3],
sub_auths[4], sub_auths[5], sub_auths[6], sub_auths[7],
&s
))
{
throw std::runtime_error("Unable to allocate Admin SID");
}
}
sid(PSID const &p=NULL) : s(p) {}
bool operator==(sid const &r) const { return EqualSid(s, r.s); }
};
class access_token {
HANDLE token;
public:
access_token(HANDLE PID=GetCurrentProcess(), DWORD access=TOKEN_READ) {
if (!OpenProcessToken(PID, access, &token))
throw std::runtime_error("Unable to open process token");
}
operator HANDLE() { return token; }
~access_token() { CloseHandle(token); }
};
std::vector<sid> get_group_sids() {
DWORD buffer_size = 0;
TOKEN_GROUPS *group_token = NULL;
std::vector<sid> groups;
access_token token;
GetTokenInformation(token, TokenGroups, group_token, 0, &buffer_size);
std::vector<char> buffer(buffer_size);
group_token = reinterpret_cast<TOKEN_GROUPS*>(&buffer[0]);
if (GetTokenInformation(token, TokenGroups, group_token, buffer_size, &buffer_size))
for (int i=0; i<group_token->GroupCount; i++)
groups.push_back(group_token->Groups[i].Sid);
return groups;
}
bool is_administrator() {
std::vector<sid> groups = get_group_sids();
SID_IDENTIFIER_AUTHORITY NT_authority = SECURITY_NT_AUTHORITY;
std::vector<DWORD> sub_auths;
sub_auths.push_back(SECURITY_BUILTIN_DOMAIN_RID);
sub_auths.push_back(DOMAIN_ALIAS_RID_ADMINS);
sid admin_SID(NT_authority, sub_auths);
return std::find(groups.begin(), groups.end(), admin_SID) != groups.end();
}
#ifdef TEST
#include <iostream>
#include <iomanip>
int main() {
std::cout << std::boolalpha << is_administrator() << "\n";
}
#endif
당신은 shell32를
UAC가 설정된 Win8/10에서 IsUserAnAdmin이 Administrators 그룹의 구성원 인 사용자를 올바르게 식별하지 못합니다. – jeffm
약간 다른에서 IsUserAnAdmin를 사용해야합니다 MSDN에 몇 가지 힌트에서 적응 방법 :
PSID administrators_group = NULL;
SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY;
BOOL result = AllocateAndInitializeSid(&nt_authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &administrators_group);
BOOL is_user_admin = FALSE;
if (result)
{
CheckTokenMembership(NULL, administrators_group, &is_user_admin);
FreeSid(administrators_group);
}
if (is_user_admin)
{
// do something here for admin users...
}
테스트하지는 않았지만 UAC 사용 가능 컴퓨터에서 작동하는지 여부를 알면 UAC 권한 상승을 확인해야하며 관리자 그룹 구성원 일 필요는 없습니다. – TaterJuice
감사합니다 , 이것이 도움이되었지만, 처음에는 GetTokenInformation에 대한 첫 번째 호출이 오류를 반환한다는 것이 확인되지 않았습니다. 나는 GetLastError() == ERROR_INSUFFICIENT_MEMORY를 확인한다. – TBD
이것은 실제로 Win32 프로그래밍에서 실제로 일반적으로 사용되는 패턴입니다. API가 두 번 호출되는 것을 볼 때마다, NULL로 처음으로 첫 번째 호출이 두 번째 호출에 적합한 메모리를 할당 할 수 있도록 크기를 얻는 경우가 일반적입니다. – Benj