Einzelnen Beitrag anzeigen

Benutzerbild von Codewalker
Codewalker

Registriert seit: 18. Nov 2005
Ort: Ratingen
945 Beiträge
 
Delphi XE2 Professional
 
#7

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist

  Alt 13. Aug 2006, 20:07
Für die Forensuche - Die Lösung:

Hilfsfunktion:
Delphi-Quellcode:
function GetUserAndDomainFromPID(ProcessId: DWORD; var User, Domain: String): Boolean;
  { Hilfsfunktion. Ermittelt zu einer PID den Benutzerkontext und die Domäne }
var
  hToken: THandle;
  cbBuf: Cardinal;
  ptiUser: PTOKEN_USER;
  snu: SID_NAME_USE;
  ProcessHandle: THandle;
  UserSize, DomainSize: DWORD;
  bSuccess: Boolean;
begin
  Result := False;
  ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessId);
  if ProcessHandle <> 0 then
  begin
    if OpenProcessToken(ProcessHandle, TOKEN_QUERY, hToken) then
    begin
      bSuccess := GetTokenInformation(hToken, TokenUser, nil, 0, cbBuf);
      ptiUser := nil;
      while (Not bSuccess) And (GetLastError = ERROR_INSUFFICIENT_BUFFER) do
      begin
        ReallocMem(ptiUser, cbBuf);
        bSuccess := GetTokenInformation(hToken, TokenUser, ptiUser, cbBuf, cbBuf);
      end;
      CloseHandle(hToken);

      if Not bSuccess then
      begin
        Exit;
      end;

      UserSize := 0;
      DomainSize := 0;
      LookupAccountSid(nil, ptiUser.User.Sid, nil, UserSize, nil, DomainSize, snu);
      if (UserSize <> 0) And (DomainSize <> 0) then
      begin
        SetLength(User, UserSize);
        SetLength(Domain, DomainSize);
        if LookupAccountSid(nil, ptiUser.User.Sid, PChar(User), UserSize, PChar(Domain),
          DomainSize, snu) then
        begin
          Result := True;
          User := StrPas(PChar(User));
          Domain := StrPas(PChar(Domain));
        end;
      end;

      if bSuccess then
      begin
        FreeMem(ptiUser);
      end;
    end;
    CloseHandle(ProcessHandle);
  end;
end;
Eigentliche Funktion:

Delphi-Quellcode:
function IsServiceApp(AppName: String; PID: Integer; var ServiceName: String): Boolean;
{
Überprüft, ob ein Prozess mit der PID ein Dienst ist.
Bedingungen: - Benutzerkonto ist das Systemkonto
            - Service ist in der Registry eingetragen
}

var
  User, Domain: String;
  Reg: TRegistry;
  List: TStringList;
  I: Integer;
begin
  Result := False;
  GetUserAndDomainFromPID(PID, User, Domain); // Ermittelt den Benutzerkontext
  if User = 'SYSTEMthen
  begin // Programm läuft im Systemkontext... (könnte ein Dienst sein)
    Reg := TRegistry.Create;
    List := TStringList.Create;

    Reg.RootKey := HKEY_LOCAL_MACHINE;
    Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Services\'); // Serviceliste öffnen
    Reg.GetKeyNames(List); // Alle Untereinträge auflisten
    for I := 0 to List.Count - 1 do
    begin
      Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Services\' + List[i]);
      if Reg.ValueExists('ImagePath')
      // Wenn zugehörige Startdatei angegeben... (sonst kann nicht zugeordnet werden über den Prozessnamen)
      then
      begin
        if LowerCase(ExtractFileNameFromSystemPath(Reg.ReadString('ImagePath'))) =
          LowerCase(AppName)
        // Wenn die Dienst-EXE = Prozess-EXE --> Prozess ist ein Dienst
        then
        begin
          Result := True; // Prozess = Dienst
          ServiceName := List[i]; // Prozessnamen zurückgeben (z.B. "Spooler")
          Break; // Schleife verlassen
        end;
      end;
    end;
    List.Free;
    Reg.Free;
  end;
end;
Funktioniert bis jetzt ohne Probleme, bin aber für Diskussion offen
  Mit Zitat antworten Zitat