AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) C++ Administratorrechte anfordern (Elevation/Impersonation ?)
Thema durchsuchen
Ansicht
Themen-Optionen

Administratorrechte anfordern (Elevation/Impersonation ?)

Ein Thema von OregonGhost · begonnen am 30. Mai 2007 · letzter Beitrag vom 17. Nov 2016
Antwort Antwort
NicoDE
(Gast)

n/a Beiträge
 
#1

Re: Administratorrechte anfordern (Elevation/Impersonation ?

  Alt 1. Jun 2007, 14:29
Zitat von OregonGhost:
oder hoffen, dass NicoDE seine Wrapper-Funktionen findet
Die Hoffnung stirbt zuletzt
(sind genauso zu verwenden wie die API-Funktionen - die Fallbacks dürften auch das gleiche machen wie die jeweilige API *g*)
Delphi-Quellcode:
unit TokenTools;

interface

uses
  Windows;

function CheckTokenMembership(TokenHandle: THandle; SidToCheck: PSID;
  out IsMember: BOOL): BOOL; stdcall;
function SHTestTokenMembership(hToken: THandle; ulRID: ULONG): BOOL; stdcall;
function IsUserAnAdmin(): BOOL; stdcall;

implementation

function GetAdvApi32Lib(): HMODULE;
const
  ModuleName = 'ADVAPI32';
{$WRITEABLECONST ON}
const
  ModuleHandle: HMODULE = HMODULE(nil);
{$WRITEABLECONST OFF}
begin
  Result := ModuleHandle;
  if Result = HMODULE(nil) then
  begin
    Result := LoadLibrary(ModuleName);
    if Result <> HMODULE(nil) then
      ModuleHandle := Result;
  end;
end;

function CheckTokenMembership(TokenHandle: THandle; SidToCheck: PSID;
  out IsMember: BOOL): BOOL;
type
  TFNCheckTokenMembership = function(TokenHandle: THandle; SidToCheck: PSID;
    out IsMember: BOOL): BOOL; stdcall;
{$WRITEABLECONST ON}
const
  Initialized: Integer = 0;
  RealApiFunc: TFNCheckTokenMembership = nil;
{$WRITEABLECONST OFF}
type
  TAceHeader = packed record
    AceType : Byte;
    AceFlags: Byte;
    AceSize : Word;
  end;
  TAccessAllowedAce = packed record
    Header : TAceHeader;
    Mask : ACCESS_MASK;
    SidStart: DWORD;
  end;
const
  ACL_REVISION = 2;
  DesiredAccess = 1;
  GenericMapping: TGenericMapping = (
    GenericRead : STANDARD_RIGHTS_READ;
    GenericWrite : STANDARD_RIGHTS_WRITE;
    GenericExecute: STANDARD_RIGHTS_EXECUTE;
    GenericAll : STANDARD_RIGHTS_ALL
  );
var
  ClientToken: THandle;
  ProcessToken: THandle;
  SecurityDescriptorSize: Cardinal;
  SecurityDescriptor: PSecurityDescriptor;
  Dacl: PACL;
  PrivilegeSetBufferSize: ULONG;
  PrivilegeSetBuffer: packed record
    PrivilegeSet: TPrivilegeSet;
    Buffer: array [0..2] of TLUIDAndAttributes;
  end;
  GrantedAccess: ACCESS_MASK;
  AccessStatus: BOOL;
begin
  if Initialized = 0 then
  begin
    RealApiFunc := TFNCheckTokenMembership(
      GetProcAddress(GetAdvApi32Lib(), 'CheckTokenMembership'));
    InterlockedIncrement(Initialized);
  end;
  if Assigned(RealApiFunc) then
    Result := RealApiFunc(TokenHandle, SidToCheck, IsMember)
  else
  begin
    Result := False;
    IsMember := False;
    ClientToken := THandle(nil);
    try
      if TokenHandle <> THandle(nil) then
        ClientToken := TokenHandle
      else if not OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, False,
        ClientToken) then
      begin
        ClientToken := THandle(nil);
        if GetLastError() = ERROR_NO_TOKEN then
        begin
          if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY or
            TOKEN_DUPLICATE, ProcessToken) then
          try
            if not DuplicateToken(ProcessToken, SecurityImpersonation,
              @ClientToken) then
            begin
              ClientToken := THandle(nil);
            end;
          finally
            CloseHandle(ProcessToken);
          end;
        end;
      end;
      if ClientToken <> THandle(nil) then
      begin
        SecurityDescriptorSize := SizeOf(TSecurityDescriptor) +
          SizeOf(TAccessAllowedAce) + SizeOf(TACL) +
          3 * GetLengthSid(SidToCheck);
        SecurityDescriptor := PSecurityDescriptor(
          LocalAlloc(LMEM_ZEROINIT, SecurityDescriptorSize));
        if SecurityDescriptor <> nil then
        try
          if InitializeSecurityDescriptor(SecurityDescriptor,
            SECURITY_DESCRIPTOR_REVISION) then
          begin
            if SetSecurityDescriptorOwner(SecurityDescriptor, SidToCheck,
              False) then
            begin
              if SetSecurityDescriptorGroup(SecurityDescriptor, SidToCheck,
                False) then
              begin
                Dacl := PACL(SecurityDescriptor);
                Inc(PSecurityDescriptor(Dacl));
                if InitializeAcl(Dacl^,
                  SecurityDescriptorSize - SizeOf(TSecurityDescriptor),
                  ACL_REVISION) then
                begin
                  if AddAccessAllowedAce(Dacl^, ACL_REVISION, DesiredAccess,
                    SidToCheck) then
                  begin
                    if SetSecurityDescriptorDacl(SecurityDescriptor, True, Dacl,
                      False) then
                    begin
                      PrivilegeSetBufferSize := SizeOf(PrivilegeSetBuffer);
                      Result := AccessCheck(SecurityDescriptor, ClientToken,
                        DesiredAccess, GenericMapping,
                        PrivilegeSetBuffer.PrivilegeSet, PrivilegeSetBufferSize,
                        GrantedAccess, AccessStatus);
                      if Result then
                        IsMember := AccessStatus and
                          (GrantedAccess = DesiredAccess);
                    end;
                  end;
                end;
              end;
            end;
          end;
        finally
          LocalFree(HLOCAL(SecurityDescriptor));
        end;
      end;
    finally
      if (ClientToken <> THandle(nil)) and
        (ClientToken <> TokenHandle) then
      begin
        CloseHandle(ClientToken);
      end;
    end;
  end;
end;

function GetShell32Lib(): HMODULE;
const
  ModuleName = 'SHELL32';
{$WRITEABLECONST ON}
const
  ModuleHandle: HMODULE = HMODULE(nil);
{$WRITEABLECONST OFF}
begin
  Result := ModuleHandle;
  if Result = HMODULE(nil) then
  begin
    Result := LoadLibrary(ModuleName);
    if Result <> HMODULE(nil) then
      ModuleHandle := Result;
  end;
end;

function SHTestTokenMembership(hToken: THandle; ulRID: ULONG): BOOL; stdcall;
type
  TFNSHTestTokenMembership = function(hToken: THandle; ulRID: ULONG): BOOL; stdcall;
{$WRITEABLECONST ON}
const
  Initialized: Integer = 0;
  RealApiFunc: TFNSHTestTokenMembership = nil;
{$WRITEABLECONST OFF}
const
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID = $00000020;
var
  SidToCheck: PSID;
begin
  if Initialized = 0 then
  begin
    RealApiFunc := TFNSHTestTokenMembership(
      GetProcAddress(GetShell32Lib(), 'SHTestTokenMembership'));
    InterlockedIncrement(Initialized);
  end;
  if Assigned(RealApiFunc) then
    Result := RealApiFunc(hToken, ulRID)
  else
  begin
    Result := AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
      SECURITY_BUILTIN_DOMAIN_RID, ulRID, 0, 0, 0, 0, 0, 0, SidToCheck);
    if Result then
    try
      if not CheckTokenMembership(THandle(nil), SidToCheck, Result) then
        Result := False;
    finally
      FreeSid(SidToCheck);
    end;
  end;
end;

function IsUserAnAdmin(): BOOL;
const
  DOMAIN_ALIAS_RID_ADMINS = $00000220;
type
  TFNIsUserAnAdmin = function(): BOOL; stdcall;
{$WRITEABLECONST ON}
const
  Initialized: Integer = 0;
  RealApiFunc: TFNIsUserAnAdmin = nil;
{$WRITEABLECONST OFF}
begin
  if Initialized = 0 then
  begin
    RealApiFunc := TFNIsUserAnAdmin(
      GetProcAddress(GetShell32Lib(), 'IsUserAnAdmin'));
    InterlockedIncrement(Initialized);
  end;
  if Assigned(RealApiFunc) then
    Result := RealApiFunc()
  else
    Result := SHTestTokenMembership(THandle(nil), DOMAIN_ALIAS_RID_ADMINS);
end;

end.
ps: Die von Luckie kopierte IsAdmin-Funktion enthält den klassischen Fehler (es wurde vergessen zu prüfen, ob die aktuelle Sid überhaupt im Token aktiviert ist).
pps: upz, da war aber noch nen blöder Fehler drin *g*
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#2

AW: Re: Administratorrechte anfordern (Elevation/Impersonation ?

  Alt 24. Sep 2015, 20:21
Liebe Leute, bitte verzeiht mir, daß ich diese "Asbach-Diskussion" reanimiere.

ps: Die von Luckie kopierte IsAdmin-Funktion enthält den klassischen Fehler (es wurde vergessen zu prüfen, ob die aktuelle Sid überhaupt im Token aktiviert ist).
Von der simplen IsAdmin-Funktion, von der Luckie hier eine veröffentlichte, sind einige - einander ziemlich ähnliche - Versionen im Netz aufzuspüren.

Auch wenn sie genaugenommen fehlerhaft sein mag, so hat sie (bei mir jedenfalls) bisher immer das gewünschte, also korrekte Ergebnis geliefert. Tut sie das aber immer? Falls, ja, dann ist sie "phänomenologisch" eben doch richtig. Oder sind Konstellationen möglich (nichtaktivierte SID im Token?), bei der ihre Fehlerhaftigkeit eben doch durchschlägt?
  Mit Zitat antworten Zitat
Benutzerbild von NicoDE
NicoDE

Registriert seit: 16. Jul 2012
Ort: Darmstadt
26 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Re: Administratorrechte anfordern (Elevation/Impersonation ?

  Alt 17. Nov 2016, 10:51
Auch wenn sie genaugenommen fehlerhaft sein mag, so hat sie (bei mir jedenfalls) bisher immer das gewünschte, also korrekte Ergebnis geliefert.
Das gewünschte Ergebnis hängt von der Fragestellung ab
Es macht einen erheblichen Unterschied, ob ich im aktuellen Kontext administrative Rechte habe oder haben könnte.
Im letzteren Fall würde man eher etwas wie "IsUserInAdminGroup" im UAC self-elevation (CppUACSelfElevation)-Beispielprojekt von Microsoft schreiben.
Nico Bendlin
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:48 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz