Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Ermitteln ob ein Programm oder Prozess ein Dienst ist (https://www.delphipraxis.net/69927-ermitteln-ob-ein-programm-oder-prozess-ein-dienst-ist.html)

Codewalker 22. Mai 2006 14:03


Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
Hallo zusammen.

Weiß jemand, wie ich herausfinden kann, ob ein Programm (exe?) oder ein Prozess ein Dienst ist. Ich würde gerne einen Prozess bei beenden neu starten, jedoch muss man ja Programme über CreateProcess und Dienste im Systemkonto mit "net start dienstname" starten. Wie kann man diesen Unterschied automatisch ermitteln?

Angel4585 22. Mai 2006 14:21

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
du könntest versuchen den Dienst oder das Programm mit NET STOP vorher zu beenden, wenn die Meldung kommt der es kein installierter DIenst ist, ist es ein normales Programm.. kA ob des so funzt.

Olli 22. Mai 2006 14:31

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
Herausbekommen kann man das mit Sicherheit garnicht richtig (es gibt nämlich auch EXE-Dateien, die sich als Zwitter verhalten). Es gibt aber gewisse Anhaltspunkte:

1. Ist der Elternprozeß SERVICES.EXE?
2. Läuft der Prozeß als SYSTEM?

Es gibt sicher noch mehr. Das Problem ist halt, daß man bei einer Zwitter-EXE es kaum generisch ermitteln kann.

Codewalker 22. Mai 2006 15:52

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
Danke, ich werds damit mal versuchen...

Codewalker 26. Mai 2006 16:35

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
Zitat:

Zitat von Angel4585
du könntest versuchen den Dienst oder das Programm mit NET STOP vorher zu beenden, wenn die Meldung kommt der es kein installierter DIenst ist, ist es ein normales Programm

Soweit so gut, ich habs mit dem Systemkonto, etc. versucht. Jetzt würde ich für den Zweifelsfall noch gern die Überprüfung mit NET STOP einbauen. Das sollte aber innerhalb meines Programms erfolgen, ohne dass dabei das Konsolenfenster geöffnet wird. Ist das möglich und wenn ja, wir kann ich das Ergebnis von NET STOP abfangen?

Olli 26. Mai 2006 16:59

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
Das geht mit den entsprechenden API-Funktionen zum Starten und Stoppen. Anhaltspunkte findest du hier:
http://assarbad.info/en/stuff/tutorials/ntsvc/

Codewalker 13. Aug 2006 19:07

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
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 = 'SYSTEM' then
  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 :wink:

Olli 13. Aug 2006 19:57

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
Zitat:

Zitat von Codewalker
Funktioniert bis jetzt ohne Probleme, bin aber für Diskussion offen :wink:

<homermäßig>Naaaain :mrgreen:</homermäßig>

1. Punkt: was passiert, wenn einmal der Service-Schlüssel aaa und einmal zzz, beidemale mit dem gleichen ImagePath existieren? Hat ja niemand gesagt, daß man von einer EXE nur eine Instanz als Service laufen lassen kann.
2. Punkt: ImagePath kann auch Parameter enthalten, nicht nur Pfade. Abgesehen davon kann es mal eine Umgebungsvariable und einmal schon "expandierte" Pfade enthalten.
3. Punkt: Warum sollte ein normales Programm nicht auch als SYSTEM laufen können?
4. Punkt: Zuguterletzt Stichwort MSDN-Library durchsuchenImpersonation

Anderes ließe sich noch anführen. So richtig kann man es eben doch nicht rausbekommen. Der Prozeßbaum (Suche nach "svchost") wäre noch eine Alternative, aber auch nicht 100% sicher - schließlich kann ein Dienst auch einen "normalen" Prozeß starten.

Codewalker 14. Aug 2006 13:31

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
okay, okay. 1:0 für Dich, verdammt gute Argumente :wink: . Aber ich hab einen Vorschlag, es zu ändern:

Zitat:

Zitat von Olli
1. Punkt: was passiert, wenn einmal der Service-Schlüssel aaa und einmal zzz, beidemale mit dem gleichen ImagePath existieren? Hat ja niemand gesagt, daß man von einer EXE nur eine Instanz als Service laufen lassen kann.

Okay, aber für die reine Erkennung, ob es ein Dienst ist, tut es da ja auch. Dann kann ich halt nur nicht mit Sicherheit den Dienstnamen ermitteln. Dn könnte man ja in solchen Zweifelsfällen auf einen leeren String setzen bzw. als StringList beide Werte zurückgeben. Außerdem darf die Schleife dann bei einem Fund nicht automatisch abgebrochen werden.

Zitat:

Zitat von Olli
2. Punkt: ImagePath kann auch Parameter enthalten, nicht nur Pfade. Abgesehen davon kann es mal eine Umgebungsvariable und einmal schon "expandierte" Pfade enthalten.

Okay, das lässt sich aber auch noch machen. ExtractFileNameFromSystemPath habe ich selbst geschrieben um Pfad wie %systemdir% und ähnliche aufzulösen. Kann ich bei Gelegenheit gerne posten (hab ich grad nicht zur Hand).

Das könnte man über die Module ermitteln. Bei einem normalen Programm ist das Modul 0 immer das Programm selber. Bei einem Dienst dürfte das doch dann nicht der Fall sein. Siehe auch hier Link am Ende des ersten Posts

Zitat:

Zitat von Olli
4. Punkt: Zuguterletzt Stichwort MSDN-Library durchsuchenImpersonation

Was meinst du damit? :gruebel:

Zitat:

Zitat von Olli
Der Prozeßbaum (Suche nach "svchost") wäre noch eine Alternative, aber auch nicht 100% sicher

Und das sagt mir auch nicht viel.... :gruebel:

Olli 14. Aug 2006 13:53

Re: Ermitteln ob ein Programm oder Prozess ein Dienst ist
 
Zitat:

Zitat von Codewalker
Okay, aber für die reine Erkennung, ob es ein Dienst ist, tut es da ja auch. Dann kann ich halt nur nicht mit Sicherheit den Dienstnamen ermitteln. Dn könnte man ja in solchen Zweifelsfällen auf einen leeren String setzen bzw. als StringList beide Werte zurückgeben. Außerdem darf die Schleife dann bei einem Fund nicht automatisch abgebrochen werden.

Sicher.

Zitat:

Zitat von Codewalker
Okay, das lässt sich aber auch noch machen. ExtractFileNameFromSystemPath habe ich selbst geschrieben um Pfad wie %systemdir% und ähnliche aufzulösen. Kann ich bei Gelegenheit gerne posten (hab ich grad nicht zur Hand).

Hmm.

Zitat:

Zitat von Codewalker
Das könnte man über die Module ermitteln. Bei einem normalen Programm ist das Modul 0 immer das Programm selber. Bei einem Dienst dürfte das doch dann nicht der Fall sein. Siehe auch hier Link am Ende des ersten Posts

Das müßtest du mir nochmal erklären, wenn es geht.

Zitat:

Zitat von Codewalker
Was meinst du damit? :gruebel:

Ein Thread innerhalb eines Dienstes muß nicht als SYSTEM laufen, auch wenn der Dienst als SYSTEM gestartet wurde. Ergo kann das Token falsch sein, oder schlimmer, du kannst möglicherweise garnicht die Rechte haben um auf Ressourcen zuzugreifen, die du im obigen Code ansprichst.

Zitat:

Zitat von Codewalker
Und das sagt mir auch nicht viel.... :gruebel:

Daß einige Prozesse einen Elternprozeß haben ist dir klar? Für Dienste gibt es normalerweise einen einzigen Elternprozeß (services.exe) unter dem dann andere laufen (svchost.exe für DLL-Services usw.).


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:04 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz