How to Determine if a User is a Member of the Administrators Group with UAC Enabled on Windows Vista
User Account Control (UAC) on Windows Vista changes the paradigm of being an administrator on a Microsoft Windows operating system. Rather than wielding full administrative privileges all of the time, the token is "split" and there are two of them. If you run an application normally, it is given the token that has fewer privileges (a "standard user" token, if you will, although the Administrators group is still present and set to "deny only" so securable objects that an administrator is explicitly forbidden from accessing will still be denied to this user). If you create a process elevated, you are prompted to approve the elevation, after which the process is provided with an "unfiltered" token that grants this application full administrator credentials.
This is a huge win for security. However, it does break some of the paradigms that you may be used to using when developing applications. One example is checking to see if the user is an administrator explicitly. Most of the tools that help identify more LUA bugs (and these tools are becoming pretty indespensible now that pretty much everybody is running as a standard user the majority of the time) will flag this as a potential LUA bug. You see, this is something that can be done for good (you are checking to see if the user is an administrator to determine whether or not you want to offer them the option of launching another process elevated to provide additional functionality), and it is something that can be done for evil (you are checking to see if the user is an administrator, because it is easier just to fail than to fix the LUA bug). For now, let's assume that you are using this power for good.
If you happen to be using the handy shell32 API IsUserAnAdmin, you will find that it will return true if the process is elevated, and false if it is not. Note that the boolean return value doesn't provide you with any information that will help you determine if the user CAN elevate - it just tells you if you already have. What can you do if you want to know if the user CAN elevate, whether or not they already have?
The GetTokenInformation API provides a new ability to return a TokenElevationType structure. As of Windows Vista RC1, I do not see this documented in the Windows SDK, but you can find it in the Windows header files (winbase.h and winnt.h). So, I whipped together a little sample that you can run from the command line to determine not only whether the current process is elevated, but also whether the user happens to be a member of the administrators group:
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE hToken;
TOKEN_ELEVATION_TYPE elevationType;
DWORD dwSize;
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize);
switch (elevationType) {
case TokenElevationTypeDefault:
wprintf(TEXT("\nTokenElevationTypeDefault - User is not using a split token.\n"));
break;
case TokenElevationTypeFull:
wprintf(TEXT("\nTokenElevationTypeFull - User has a split token, and the process is running elevated.\n"));
break;
case TokenElevationTypeLimited:
wprintf(TEXT("\nTokenElevationTypeLimited - User has a split token, but the process is not running elevated.\n"));
break;
}
if (hToken) {
CloseHandle(hToken);
}
}
As you can see, it's fairly straightforward. (I have elided error handling and return value checking for clarity.) If you are looking to use this information for good, I hope this helps. If you are looking to use this information for evil, I hope you don't find this post!
Update: Note that this technique detects if the token is split or not. In the vast majority of situations, this will determine whether the user is running as an administrator. However, there are other user types with advanced permissions which may generate a split token during an interactive login (for example, the Network Configuration Operators group). If you are using one of these advanced permission groups, this technique will determine the elevation type, and not the presense (or absense) of the administrator credentials.