2016-11-04 4 views
5

Sobald Sie eine Anwendung mit Administratorberechtigung gestartet haben, erben Programme, die in dieser Anwendung unter Verwendung von ShellExecute ausgeführt werden, die Administratorberechtigung. Aber das ist nicht das, was ich will: Es muss nur regelmäßig ohne die zusätzlichen Berechtigungen gestartet werden. ShellExecute akzeptiert die Parameter OPEN (normal) und RUNAS (Administrator). Aber wenn Sie OPEN verwenden, nachdem Sie die Anwendung als Administrator gestartet haben, verhält es sich immer noch wie RUNAS.Starten Sie die Anwendung ohne Administratorrechte

Das folgende Beispiel zeigt dies: Wenn Sie es mit regulären Berechtigungen starten, heißt es "Starte regulär". Sobald Sie 1 für 'admin' drücken, wird es als Administrator gestartet. Wenn Sie in der neu erstellten Eingabeaufforderung 2 drücken, wird keine "normale" Eingabeaufforderung gestartet, sondern erneut die Eingabeaufforderung "Administrator".

Ich habe etwas über einige Parameter in RUNAS (https://superuser.com/a/374866) gefunden, aber sie können nicht in ShellExecute übergeben werden. Irgendwelche Ideen?

program WindowsPrivilegeTest; 
{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils, 
    Winapi.Windows, 
    Winapi.ShellAPI; 

function CheckTokenMembership(TokenHandle: THANDLE; SidToCheck: Pointer; var 
    IsMember: BOOL): BOOL; stdcall; external advapi32 name 'CheckTokenMembership'; 

// Source: http://stackoverflow.com/a/28572886/1870208 
function IsAdministrator: Boolean; 
var 
    psidAdmin: Pointer; 
    B: BOOL; 
const 
    SECURITY_NT_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5)); 
    SECURITY_BUILTIN_DOMAIN_RID = $00000020; 
    DOMAIN_ALIAS_RID_ADMINS  = $00000220; 
    SE_GROUP_USE_FOR_DENY_ONLY = $00000010; 
begin 
    psidAdmin := nil; 
    try 
    Win32Check(AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, 
     SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, 
     psidAdmin)); 

    if CheckTokenMembership(0, psidAdmin, B) then 
     Result := B 
    else 
     Result := False; 
    finally 
    if psidAdmin <> nil then 
     FreeSid(psidAdmin); 
    end; 
end; 

var 
    lLine : String; 
    lOperation : PChar; 
begin 
    try 
    if IsAdministrator then 
    begin 
     Writeln('Started as administrator'); 
    end 
    else 
    begin 
     Writeln('Started regular'); 
    end; 

    while True do 
    begin 
     Writeln(''); 
     Writeln('How to start? 1 = admin, 2 = regular user. Type number and press enter'); 
     ReadLn(lLine); 
     lOperation := ''; 

     if lLine = '1' then 
     begin 
     lOperation := 'RUNAS'; 
     end 
     else 
     if lLine = '2' then 
     begin 
     lOperation := 'OPEN'; 
     end; 

     if lOperation <> '' then 
     begin 
     ShellExecute(0, lOperation, PChar(ParamStr(0)), nil, nil, SW_SHOWNORMAL); 
     Break; 
     end; 
    end; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 
+0

abgestimmt, wieder zu öffnen als die Antwort in der Frage, die ist, bezeichnet wird, ist nicht der richtige Weg, der richtige Weg, um die Prozess-Token zu erhalten wäre, der Anruf 'GetTokenInformation' mit den' TokenLinkedToken' Parametern erhält die nicht abgelaufenes Token. Verwenden Sie dieses Token, um den neuen Prozess zu starten. Überprüfe natürlich auch, ob die UAC tatsächlich aktiviert ist (http://www.remkoweijnen.nl/blog/2011/08/11/gettokeninformation-with-tokenlinkedtoken-returns-error-1312/). – Remko

Antwort

3

Ich habe dieses Rätsel bei der Erstellung eines Installers gelöst, hier ist eine der möglichen Lösungen.

Die Idee besteht darin, einen Hintergrundprozess zu erstellen, der mit Benutzerberechtigungen ausgeführt wird. Ihre Hauptanwendung kommuniziert mit ihr und teilt ihr mit, welches Programm gestartet werden soll - der gestartete Prozess hat Benutzerrechte.

Es sollte so funktionieren: Hintergrundprozess wird wie gewohnt gestartet, mit Benutzerberechtigungen. Wenn es gestartet wird, startet es Ihr Hauptprogramm als Admin. Der Hintergrundprozess bleibt verborgen und wartet auf den Befehl vom Hauptprozess.

+0

Dies ist sicherlich die einfachste Methode, wenn nur Prozesse * als Benutzer der aktuell angemeldeten Sitzung * gestartet werden müssen. Andernfalls ist die einzige Möglichkeit, das Token für den angemeldeten Benutzer abzurufen, ohne sein Kennwort zu kennen oder zu speichern, [über API-Aufrufe als lokaler Systembenutzer] (https://msdn.microsoft.com/en-us/library /aa383840(v=vs.85).aspx) (dh: Sie müssen einen Systemdienst schreiben, um dies aufzurufen, und dann mit 'ShellExecuteEx' weitermachen und das Token des Benutzers übergeben). –

+0

@J ... Nicht ganz, siehe die Betrogene –

+0

@DavidHeffernan Überraschend, dass dies angesichts der Vorsichtsmaßregeln für die Verwendung von 'WTSQueryUserToken' (und die Risiken des Leaking des Tokens) möglich ist, sogar aus dem Systemkontext, auf den es beschränkt ist. +1 dafür, in jedem Fall. –

Verwandte Themen