[Update] RunAs für normale Dokumente anwenden

Hannes hat letztens das Tool CPAU vorgestellt, das im Grunde genauso funktioniert, wie das Windows-interne runas-Programm. Wer dessen Funktionalität nicht kennt: Es ist dazu da, um eine Anwendung mit den Rechten eines anderen Benutzers ausführen zu können.

Nun ist bei ihm das Problem aufgetreten, dass es ihm nicht möglich ist, MSP-Dateien auszuführen. Grund hierfür ist, dass es sich bei MSP-Dateien nicht um echte, ausführbare Dateien handelt, sondern um Dokumente - also im Grunde wie Bilddateien.

Wenn ihr sehen wollt, was Windows im Hintergrund macht, wenn ihr ein Dokument doppelt anklickt, könnt ihr folgendes machen:

  1. Drückt die Tastenkombination Windowstaste+R. Es öffnet sich das Ausführen-Fenster.
  2. Gebt in dem Fenster "regedit" ein und drückt Enter. Es öffnet sich der Registry-Editor.

    Ausführen-Dialog

  3. Öffnet unter "Arbeitsplatz" den Baum "HKEY_CLASSES_ROOT". Darunter findet ihr eine Liste aller Dateiendungen.

    HKEY_CLASSES_ROOT

  4. Öffnet nun den Eintrag einer Dateiendung - zum Beispiel ".jpg". Ihr seht ein paar Unterelemente.

    .jpg Knoten

  5. Guckt, ob es den Unterbaum "shell/open/command" gibt. Falls ja, macht weiter mit Punkt 8, falls nein, macht weiter mit Punkt 6.
  6. Klickt den aktuellen Baumeintrag (z.B. ".jpg") an, dieser sollte einen Wert "(Standard)" beinhalten. Der darin gespeicherte Wert ist ein Platzhalter.

    .jpg-(Standard)-Wert

  7. Sucht einen Baumeintrag, der den Namen des Platzhalters entspricht. Die Platzhalter dienen dazu, dass mehrere Dateiendungen sich genau gleich verhalten (z.B. ".jpg" und ".jpeg").

    jpegfile Knoten

  8. Öffnet nun den Unterbaum "shell/open/command". Dieser Knoten bestimmt, was geschehen soll, wenn eine Datei dieses Typs geöffnet werden soll.

    shell/open/command Knoten

  9. Seht euch nun den Wert "(Standard)" an. Dieser beinhaltet den tatsächlich ausgeführten Befehl zu einer Dateiendung (z.B. bei einem Doppelklick). Der Parameter "%1" wird bei der Ausführung mit dem entsprechenden Dateinamen ersetzt. Einige Dateitypen (z.B. MSI-Dateien) können zusätzliche Parameter erhalten. Diese können mit dem Parameter "%*" übergeben werden.

    shell/open/command-(Standard)-Wert

(Für diejenigen unter euch, die gerne experimentieren: Lasst die Finger von dem Knoten "exefile"! Wenn ihr diesen unbedarft ändert, zerschießt ihr euch das ganze System. Um das dann wieder gerade zu biegen, müsst ihr remote den entsprechenden Registry-Hive mounten und den Registry-Eintrag reparieren.)

Nach diesem kleinen Exkurs kommen wir nun zurück zum Thema: Das Problem, weshalb die runas-Programme diese MSP-Datei nicht öffnen können, liegt wahrscheinlich daran, dass sie versuchen, die Datei direkt auszuführen - dabei müssten sie doch erst nachgucken, mit welchem Programm die Datei geöffnet werden muss! Und genau hierfür habe ich ein kleines Programm mit dem Namen "execute" geschrieben: Es macht nicht viel, sondern öffnet eine angegebene Datei einfach anhand des Befehls, der dort in der Registry hinterlegt ist. Dabei ist es egal, ob es sich um ein Programm, ein Bild oder etwas anderes handelt. Den Quelltext des Programms findet ihr hier:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
program execute;

uses
  Windows,
  SysUtils,
  ShellAPI,
  ActiveX;

var
  VCOMCode    : HRESULT;
  VIndex      : Integer;
  VParameters : String;
  VReturnCode : Cardinal;

begin
  ExitCode := 0; // application terminated successfully

  if (ParamCount > 0) then
  begin
    VParameters := '';
    for VIndex := 2 to ParamCount do
      VParameters := VParameters + '"' + ParamStr(VIndex) + '" ';
    Delete(VParameters, Length(VParameters), 1); // trim last space character

    VCOMCode := CoInitializeEx(nil, COINIT_APARTMENTTHREADED or COINIT_DISABLE_OLE1DDE);
    if ((VCOMCode = S_OK) or (VCOMCode = S_FALSE)) then
    begin
      try
        VReturnCode := ShellExecute(0,                                       // hwnd,
                                    'open',                                  // lpOperation,
                                    PAnsiChar(ParamStr(1)),                  // lpFile,
                                    PAnsiChar(VParameters),                  // lpParameters,
                                    PAnsiChar(ExtractFilePath(ParamStr(1))), // lpDirectory,
                                    SW_SHOWNORMAL                            // nShowCmd
                                   );

        if (VReturnCode <= 32) then
          ExitCode := 100 + VReturnCode; // file could not be executed
      finally
        CoUninitialize();
      end;
    end
    else
      ExitCode := 2; // COM could not be initialized
  end
  else
    ExitCode := 1; // file was not provided
end.

Die Verwendung der Anwendung ist super einfach: Ihr ruft das Programm einfach mit dem Pfad der auszuführenden Datei als ersten Parameter auf - alle weiteren Parameter werden an die Datei als weitere Parameter übergeben.

In diesem Beispiel wird z.B. die Kommandozeile mit den Rechten des Administrators aufgerufen, Google angepingt und die Kommandozeile danach offen gehalten:

1
runas /user:Administrator "execute cmd /K ping \"google.de\""

Bitte beachtet, dass der gesamte Aufruf mit allen Parametern für das aufgerufene Dokument in einem Parameter an runas übergeben werden muss! Sollte es nötig sein, Anführungungszeichen für die eigentlichen Parameter zu benutzen, so müssen diese mit einem Backslash "escaped" werden. Seht euch den Parameter \"google.de\" als Beispiel an. ;-)

Ich hoffe, euch hat dieser kleine Ausflug in die Welt der Dateitypen gefallen und ihr habt ein bisschen was darüber gelernt, wie Windows eure Dateien intern behandelt. :-)

Update:
Ich sorge nun vor dem Aufrufen noch dafür, dass COM ordentlich initialisiert und danach auch wieder deinitialisiert wird. Man weiß ja nie. ;-)

Zum Schluss noch etwas Rechtliches:
Der Autor dieses Programms haftet nicht für Schäden an Soft- oder Hardware oder Vermögensschäden, die durch das Benutzen des Programms entstehen, es sei denn, diese beruhen auf einem grob fahrlässigen oder vorsätzlichen Handeln des Autors, seiner Erfüllungsgehilfen oder seiner gesetzlichen Vertreter.

Aufrufende Grüße, Kenny

P.S.: Wie zu erkennen ist, verwende ich einfach die API-Funktion ShellExecute(). Wer Langeweile hat und sich mit dem Parsen der Befehle herumärgern will, der kann das ganze natürlich auch nach dem oben beschriebenen Schema nachbauen (Action auslesen und über CreateProcess() nachbilden).

3 Kommentare » Schreibe einen Kommentar

  1. Pingback: Teile der Systemsteuerung als anderer Benutzer ausführen | IT | IMA - Informationen Mal Anders

  2. Du bist einfach nur genial. Wann gehste denn zu Microsoft oder Google Deutschland? :D
    Das ganze Thema schau ich mir nochmal an, werd ich sicher mal meinen Arbeitskollegen vorstellen wenns funzt.

Hinterlasse eine Antwort

Pflichtfelder sind mit * markiert.


Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>