Einzelnen Beitrag anzeigen

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