Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi JWSCL: Prozess von Dienst starten im Benutzerkontext (https://www.delphipraxis.net/160343-jwscl-prozess-von-dienst-starten-im-benutzerkontext.html)

Zacherl 10. Mai 2011 15:34

AW: JWSCL: Prozess von Dienst starten im Benutzerkontext
 
Habe aus Spaß an der Freude noch ein kleines Workaround verfasst, wenn man seinen Prozess wirklich mit SYSTEM Rechten laufen lassen will (Sinn sei dahingestellt), aber trotzdem Aktionen im Benutzerkontext durchführen will. Ist vielleicht ganz nützlich, wenn man ein eigentlich fertiges Programm vom Service aus starten will. Statt alles umzuschreiben, kann man dann einfach einmalig am Start die Funktion ImpersonateProcess() aufrufen. Der Hook sorgt dann von selbst dafür, dass sämtliche Threads direkt beim Start impersoniert werden. Zusätzlich wird mit MSDN-Library durchsuchenRegOverwritePredefKey der HKEY_CURRENT_USER Key gradegebogen. Benutzerprofilpfade, etc. dürften dank des angepassten Environments nicht verfälscht werden.

Delphi-Quellcode:
function QueryTokenSID(hToken: THandle): String;
var
  ConvertSidToStringSidW: function(Sid: PSID;
    var StringSid: PWideChar): BOOL; stdcall;
var
  Buffer: PTokenUser;
  ReturnLength: DWord;
  StringSid: PWideChar;
begin
  Result := '';
  @ConvertSidToStringSidW := GetProcAddress(LoadLibrary('advapi32.dll'),
    'ConvertSidToStringSidW');
  if (not Assigned(ConvertSidToStringSidW)) then Exit;
  if (not GetTokenInformation(hToken, TokenUser, nil, 0, ReturnLength))
    and (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then Exit;
  GetMem(Buffer, ReturnLength);
  try
    if (not GetTokenInformation(hToken, TokenUser, Buffer, ReturnLength,
      ReturnLength)) then Exit;
    if ConvertSidToStringSidW(Buffer^.User.Sid, StringSid) then
    try
      Result := StringSid;
    finally
      LocalFree(Cardinal(StringSid));
    end;
  finally
    FreeMem(Buffer);
  end;
end;

function ImpersonateThread(hToken: THandle): Boolean;
var
  hNewHKey: HKEY;
begin
  Result := false;
  if (not ImpersonateLoggedOnUser(hToken)) then Exit;
  if (RegOpenKeyEx(HKEY_USERS, PChar(QueryTokenSID(hToken)), 0,
    KEY_ALL_ACCESS, hNewHKey) = ERROR_SUCCESS) then
  try
    Result := RegOverridePredefKey(HKEY_CURRENT_USER, hNewHKey) =
      ERROR_SUCCESS;
  finally
    RegCloseKey(hNewHKey);
  end;
end;

type
  PThreadParam = ^TThreadParam;
  TThreadParam = packed record
    UserToken: THandle;
    Thread: Pointer;
    Param: Pointer;
  end;
  TThreadFunction = function(lpParam: Pointer): DWord; stdcall;

var
  UserToken: THandle;

var
  O_CreateThread: function(lpThreadAttributes: Pointer;
    dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine;
    lpParameter: Pointer; dwCreationFlags: DWORD;
    var lpThreadId: DWORD): THandle; stdcall = nil;

function C_CreateThread(lpThreadAttributes: Pointer;
  dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine;
  lpParameter: Pointer; dwCreationFlags: DWORD;
  var lpThreadId: DWORD): THandle; stdcall;

function LocalThread(lpParam: PThreadParam): DWord; stdcall;
begin
  ImpersonateThread(lpParam^.UserToken);
  Result := TThreadFunction(lpParam^.Thread)(lpParam^.Param);
  Dispose(lpParam);
end;

var
  ThreadParam: PThreadParam;
begin
  New(ThreadParam);
  ThreadParam^.UserToken := UserToken;
  ThreadParam^.Thread := lpStartAddress;
  ThreadParam^.Param := lpParameter;
  Result := O_CreateThread(lpThreadAttributes, dwStackSize, @LocalThread,
    ThreadParam, dwCreationFlags, lpThreadId);
end;

function ImpersonateProcess(hToken: THandle): Boolean;
begin
  Result := false;
  if (not Assigned(O_CreateThread)) then
  begin
    UserToken := hToken;
    Result := ImpersonateThread(hToken) and
      InstallInlineHook(GetProcAddress(LoadLibrary('kernel32.dll'),
      'CreateThread'), @C_CreateThread, @O_CreateThread);
  end;
end;
Möglicher Aufruf wäre beispielsweise (ohne Win2000 Kompatibilität):
Delphi-Quellcode:
var
  WTSGetActiveConsoleSessionId: function: DWord; stdcall;
  WTSQueryUserToken: function(SessionId: ULONG;
    var phToken: THandle): BOOL; stdcall;
var
  hToken: THandle;
begin
  @WTSGetActiveConsoleSessionId :=
    GetProcAddress(LoadLibrary('kernel32.dll'), 'WTSGetActiveConsoleSessionId');
  @WTSQueryUserToken :=
    GetProcAddress(LoadLibrary('wtsapi32.dll'), 'WTSQueryUserToken');
  if (not Assigned(WTSGetActiveConsoleSessionId)) or
    (not Assigned(WTSQueryUserToken)) then Exit;

  if not WTSQueryUserToken(WTSGetActiveConsoleSessionId, hToken) then
    RaiseLastOSError;

  ImpersonateProcess(hToken);
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:37 Uhr.
Seite 2 von 2     12   

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