Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Feststellen, ob "Als Administrator" ausgeführt (https://www.delphipraxis.net/189175-feststellen-ob-als-administrator-ausgefuehrt.html)

kwhk 12. Mai 2016 11:29

Feststellen, ob "Als Administrator" ausgeführt
 
Wie kann man feststellen, ob das eigene Programm oder ein anderes mit "Als Administrator ausführen" gestartet wurde. Wenn man unter Windows 10 z.B. ein CMD-Fenster öffnet (CMD.EXE), dann wird im Titel "Administrator: Eingabeaufforderung" angezeigt. Das Programm CMD.EXE bemerkt dieses Sachverhalt.
Wie fragt man das ab ? Gibt es ein Tool, mit dem man feststellen kann, ob ein Programm so gestartet wurde oder auch nicht ?

himitsu 12. Mai 2016 12:57

AW: Feststellen, ob "Als Administrator" ausgeführt
 
Hier im Forum suchenIsAdmin?

Zitat:

Als Administrator
Und das macht man nicht :warn:
  • OK, man kann nach sehen, ob der Benutzeraccount "Administrator" heißt, aber nur weil der so heißt, muß er das nicht sein.
  • Man kann auch gucken, ob er in der Benutzergruppe "Administratoren" ist, aber man kann im dann dennoch viele Rechte weggenommen haben. Und muß zuätzlich prüfen, ob diese Rechte auch aktiv sind. (z.B. durch UAC deaktiviert)
  • Also was du wirklich willst, ist zu prüfen, ob der User-Token zu deiner laufenden Anwendung eine "bestimmte" Berechtigung enthält, welche du eigentlich benötigst.
  • Oder man versucht einfach was zu machen und wenn es nicht geht, dann fehlen Einem wohl die nötigen Rechte.

Man kann garantiert auch den Token eines fremden Programms prüfen.

p80286 12. Mai 2016 13:00

AW: Feststellen, ob "Als Administrator" ausgeführt
 
hier http://www.michael-puff.de/Programmi...kel/DACL.shtml steht eigentlich alles wichtige für den Einstieg drin. Wobei die eigentlich wichtige Frage ist, was verstehst Du unter "Administrator".

Gruß
K-H

kwhk 12. Mai 2016 13:45

AW: Feststellen, ob "Als Administrator" ausgeführt
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich meine den Sachverhalt, wenn man das Programm mit Als Administrator ausführen startet.

himitsu 12. Mai 2016 14:01

AW: Feststellen, ob "Als Administrator" ausgeführt
 
Ja, es wird mit den Rechten des/eines Adminaccounts gestartet, was aber nicht bedeutet, dass das Programm dann auch alle Rechte hat, vorallem die nicht, welche man vorher dem Admin weggenommen hat. :stupid:

Sir Rufo 12. Mai 2016 14:38

AW: Feststellen, ob "Als Administrator" ausgeführt
 
Zitat:

Zitat von himitsu (Beitrag 1338057)
Ja, es wird mit den Rechten des/eines Adminaccounts gestartet, was aber nicht bedeutet, dass das Programm dann auch alle Rechte hat, vorallem die nicht, welche man vorher dem Admin weggenommen hat. :stupid:

Der Account interessiert nur sekundär (der Accountname interessiert schon mal gar nicht). Primär wird geprüft, ob man sich in der Gruppe Administrators befindet. Dann ist man ein Administrator.

Es geht also um die Rolle.

Und die fragt man so ab:
Delphi-Quellcode:
uses
  Winapi.Windows; // <= die wird Minimum benötigt

function IsUserAdmin: Boolean;
var
  b: BOOL;
  AdministratorsGroup: PSID;
begin
  {
    This function returns true if you are currently running with admin privileges.
    In Vista and later, if you are non-elevated, this function will return false
    (you are not running with administrative privileges).
    If you *are* running elevated, then IsUserAdmin will return true, as you are
    running with admin privileges.

    Windows provides this similar function in Shell32.IsUserAnAdmin.
    But the function is deprecated, and this code is lifted
    from the docs for CheckTokenMembership:
      http://msdn.microsoft.com/en-us/library/aa376389.aspx
  }

  {
    Routine Description: This routine returns TRUE if the callers
    process is a member of the Administrators local group. Caller is NOT
    expected to be impersonating anyone and is expected to be able to
    open its own process and process token.
      Arguments: None.
      Return Value:
        TRUE - Caller has Administrators local group.
        FALSE - Caller does not have Administrators local group.
  }
  b := AllocateAndInitializeSid(
      SECURITY_NT_AUTHORITY,
      2, //2 sub-authorities
      SECURITY_BUILTIN_DOMAIN_RID, //sub-authority 0
      DOMAIN_ALIAS_RID_ADMINS,     //sub-authority 1
      0, 0, 0, 0, 0, 0,            //sub-authorities 2-7 not passed
      AdministratorsGroup);
  if (b) then
  begin
    if not CheckTokenMembership(0, AdministratorsGroup, b) then
      b := False;
      FreeSid(AdministratorsGroup);
  end;

  Result := b;
end;
(Quelle: http://stackoverflow.com/a/6319521/1744164)

Nach genauer Analyse kräuseln sich mir bei so einem Code allerdings die Fußnägel, darum hier nochmal so, wie man das machen sollte:
Delphi-Quellcode:
unit Unit3;

interface

function IsUserAdmin: Boolean;

implementation

uses
  Winapi.Windows,
  System.SysUtils;

Const
 SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
 SECURITY_BUILTIN_DOMAIN_RID = $00000020;
 DOMAIN_ALIAS_RID_ADMINS    = $00000220;
 DOMAIN_ALIAS_RID_USERS     = $00000221;
 DOMAIN_ALIAS_RID_GUESTS    = $00000222;
 DOMAIN_ALIAS_RID_POWER_USERS= $00000223;

function CheckTokenMembership(TokenHandle: THandle; SidToCheck: PSID; var IsMember: BOOL): BOOL; stdcall; external advapi32;

function IsUserAdmin: Boolean;
var
  IsMember          : BOOL;
  AdministratorsGroup: PSID;
begin
  Win32Check( AllocateAndInitializeSid(
    {} SECURITY_NT_AUTHORITY,
    {} 2,                          // 2 sub-authorities
    {} SECURITY_BUILTIN_DOMAIN_RID, // sub-authority 0
    {} DOMAIN_ALIAS_RID_ADMINS,    // sub-authority 1
    {} 0, 0, 0, 0, 0, 0,           // sub-authorities 2-7 not passed
    {} AdministratorsGroup ) );
  try
    Win32Check( CheckTokenMembership( 0, AdministratorsGroup, IsMember ) );
  finally
    FreeSid( AdministratorsGroup );
  end;
  Result := IsMember;
end;

end.
Sauber, sicher und im Ernstfall sogar kommunikativ :stupid:

Zacherl 12. Mai 2016 14:38

AW: Feststellen, ob "Als Administrator" ausgeführt
 
Zitat:

Zitat von himitsu (Beitrag 1338047)
  • Also was du wirklich willst, ist zu prüfen, ob der User-Token zu deiner laufenden Anwendung eine "bestimmte" Berechtigung enthält, welche du eigentlich benötigst.
  • Oder man versucht einfach was zu machen und wenn es nicht geht, dann fehlen Einem wohl die nötigen Rechte.

Definitiv den zweiten Ansatz wählen! Hier spart man sich alle umständlichen Checks und wenn die entsprechende API, dann ERROR_ACCESS_DENIED zurückgibt, weiß man eh direkt, wo man dran ist.

In manchen Fällen prüfe ich allerdings auch beim Programmstart, ob meine Anwendung mit einem Elevated-Token gestartet wurde, um bestimmte (kontextual weniger wichtige) Aktionen dann zu unterlassen.

@Sir Rufo:
Das ist ab Vista auch nur halb korrekt. Wenn du einen Adminaccount hast, wird das Programm auch in dessem Kontext gestartet. Standardmäßig allerdings mit dem eingeschränkten Token.

Das hier sollte seinen Dienst tun:
Delphi-Quellcode:
type
  TPrivilegeLevel = (plLimited, plAdmin, plAdminElevated);

function QueryPrivilegeLevel(const UseThreadToken: Boolean): TPrivilegeLevel;

function GetAdminSid: PSID;
const
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID: DWord            = $00000020;
  DOMAIN_ALIAS_RID_ADMINS   : DWord            = $00000220;
begin
  Result := nil;
  AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID,
    DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, Result);
end;

const
  SE_GROUP_USE_FOR_DENY_ONLY                    = $00000010;

var
  TokenHandle: THandle;
  ReturnLength: DWORD;
  TokenInformation: PTokenGroups;
  AdminSid: PSID;
  Loop: Integer;
begin
  Result := plLimited;
  if (UseThreadToken) then
  begin
    if not OpenThreadToken(GetCurrentThread, TOKEN_QUERY, true, TokenHandle) then Exit;
  end else
  begin
    if not OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, TokenHandle) then Exit;
  end;
  if (TokenHandle <> 0) then
  try
    ReturnLength := 0;
    GetTokenInformation(TokenHandle, TokenGroups, nil, 0, ReturnLength);
    TokenInformation := GetMemory(ReturnLength);
    if Assigned(TokenInformation) then
    try
      if GetTokenInformation(TokenHandle, TokenGroups, TokenInformation, ReturnLength,
        ReturnLength) then
      begin
        AdminSid := GetAdminSid;
        for Loop := 0 to TokenInformation^.GroupCount - 1 do
        begin
          if EqualSid(TokenInformation^.Groups[Loop].Sid, AdminSid) then
          begin
            if ((TokenInformation^.Groups[Loop].Attributes and SE_GROUP_USE_FOR_DENY_ONLY) =
              SE_GROUP_USE_FOR_DENY_ONLY) then
            begin
              Result := plAdmin;
            end else
            begin
              Result := plAdminElevated;
            end;
            Break;
          end;
        end;
        FreeSid(AdminSid);
      end;
    finally
      FreeMemory(TokenInformation);
    end;
  finally
    CloseHandle(TokenHandle);
  end;
end;

himitsu 12. Mai 2016 14:55

AW: Feststellen, ob "Als Administrator" ausgeführt
 
Zitat:

Zitat von Sir Rufo (Beitrag 1338058)
Und die fragt man so ab:

Wie in den verlinkten Threads zu lesen, knallt das gern mal bei DomänAdministratoren, wenn man nur lokal prüft.
Und wenn der von dir für OK befundene Administrator das nötigt Recht nicht besitzt, dann geht deine Prüfung auch schief, da sie zwar "JA, ist ein Administrator" sagt, es aber dennoch NEIN heißen müsste.

Wenn du das Programm direkt im AdminAcc startest, dann sagt das auch "der ist bei den Administratoren", aber UAC hat das Programm standardmäßig dennoch eingeschränkt. :stupid:

Und dann gibt es eventuell noch Benutzer mit den nötigen Rechten, die aber keine Administratoren sind.

Neutral General 12. Mai 2016 15:16

AW: Feststellen, ob "Als Administrator" ausgeführt
 
Es wurden schon (soweit ich das beurteilen kann) gute Antworten gepostet aber da ich noch nie mit sowas zu tun hatte habe ich mich selbst mal dran gesetzt:
Delphi-Quellcode:
function IsRunAsAdmin: Boolean;
const
  WinBuiltinAdministratorsSid = 26;
var
  sidlen: Cardinal;
  sid: PSID;
  isAdmin: BOOL;
begin
  Result := false;

  CreateWellKnownSid(WinBuiltinAdministratorsSid, nil , nil, @sidlen);
  GetMem(sid, sidlen);
  try
    if CreateWellKnownSid(WinBuiltinAdministratorsSid, nil , sid, @sidlen) then
    begin
      try
      if CheckTokenMembership(0, Sid, isAdmin) then
        Result := isAdmin;
      finally
        FreeSid(sid);
      end;
    end
  finally
    FreeMem(sid);
  end;
end;
Was ist daran schlecht/ungünstig?
Was mich auch verwirrt: Muss ich in dem Fall FreeSid aufrufen? Und wenn ja, muss ich dann auch noch FreeMem aufrufen?
Ansonsten hab ichs getestet und es scheint zumindest zu funktionieren.

Wahrscheinlich sollte ich Exceptions werfen, statt false zurückzugeben wenn eine API fehlschlägt.
Aber ansonsten müsste das doch in Ordnung sein oder?

Kritik ist erwünscht.

t.roller 12. Mai 2016 16:37

AW: Feststellen, ob "Als Administrator" ausgeführt
 
Ist ähnlich wie hier:

http://stackoverflow.com/questions/8...us-free-pascal

Delphi-Quellcode:
program TestAdmin;

{$IFDEF FPC}
  {$mode objfpc}{$H+}
{$ELSE}
  {$APPTYPE CONSOLE}
{$ENDIF}

uses
  SysUtils,
  Windows,
  Classes;

Const
 SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
 SECURITY_BUILTIN_DOMAIN_RID = $00000020;
 DOMAIN_ALIAS_RID_ADMINS    = $00000220;
 DOMAIN_ALIAS_RID_USERS     = $00000221;
 DOMAIN_ALIAS_RID_GUESTS    = $00000222;
 DOMAIN_ALIAS_RID_POWER_USERS= $00000223;

 function CheckTokenMembership(TokenHandle: THandle; SidToCheck: PSID; var IsMember: BOOL): BOOL; stdcall; external advapi32;

 function UserInGroup(Group :DWORD) : Boolean;
 var
  pIdentifierAuthority :TSIDIdentifierAuthority;
  pSid : Windows.PSID;
  IsMember   : BOOL;
 begin
  pIdentifierAuthority := SECURITY_NT_AUTHORITY;
  Result := AllocateAndInitializeSid(pIdentifierAuthority,2, SECURITY_BUILTIN_DOMAIN_RID, Group, 0, 0, 0, 0, 0, 0, pSid);
  try
    if Result then
      if not CheckTokenMembership(0, pSid, IsMember) then //passing 0 means which the function will be use the token of the calling thread.
         Result:= False
      else
         Result:=IsMember;
  finally
     FreeSid(pSid);
  end;
 end;

begin
 Writeln(Format('Current user is Admin %s',
[BoolToStr(UserInGroup(DOMAIN_ALIAS_RID_ADMINS),True)]));
 Writeln(Format('Current user is Guest %s',
[BoolToStr(UserInGroup(DOMAIN_ALIAS_RID_GUESTS),True)]));
 Writeln(Format('Current user is Power User %s',
[BoolToStr(UserInGroup(DOMAIN_ALIAS_RID_POWER_USERS),True)]));
 readln;
end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:41 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz