Delphi-PRAXiS
Seite 1 von 4  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   CommandLines der Prozesse unter Windows 64 Bit ermitteln? (https://www.delphipraxis.net/181736-commandlines-der-prozesse-unter-windows-64-bit-ermitteln.html)

Delphi-Laie 5. Sep 2014 17:41

CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
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

jaenicke 5. Sep 2014 21:02

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
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.

Delphi-Laie 7. Sep 2014 17:35

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
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;

Bernhard Geyer 7. Sep 2014 18:04

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
Zitat:

Zitat von Delphi-Laie (Beitrag 1271465)
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.

jaenicke 7. Sep 2014 18:42

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
Zitat:

Zitat von Delphi-Laie (Beitrag 1271465)
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...

Delphi-Laie 7. Sep 2014 20:36

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
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.

Zacherl 9. Sep 2014 07:24

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
Ursache des Problems ist folgende:
Zitat:

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.

Delphi-Laie 9. Sep 2014 12:14

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
Ich staune immer wieder, was manche Genies im Internet aufzustöbern imstande sind.

Vielen Dank, Zacherl!

Zacherl 9. Sep 2014 12:27

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
Zitat:

Zitat von Delphi-Laie (Beitrag 1271815)
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) :D Hier gibts übrigens Prototypen zu den genannten Funktionen und auch etwas fertigen Code zum Auslesen des PEBs zwecks Modul Enumeration.

Delphi-Laie 14. Sep 2014 15:44

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?
 
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


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:36 Uhr.
Seite 1 von 4  1 23     Letzte »    

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