Laden...

Nur bestimmten Code als Admin ausführen

Erstellt von TheBrainiac vor 13 Jahren Letzter Beitrag vor 13 Jahren 13.657 Views
TheBrainiac Themenstarter:in
795 Beiträge seit 2006
vor 13 Jahren
Nur bestimmten Code als Admin ausführen

Hi @ All!

Ich habe eine Anwendung, die als normaler User läuft. Bestimmte Aufgaben in dieser Anwendung müssen allerdings als Administrator ausgeführt werden. Ist es irgendwie möglich, nur bestimmten Code als Administrator auszuführen? Ich möchte nur ungern die ganze Anwendung als Administrator neu starten oder den Umweg über andere Mini-Anwendungen gehen, die diese Aufgaben dann (von der Hauptanwendung ausgelöst) erledigen.

Am liebsten wäre es mir in etwa so:

using (var admin = new AdministrativePrivileges()) {
     // Tue was auch immer
}

Ist das irgendwie möglich?

Gruß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
3.511 Beiträge seit 2005
vor 13 Jahren

Hallo,

sowas nennt sich "Impersonating". Hier gibt es was fertiges dazu.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

TheBrainiac Themenstarter:in
795 Beiträge seit 2006
vor 13 Jahren

Danke. Damit kann ich zwar schon mal was anfangen, ist aber nicht ganz das, was ich meinte.

Gibt es das auch so, wie es einige Installer machen (Also dass man den Windows-Dialog für "Run-As-Admin" angezeigt bekommt, anstatt einen Benutzer eingeben und anmelden zu müssen?)

Gruß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
1.552 Beiträge seit 2010
vor 13 Jahren

Hallo TheBrainiac,

es könnte auch mit Berücksichtigung dass der User dar Administrator Rolle angehört folgendes funktionieren:

WindowsPrincipal principal =  new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool isAdmin =  principal.IsInRole(WindowsBuiltInRole.Administrator);

Gruß,
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

TheBrainiac Themenstarter:in
795 Beiträge seit 2006
vor 13 Jahren

Das ist mir auch bekannt. Dadurch prüfe ich ja nur, ob der angemeldete Benutzer Adminrechte hat. Ich möchte aber in einem Prozess, der nicht als Admin läuft, bestimmten Code als Admin ausführen möglichst, ohne einen berechtigten Benutzer anzumelden, sonder nur mit UAC-Abfrage, ob Admin-Rechte gewährt werden sollen.

Gruß, Christian.

`There are 10 types of people in the world: Those, who think they understand the binary system Those who don't even have heard about it And those who understand "Every base is base 10"`
Gelöschter Account
vor 13 Jahren

Das mit dem UAC geht ab vista. suche nach "UAC c#"

1.552 Beiträge seit 2010
vor 13 Jahren

Man kann auch das Attibut [PrincipalPermission(SecurityAction.Demand, Role = "Administrators")] über den Methoden setzen, jedoch wird dann die Methode nicht ausgeführt fall der User nicht Admin ist.
Guck mal folgenden Link C# & UAC

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

238 Beiträge seit 2007
vor 13 Jahren

N'abend,
für das Problem fallen mir zwei Möglichkeiten ein:*Für die verschiedenen Aktionen die Adminrechte brauchen Befehlszeilenparameter definieren und die selbe Anwendung dann als Admin mit dem jeweiligen Parameter starten, die Funktion ausführen und wieder beenden. *ComElevation: Damit kann man COM-Klassen einzelnd Adminrechte verpassen. Ist allerdings alles andere als einfach aber ich habe ein gutes Beispiel gefunden, is zwar VB.NET aber es geht ja ums Prinzip: COM Elevation: Make Your Program UAC-Aware

Cheerio

1.361 Beiträge seit 2007
vor 13 Jahren

Hi TheBrainiac,

der Vista/Win7-UAC Dialog wird von der consent.exe zur Verfügung gestellt. Darum kümmert sich der Application Information Service, welcher wiederum über nen RPC ansprechbar ist. Das ist aber nicht offengelegt. Eine Methode, die aber diese Funktionalität nutzt ist ShellExecute(...), die intern manchmal auch von der .NET-Methode Process.Start(...) verwendet wird.
Noch mehr Infos dazu unter UAC: The Definitive Guide und vor allem den dort verlinkten Quellen!

Bis auf die von Maximilian erwähnte ComElevation ist also das einzige "anhebbare" ein neuer Prozess. Deshalb kommst du um das Erzeugen eines (neuen) Prozesses nicht umhin.

Jetzt kommt aber mein Vorschlag:*Erzeuge einen neuen Prozess mit Admin-Request *Hole dir das SecurityToken des nun als Admin laufenden Prozesses *Beende diesen Prozess wieder *Nutze das Token um Impersonation zu betreiben

Ich hab damit jetzt mal etwas rumgespielt und folgende Helferklasse dafür geschrieben:

using System;
using System.Security.Principal;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace System.Security
{
    public class ElevationContext
    {
        private static IntPtr ElevatedToken = IntPtr.Zero;
        private const string ElevationArgument = "-waitForTerminationAfterElevation";

        public static void CheckIfCalledWithElevationArguments(string[] args)
        {
            if (args.Length == 1 && args[0] == ElevationArgument)
            {
                Thread.Sleep(2000); // 2 Sekunden warten und danach von selbst sterben
                Environment.Exit(0);
            }
        }

        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
        
        static IntPtr OpenProcessToken(IntPtr processHandle)
        {
            IntPtr token;
            if (!OpenProcessToken(
                processHandle, 
                (uint)(TokenAccessLevels.Duplicate | TokenAccessLevels.Query), 
                out token))
                throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
            return token;
        }

        public static void CallForElevation()
        {
            // neuen Prozess mit höheren Rechten starten.
            Process p = new Process();
            p.StartInfo.FileName = Process.GetCurrentProcess().MainModule.FileName;
            p.StartInfo.Verb = "runas";
            p.StartInfo.Arguments = ElevationArgument;
            p.Start();

            // Security-Token auslesen und merken
            ElevatedToken = OpenProcessToken(p.Handle);

            // Prozess beenden
            p.Kill();
        }

        public static WindowsImpersonationContext Impersonate()
        {
            // Falls noch kein gültiges SecurityToken da ist, 
            // danach fragen, sonst das letzte nehmen
            if (ElevatedToken == IntPtr.Zero)
                CallForElevation();
            return WindowsIdentity.Impersonate(ElevatedToken);
        }
    }
}

Die oben aufgelisteten Punkte kannst du damit gut umsetzen. Als den neuen Prozess, den es ja zu starten gilt, wird einfach die selbe Applikation noch einmal genommen - mit einem speziellen Parameter.

Deshalb muss deine Anwendung als allererste Anweisung die CheckIfCalledWithElevationArguments(...) ausführen!

Das starten und danach fragen (sofern du nicht schon hoch-priviligiert bist) passiert dann alles einmalig on-demand.
Die Verwendung selbst ist dann analog zur WindowsIdentity.Impersonate(...)-Methode des Frameworks.
Die beste Verwendung ergibt sich in einem using-Statement:

using (WindowsImpersonationContext contect = ElevationContext.Impersonate())
{
   MessageBox.Show(IsAdmin().ToString()); //anzeigen, ob wir admin sind
   // ...
   // weitere wichtige Dinge, die du als Admin ausführen willst.
   //
}

beste Grüße
zommi

//EDIT !
Arggh... scheint doch nich zu funktionieren. Der von xxMUROxx gepostete "Admin-Check" sagt zwar ich sei ein Admin, aber sobald man etwas macht, was Security-Checks erfordert, gibt es eine Exception:
Errorcode 1314: ERROR_PRIVILEGE_NOT_HELD
Wahrscheinlich fehlt das SeImpersonatePrivilege, oder aber sogar das SeTcbPrivliege. Und das hat man als Nicht-Admin aber eigentlich nicht... mhh.. doof.
Also ohne Admin-Privilegien keine Chance, Admin zu werden 😃

1.361 Beiträge seit 2007
vor 13 Jahren

Nochmal etwas offtopic,

ich hab grad bemerkt, dass obiges Vorgehen fast schon für Malware missbrauchbar ist.*Meine Malware startet eine "seriöse" Anwendung mit UAC-Elevation. *Weil ich sie gestartet hab, hab ich ein Process-Handle mit allen Rechten. *Darunter auch das Recht, mir das SecurityToken zu holen, was ich nun selbst für Impersonation nutzen kann.

Als Malware präsentiere ich also irgendwann mal dem User ne "seriöse" Anwendung. Beispielsweise Windows Update (wuauclt.exe) oder das JavaUpdate (was mich persönlich alle Nase lang nervt, aber wenn da Java und Sun/Oracle in dem UAC-Dialog mit beruhigender blauer (von MS zertifizierter) Schrift steht, dann geb ich gern mein Admin-Kennwort ein).
Der User sieht eine UAC-Anfrage mit einer "gutartigen" Anwendung und gibt die Credentials ein.
Und schon hat meine Anwendung ebenfalls Adminrechte!

Gefallen tut mir das nich ... X(

beste Grüße
zommi

D
216 Beiträge seit 2009
vor 13 Jahren

Vielen Usern kann die Anwendung auch "ganz normal" am Anfang den UAC Dialog zeigen, die sehen dann "Bitte Adminpasswort eingeben" und machen das dann erstmal ohne das weiterzuhinterfragen.
Wenigstens kommt da ein Dialog und nicht wie bei Windows XP wo sich ein Programm einfach so Adminrechte hat wenn der Benutzer Administrator ist.

BTT: Interessante und einfache Hilfsklasse die ich bestimmt auch mal Verwenden kann, bisher benutze ich sonst immer kleine Hilfsprogramme die die Aktionen, für die Adminrechte erforderlich sind, ausführen, so könnte ich mir das sparen, auch wenn ich es persönlich manchmal praktisch finde das man im UAC Dialog dann auch an meinem Dateinamen des Hilfsprogramm sieht, was es macht.