Акжан в сети - На уровень вверх(NT) Как проверить, имеем ли мы административные привилегии в системе?

Исходный текст -

// Routine: check if the user has administrator provileges
// Was converted from C source by Akzhan Abdulin. Not properly tested.
type
 PTOKEN_GROUPS = TOKEN_GROUPS^;

function RunningAsAdministrator (): Boolean;
var
 SystemSidAuthority: SID_IDENTIFIER_AUTHORITY = SECURITY_NT_AUTHORITY;
 psidAdmin: PSID;
 ptg: PTOKEN_GROUPS = nil;
 htkThread: Integer; { HANDLE }
 cbTokenGroups: Longint; { DWORD }
 iGroup: Longint; { DWORD }
 bAdmin: Boolean;
 
begin
  Result := false;
  if not OpenThreadToken(GetCurrentThread(),      // get security token
                         TOKEN_QUERY,
                         FALSE,
                         htkThread) then
    if GetLastError() = ERROR_NO_TOKEN then
    begin
      if not OpenProcessToken(GetCurrentProcess(),
                              TOKEN_QUERY,
                              htkThread) then
        Exit;
    end
    else
      Exit;
  if GetTokenInformation(htkThread,            // get #of groups
                         TokenGroups,
                         nil,
                         0,
                         cbTokenGroups) then
    Exit;
  if GetLastError() <> ERROR_INSUFFICIENT_BUFFER then
    Exit;
  ptg := PTOKEN_GROUPS( getmem( cbTokenGroups ) );
  if not Assigned(ptg) then
    Exit;
  if not GetTokenInformation(htkThread,           // get groups
                             TokenGroups,
                             ptg,
                             cbTokenGroups,
                             cbTokenGroups) then
    Exit;
  if not AllocateAndInitializeSid(SystemSidAuthority,
                                  2,
                                  SECURITY_BUILTIN_DOMAIN_RID,
                                  DOMAIN_ALIAS_RID_ADMINS,
                                  0, 0, 0, 0, 0, 0,
                                  psidAdmin) then
    Exit;
  iGroup := 0;
  while iGroup < ptg^.GroupCount do // check administrator group
  begin
    if EqualSid(ptg^.Groups[iGroup].Sid, psidAdmin) then
    begin
      Result := TRUE;
      break;
    end;
    Inc( iGroup );
  end;
  FreeSid(psidAdmin);
end;

Andy Nikolayev

an@megatel.msk.su
(2:5020/56)

Два метода в одном флаконе:

#include <windows.h>
#include <stdio.h>
#include <lm.h>
#pragma hdrstop

#pragma comment( lib, "netapi32.lib" )

// My thanks to Jerry Coffin (jcoffin@taeus.com)
// for this much simpler method.
bool jerry_coffin_method()
{
 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;
}

bool look_at_token_method()
{
 int found;
 DWORD i, l;
 HANDLE hTok;
 PSID pAdminSid;
 SID_IDENTIFIER_AUTHORITY ntAuth = SECURITY_NT_AUTHORITY;

 byte rawGroupList[4096];
 TOKEN_GROUPS& groupList = *( (TOKEN_GROUPS *) rawGroupList );

 if ( ! OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, FALSE, &hTok ) )
 {
  printf( "Cannot open thread token, trying process token [%lu].\n",
   GetLastError() );
  if ( ! OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hTok ) )
  {
   printf( "Cannot open process token, quitting [%lu].\n",
    GetLastError() );
   return 1;
  }
 }

 // normally, I should get the size of the group list first, but ...
 l = sizeof rawGroupList;
 if ( ! GetTokenInformation( hTok, TokenGroups, &groupList, l, &l ) )
 {
  printf( "Cannot get group list from token [%lu].\n",
   GetLastError() );
  return 1;
 }

 // here, we cobble up a SID for the Administrators group, to compare to.
 if ( ! AllocateAndInitializeSid( &ntAuth, 2, SECURITY_BUILTIN_DOMAIN_RID,
  DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSid ) )
 {
  printf( "Cannot create SID for Administrators [%lu].\n",
   GetLastError() );
  return 1;
 }

 // now, loop through groups in token and compare
 found = 0;
 for ( i = 0; i < groupList.GroupCount; ++ i )
 {
  if ( EqualSid( pAdminSid, groupList.Groups[i].Sid ) )
  {
   found = 1;
   break;
  }
 }

 FreeSid( pAdminSid );
 CloseHandle( hTok );
 return !!found;
}

int main()
{
 bool j, l;

 j = jerry_coffin_method();
 l = look_at_token_method();

 printf( "NetUserGetInfo(): The current user is %san Administrator.\n",
  j? "": "not " );
 printf( "Process token: The current user is %sa member of the Administrators group.\n",
  l? "": "not " );

 return 0;
}

//****************************************************************************//

Sergey Andyk (Сергей Андык)

asvzzz@chat.ru
(2:5005/58.43)