Einzelnen Beitrag anzeigen

Der schöne Günther
Online

Registriert seit: 6. Mär 2013
6.156 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Anwendung aus Dienst heraus starten

  Alt 16. Apr 2015, 20:22
Also ich weiß nicht, ob es jetzt wirklich ein Dienst sein muss, und ob er nun im Konto SYSTEM laufen soll oder im Benutzerkonto. Gehen tut das schon. Ich habe es bislang aber nur so gemacht dass eine Anwendung auf dem SYSTEM-Konto läuft und die Anwendung dann auf dem Desktop des grade lokal angemeldeten Benutzers aufmacht.


Sieht bei mir so aus:

Delphi-Quellcode:
interface

type
   /// <summary>
   /// Startet einen Prozess in der Session des grade angemeldeten Users
   /// </summary>
   /// <remarks>
   /// <para>Muss von einer Anwendung im Kontext von <c>SYSTEM</c> aufgerufen
   /// werden</para><para>Benötigt Windows Vista oder höher</para>
   /// <para>Ich habe keine Ahnung wie sich das bei RPD verhält</para>
   /// </remarks>
   TLocalProcessLauncher = class
      protected
         /// <remarks>
         /// Das zurückgegebene <c>THandle</c> muss, wenn es nicht mehr
         /// benötigt wird, mit <c>WinApi.Windows.CloseHandle(..)</c>
         /// geschlossen werden
         /// </remarks>
         /// <summary>
         /// Liefert das <i>Client Access Token</i> um mittels
         /// <c>CreateProcessAsUser(..)</c> einen Prozess im Kontext
         /// der lokal angemeldeten Session starten zu können
         /// </summary>
         /// <exception cref="EOSError" />
         class function createSessionToken(): THandle;

      public
         /// <exception cref="EOSError" />
         class procedure launchProcess(
            const   absolutePath:   String;
            const   arguments:      String   =   ''
         );

   end platform;
und

Delphi-Quellcode:
implementation

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


class function TLocalProcessLauncher.createSessionToken(): THandle;
const
   SE_DEBUG_NAME = 'SeDebugPrivilege';
   desiredAccess: DWORD =
      TOKEN_ADJUST_PRIVILEGES or
      TOKEN_QUERY or
      TOKEN_DUPLICATE or
      TOKEN_ASSIGN_PRIMARY or
      TOKEN_ADJUST_SESSIONID or
      TOKEN_READ or
      TOKEN_WRITE;
var
   sessionID:      DWORD;
   serviceToken:   THandle;
   userToken:      THandle;
   tokenPriv:      TTokenPrivileges;
   luid:         TLargeInteger; //wtf?
begin
   sessionID := WTSGetActiveConsoleSessionId();

   Win32Check(
      OpenProcessToken(
         GetCurrentProcess(),
         desiredAccess,
         serviceToken
      )
   );
   try
      Win32Check( LookupPrivilegeValue(nil, SE_DEBUG_NAME, luid) );
      tokenPriv.PrivilegeCount := 1;
      tokenPriv.Privileges[0].Luid := luid;
      tokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;

      Win32Check(
         DuplicateTokenEx(
            serviceToken,
            MAXIMUM_ALLOWED,
            nil,
            WinApi.Windows.SecurityIdentification,
            WinApi.Windows.TokenPrimary,
            userToken
         )
      );

      Win32Check( SetTokenInformation(userToken, TokenSessionId, @sessionID, SizeOf(sessionID)) );
   finally
      CloseHandle(serviceToken);
    end;

   Result := userToken;
end;

class procedure TLocalProcessLauncher.launchProcess(const absolutePath, arguments: String);
var
   token:   THandle;
   args:   PChar;

   startupInfo:   TStartupInfo;
   processInfo:   TProcessInformation;
begin
   if arguments.IsEmpty() then args := nil else args := PChar(arguments);

   token := createSessionToken();
   try
      startupInfo := Default(TStartupInfo);
      startupInfo.cb := SizeOf(TStartupInfo);
        startupInfo.lpDesktop := 'winsta0\Default';

      Win32Check(
         CreateProcessAsUser(
            token,
            PChar(absolutePath),
            args,
            nil,
            nil,
            false,
            NORMAL_PRIORITY_CLASS or CREATE_NEW_CONSOLE,
            nil,
            nil,
            startupInfo,
            processInfo
         )
      );

   finally
      CloseHandle(token);
   end;
end;
Man sollte sich aber bewusst sein was das für ein gewaltiges Sicherheitsrisiko ist. Ich habe dafür auch keinen praktischen Anwendungsfall und das nur mal aus Spaß gemacht...
  Mit Zitat antworten Zitat