AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) CommandLines der Prozesse unter Windows 64 Bit ermitteln?
Thema durchsuchen
Ansicht
Themen-Optionen

CommandLines der Prozesse unter Windows 64 Bit ermitteln?

Ein Thema von Delphi-Laie · begonnen am 5. Sep 2014 · letzter Beitrag vom 16. Sep 2014
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#1

CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 5. Sep 2014, 18:41
Hallo Delphifreunde!

Kennt Ihr eine einfache und stabile Möglichkeit, die CommandLines aller (oder zumindest der meisten) Prozesse anhand deren Prozeß-IDs unter 64 Bit zu ermitteln? Debugrechte sind natürlich vorausgesetzt und erfolgreich angefordert, zumal das Compilat natürlich auch 64 Bit hat (mit XE2 erstellt).

Ich fand im Internet zwei recht ähnliche Delphi-Lösungen, die beide auf der kombinierten Anwendung der NTQueryProcessInformation- und ReadProcessMemory-Funktion beruhen und unter Windows 32 Bit wie gewünscht funktionieren (Abrufen der Process Basic Information). Unter Windows 7 64 Bit funktionert es jedoch nicht, nicht mal mit dem eigenen Prozeß (Prozeß-ID des eigenen Programmes). Zwar konnte ich mich ein wenig vorarbeiten (Integerwerte auf 64 Bit erweitert), doch bis zum erfolgreichen Ermitteln der Kommandozeile reicht es nie, an irgendeinem der wiederholten ReadProcessMemory-Aufrufe scheitert es regelmäßig. Natürlich lasse ich mir GetLastError ausgeben, doch für mehr als dem "Aufbohren" der Bitanzahl der Integerwerte reichten die Meldungen mir nicht.

Ehe ich hier beide Zwischenergebnisse ausgieße, einfach die Fragen:

1. Ist das Ermitteln der Kommandozeilen unter Windows 64 Bit überhaupt möglich, insbesondere mit den genannten API-Funktionen?
2. Gibt es ggf. eine recht simple Variante zur Ermittlung der jeweiligen Kommandozeile, die stabil und bitanzahlunabhängig funktioniert?

Ich vermute, daß der Process Environment Block (PEB) unter 64 Bit grundsätzlich anders gestaltet ist (s. http://stackoverflow.com/questions/5...extern-process ) und daß das der Hauptgrund ist, warum man nicht einfach für 32 und 64 Bit weitgehend gleiche Quelltexte nehmen kann.

Vielen Dank im voraus für Eure Aufmerksamkeit!

Delphi-Laie
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 5. Sep 2014, 22:02
Du kannst einfach die Spalte CommandLine aus der WMI Klasse Win32_Process nutzen:
http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
Anders machen das andere Tools auch meistens nicht.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#3

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 7. Sep 2014, 18:35
Hallo Sebastian, besten Dank für Deine Antwort!

WMI erfordert, soweit ich mich schlaugelesen habe, auf NTx das Laufen des Windows-Verwaltungsinstrumentations-Dienstes (WinMgmt.exe). Daher sympathisiere ich nicht so sehr mit dieser Lösung.

Für alle, die es interessiert, hier die beiden Funktionen, die als 32-Bit-Compilate für 32-Bit-Prozesse funktionieren (die Integervariablen müssen dann auf 32 Bit reduziert werden). Bei 64 Bit scheitert es immer an irgendeinem der wiederholten ReadProcessMemory-Aufrufe.
Delphi-Quellcode:

implementation

NtQueryInformationProcess:function(ProcessHandle:THandle;ProcessInformationClass:UInt64{DWORD};ProcessInformation:Pointer;ProcessInformationLength:ULONG;ReturnLength:PULONG):LongInt;stdcall=nil;

type UNICODESTRING=record
  Length,MaximumLength:UInt64;//Word;
  Buffer:PWideChar;
  end;

type PROCESS_BASIC_INFORMATION=packed record
  ExitStatus:{U}Int64;//DWORD;
  PebBaseAddress:Pointer;
  AffinityMask,BasePriority,UniqueProcessId,InheritedUniquePID:{U}Int64;//DWORD;
  end;

  function getcommandline1(PID:dword):string;
  label 0;
   var
    PBI:PROCESS_BASIC_INFORMATION;
    CommandLine:UNICODESTRING;
    lib:THandle;
    ReturnLength:NativeUInt;//Cardinal;
  begin
  hProcess:=OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,false,pe.th32ProcessID);
  if hProcess<>invalid_handle_value then
    begin
    lib:=Loadlibrary('ntdll.dll');
    if lib<>0 then
      begin
      NtQueryInformationProcess:=GetProcAddress(lib,'NtQueryInformationProcess');
      if (NtQueryInformationProcess(hProcess,0{=>ProcessBasicInformation},@PBI,sizeof(PBI),@ReturnLength)=0{STATUS_SUCCESS}) {and (ReturnLength=SizeOf(PBI))} then
        begin
        if not ReadProcessMemory(hProcess,Pointer({U}Int64(PBI.PEBBaseAddress)+OffsetProcessParametersx32),@rtlUserProcAddress,sizeof(Pointer),ReturnLength) then
          begin
          result:='1. '+SysErrorMessage(GetLastError);
          goto 0
          end;
        if not ReadProcessMemory(hProcess,Pointer({U}Int64(rtlUserProcAddress)+OffsetCommandLinex32),@CommandLine,sizeof(CommandLine),ReturnLength) then
          begin
          result:='2. '+SysErrorMessage(GetLastError);
          goto 0
          end;
        SetLength(CommandLineContents,CommandLine.length);
        if not ReadProcessMemory(hProcess,CommandLine.Buffer,@CommandLineContents[1],CommandLine.Length,ReturnLength) then
          begin
          result:='3. '+SysErrorMessage(GetLastError);
          goto 0
          end;
        result:=WideCharLenToString(PWideChar(CommandLineContents),CommandLine.length div 2);
        end else result:='NTQueryInformationProcess gescheitert: '+SysErrorMessage(GetLastError);
      
      0:Freelibrary(lib)
      end;
    CloseHandle(hProcess)
    end
  end;

  function getcommandline2(PID:dword):string;
  label 0;
  var ProcessHandle:THandle;
  rtlUserProcAddress,PMBAddress:Pointer;
  command_line:UnicodeString;
  command_line_contents:WideString;
  ReturnLength:NativeUInt;//Cardinal;

    function GetPEBAddress(inhandle:THandle):pointer;
    var pbi:PROCESS_BASIC_INFORMATION;
    MyHandle:THandle;
    myFunc:procedure(ProcessHandle:THandle;
                     ProcessInformationClass:DWord;
                     ProcessInformation:Pointer;
                     ProcessInformationLength:DWord;
                     ReturnLength:Pointer);stdcall;
    begin
    MyHandle:=LoadLibrary('NTDLL.DLL');
    if MyHandle<>0 then
      begin
      myfunc:=GetProcAddress(myHandle,'NtQueryInformationProcess');
      if @myfunc<>nil then MyFunc(inhandle,0{=>ProcessBasicInformation},@pbi,sizeof(pbi),nil);
      FreeLibrary(Myhandle)
      end;
    Result:=pbi.PEBBaseAddress
    end;

  begin
  ProcessHandle:=OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,false,PID);
  if ProcessHandle<>invalid_handle_value then
    begin
    PMBAddress:=GetPEBAddress(ProcessHandle);
    if not ReadProcessMemory(ProcessHandle,Pointer(int64(PMBAddress)+OffsetProcessParametersx32),@rtlUserProcAddress,sizeof(Pointer),ReturnLength) then
      begin
      result:='1. '+SysErrorMessage(GetLastError);
      goto 0
      end;
  if not ReadProcessMemory(ProcessHandle,Pointer(Longint(rtlUserProcAddress)+OffsetCommandLinex32),@command_line,sizeof(command_line),ReturnLength) then
      begin
      result:='2. '+SysErrorMessage(GetLastError);
      goto 0
      end;
    SetLength(Command_Line_Contents,command_line.length);ReadProcessMemory(ProcessHandle,command_Line.Buffer,@command_Line_contents[1],command_line.length,ReturnLength);
    Result:=WideCharLenToString(PWideChar(command_Line_Contents),command_line.length div 2);
    
    0:CloseHandle(ProcessHandle)
    end else result:='Kein gültiges Prozeßhandle '+SysErrorMessage(GetLastError);
  end;

Geändert von Delphi-Laie ( 7. Sep 2014 um 18:38 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.202 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 7. Sep 2014, 19:04
WMI erfordert, soweit ich mich schlaugelesen habe, auf NTx das Laufen des Windows-Verwaltungsinstrumentations-Dienstes (WinMgmt.exe). Daher sympathisiere ich nicht so sehr mit dieser Lösung.
Und was stört genau daraun? Ich denke bei 99,99% der Windows-Rechner wird dieser Dienst laufen. Bei den restlichen 0,01% werden eh andere Probleme haben als dein Programm auszuführen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 7. Sep 2014, 19:42
WMI erfordert, soweit ich mich schlaugelesen habe, auf NTx das Laufen des Windows-Verwaltungsinstrumentations-Dienstes (WinMgmt.exe). Daher sympathisiere ich nicht so sehr mit dieser Lösung.
Deine Lösung bewirkt ggf., dass dein Programm als Virus eingestuft wird. Zudem funktioniert sie nicht mit Adminprozessen, wenn sie ohne Adminrechte gestartet ist, die Lösung via WMI schon.

WMI ist ein Grundbestandteil von Windows, ohne läuft nicht einmal die Windows Firewall...
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#6

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 7. Sep 2014, 21:36
Das Anfordern maximaler Privilegien, das ich schrieb, setzt natürlich Administrationsrechte voraus, das ist mir klar.

Ich bin jetzt auch inzwischen soweit (also breitgeschlagen), daß ich mich mit WMI näher und mich mit den beiden o.g. auf 64 Bit "aufgebohrten" Funktionen nicht mehr beschäftigen werde. Nochmals danke für diesen Anstoß!

Unter Windows 2000 und XP ist der Instrumentationsdienst für mich ein Fremdkörper und gehört zu denen, die ich deaktiviere, und fahre damit immer recht gut (der Router "firewallt" ja ohnehin). Bei neueren Windows, und mir geht es ja um 64 Bit, ließ ich ihn bisher in Ruhe, wird ja dann auch in die svchost.exe verpackt.

Geändert von Delphi-Laie ( 7. Sep 2014 um 21:48 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#7

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 9. Sep 2014, 08:24
Ursache des Problems ist folgende:
Zitat von http://winprogger.com/getmodulefilenameex-enumprocessmodulesex-failures-in-wow64/:
PEB of the process is obviously found in PebBaseAddress. However the PEB of a 64-bit process lies at a 64-bit address and since PROCESS_BASIC_INFORMATION for 32-bit applications only has space for 32-bit pointer, how can the 64Bit PEB address be returned to a 32-bit application ? If the 64-bit PEB had no high bits set, then technically the 64-bit PEB address could fit into 32-bits without losing any of the address bits. wow64 solves this problem simply by setting PebBaseAddress to NULL in all cases.

Now, wow64 translation is needed in this case since the 64-bit structure members would have to be downsized to fit in 32-bit PROCESS_BASIC_INFORMATION structure. [32-bit PROCESS_BASIC_INFORMATION is 24 bytes where as 64-bit PROCESS_BASIC_INFORMATION is 48 bytes]

Since NtQueryInformationProcess returns success despite this loss of PEB data in the wow64 translation layer, GetModuleFileNameEx in 32-bit process eventually ends up attempting to read invalid memory in the opened process, when it calls ReadProcessMemory (or more specifically NtReadVirtualMemory) with offsets from NULL PEB returned. This causes error 299 (ERROR_PARTIAL_COPY).
Ich weiß nicht genau, ab welcher Version von Windows diese Funktionen implementiert wurden, aber schau dir mal NtWow64QueryInformationProcess64 und NtWow64ReadVirtualMemory64 aus der ntdll.dll an.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#8

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 9. Sep 2014, 13:14
Ich staune immer wieder, was manche Genies im Internet aufzustöbern imstande sind.

Vielen Dank, Zacherl!
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#9

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 9. Sep 2014, 13:27
Ich staune immer wieder, was manche Genies im Internet aufzustöbern imstande sind.
Hatte mich vor einiger Zeit mal mit dem Thema beschäftigt, deshalb wusste ich wonach ich suchen musste (ERROR_PARTIAL_COPY) Hier gibts übrigens Prototypen zu den genannten Funktionen und auch etwas fertigen Code zum Auslesen des PEBs zwecks Modul Enumeration.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#10

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 14. Sep 2014, 16:44
Hallo Zacherl, nur allein das Nachvollziehen das von Dir verlinkten Beispielprogrammes ist ein nachmittagsfüllendes Programm, das leider bisher im Versuch steckenblieb. Es scheitert an den Units, die für das Programm benötigt werden. Bis zur NcxTypes.pas konnte ich alle Units besorgen (JEDI bzw. letztere, die NcxTypes von Luckies Internetseite). Die beiden Units NcxNtDef.pas und NcxNtTeb.pas konnte ich nicht auftreiben.

Darf ich Dich deshalb fragen, ob Du das Beispielprogramm selbst einmal zum Laufen brachtest, und, falls ja, woher Du die beiden letztgenannten Units bezogst?

Danke und Gruß

Delphi-Laie

Geändert von Delphi-Laie (14. Sep 2014 um 21:07 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:33 Uhr.
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