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?

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 2 von 4     12 34   
Benutzerbild von Zacherl
Zacherl

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

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 14. Sep 2014, 17:29
Darf ich Dich deshalb fragen, ob Du das Beispielprogramm selbst einmal zum Laufen brachtest, und, falls ja, woher Du die beiden letztgenannten Units bezogst?
Leider nein Welche Deklarationen fehlen denn ohne die beiden Units? Vielleicht kann man die Klassen aus anderen Quellen rekonstruieren.
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
 
#12

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 14. Sep 2014, 18:02
Welche Deklarationen fehlen denn ohne die beiden Units? Vielleicht kann man die Klassen aus anderen Quellen rekonstruieren.
Danke für Deine Hilfsbereitschaft!

Ohne die beiden letztgenannten Units geht es in der Zeile

function GetPeb32(ph : THandle; var PEB : TPeb32):Boolean;

los, dort findet der Compilter den Typ TPeb32 nicht, dito weiter unten mit TPeb64.

Weiter geht es mit
Delphi-Quellcode:
Function PEB32ProcName(ph : THandle; Base:boolean):String;

var PEB : TPeb32;
  LdrData : TPebLdrData32;
  LdrModule : TLdrDataTableEntry32;
dort findet er den 2. und 3. Typ der var-Listung nicht.

Die paar anderen Kleckermeldungen gehen anscheinend darauf zurück, daß diese Typen unbekannt sind.

Nochmals besten Dank und viele Grüße

Delphi-Laie
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

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

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 14. Sep 2014, 18:37
Du findest Nicos Units hier:
http://www.bendlins.de/nico/delphi/NcxWOW64.zip

// EDIT:
Ich habe die Datei mal angehängt, da das laut Lizenz erlaubt ist.
Angehängte Dateien
Dateityp: zip NcxWOW64.zip (109,9 KB, 12x aufgerufen)
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Delphi-Laie

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

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 14. Sep 2014, 18:47
Sebastian, Du bist ein Schatz! Ich suchte direkt nach den Unit-Dateinamen und war damit natürlich nicht erfolgreich.

Nochmals besten Dank Euch beiden!
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

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

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 14. Sep 2014, 19:54
Ich suchte direkt nach den Unit-Dateinamen und war damit natürlich nicht erfolgreich.
Habe ich auch:
Bei Google suchenNcxNtDef
erstes Ergebnis, ganz unten:
http://www.ic0de.org/archive/index.php/t-10798.html
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Delphi-Laie

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

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 14. Sep 2014, 20:58
Wie auch immer, ich kam bei der Suche jedenfalls nicht bis zum gewünschten Ziele.

Ich staune immer wieder, wie viele im Internet veröffentlichte Quelltexte mir Probleme bereiten, hier das von Zacherl verlinkte Beispielprogramm.

Hier meine Erfahrungen mit XE2:

1. Die Compilerdirektive {$IFDEF CPU64} erzeugte merkwürdige Fehler im {$Else}-Zweig (nachdem die 32-Bit-Compilierung fehlerfrei klappte!). Alle durch {$IFDEF WIN64} ersetzt, danach schien XE2 verstanden zu haben, was gemeint ist, denn es flutschte darauhin durch die 64-Bit-Abteilungen.

2. Einige wenige Typumwandlungen von Pointer nach einen Integertyp oder umgekehrt waren noch nötig. Dann war endlich auch das erste 64-Bit-Compilat erzeugt.

3. Programmstart: Der Prozedureinsprungspunkt einer der beiden Funktionen wurde nicht gefunden. Das wundert mich nicht, denn durch den Dependency Walker wußte ich schon, daß in der gewöhnlichen ntdll.dll die Funktionen NtWow64QueryInformationProcess64 und NtWow64ReadVirtualMemory64 gar nicht enthalten sind. Also explizit die ntdll.dll im syswow64-Pfad angegeben. Dann wurden die Funktionen gefunden, weil diese Fehlermeldung entfiel, dafür gab es aber auch wieder gleich zum Programmstart eine andere Fehlermeldung, nämlich daß die Anwendung nicht korrekt gestartet werden kann (inkl. einer Binäradresse). Das gleiche Verhalten hatte ich auch schon mit meinem ursprünglichen Programm, das die Kommandozeile unter 64 Bit abzufragen versuchte.

Von PEB unter 64 Bit lasse ich nunmehr definitiv ab und werde mich deshalb nun der WMI-Lösung meiner ursprünglichen Frage zuwenden.

Nochmals danke Euch beiden für Eure Hilfsbereitschaft und Geduld mit mir!

Geändert von Delphi-Laie (14. Sep 2014 um 21:06 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

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

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 14. Sep 2014, 22:17
Das wundert mich nicht, denn durch den Dependency Walker wußte ich schon, daß in der gewöhnlichen ntdll.dll die Funktionen NtWow64QueryInformationProcess64 und NtWow64ReadVirtualMemory64 gar nicht enthalten sind. Also explizit die ntdll.dll im syswow64-Pfad angegeben.
Das kann nicht funktionieren, denn die DLL unter SysWOW64 ist eine 32-Bit DLL. In einem 64-Bit Prozess kann diese nicht funktionieren.

Eigentlich sind die Funktionen auch dafür gedacht, dass du aus einem 32-Bit Programm auf die Informationen eines 64-Bit Programms zugreifen kannst.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

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

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 14. Sep 2014, 23:46
Das Problem mit den fehlenden Imports kann ich auch nicht nachvollziehen. Habe mal ein bisschen rumgespielt:
Delphi-Quellcode:
const
  {$IFDEF WIN32}
  OFFSET_PROCESSPARAMETERS = $10;
  OFFSET_COMMANDLINE = $40;
  {$ELSE}
  OFFSET_PROCESSPARAMETERS = $20;
  OFFSET_COMMANDLINE = $70;
  {$ENDIF}
  OFFSET_PROCESSPARAMETERSWOW64 = $20;
  OFFSET_COMMANDLINEWOW64 = $70;

function GetProcessCommandLineFromPEB(hProcess: THandle): String;
var
  Status: NTSTATUS;
  ReturnLength: UInt64;
  ProcessInfo: TProcessBasicInformation;
  ProcessParametersPointer: NativeUInt;
  CommandLine: TUnicodeString;
  {$IFDEF WIN32}
  IsWow64: BOOL;
  Wow64ProcessInfo: TWow64ProcessBasicInformation64;
  Wow64CommandLine: TWow64UnicodeString64;
  Wow64ProcessParametersPointer: UInt64;
  {$ENDIF}
begin
  Result := 'ERROR';
  {$IFDEF WIN32}
  if (not IsWow64Process(hProcess, IsWow64)) then
  begin
    RaiseLastOSError;
  end;
  if (not IsWow64) then
  begin
    // Query PEB base address
    Status := NtWow64QueryInformationProcess64(hProcess, ProcessBasicInformation,
      @Wow64ProcessInfo, SizeOf(Wow64ProcessInfo), @ReturnLength);
    if ((not NT_SUCCESS(Status)) or (ReturnLength <> SizeOf(Wow64ProcessInfo))) then
    begin
      RaiseLastOSError(RtlNtStatusToDosError(Status));
    end;
    // Read the ProcessParameters pointer
    Status := NtWow64ReadVirtualMemory64(hProcess, Wow64ProcessInfo.PebBaseAddress +
      OFFSET_PROCESSPARAMETERSWOW64, @Wow64ProcessParametersPointer,
      SizeOf(Wow64ProcessParametersPointer), @ReturnLength);
    if ((not NT_SUCCESS(Status)) or (ReturnLength <> SizeOf(Wow64ProcessParametersPointer))) then
    begin
      RaiseLastOSError(RtlNtStatusToDosError(Status));
    end;
    // Read the CommandLine UNICODE_STRING
    Status := NtWow64ReadVirtualMemory64(hProcess, Wow64ProcessParametersPointer +
      OFFSET_COMMANDLINEWOW64, @Wow64CommandLine, SizeOf(Wow64CommandLine), @ReturnLength);
    if ((not NT_SUCCESS(Status)) or (ReturnLength <> SizeOf(Wow64CommandLine))) then
    begin
      RaiseLastOSError(RtlNtStatusToDosError(Status));
    end;
    // Read the actual commandline
    SetLength(Result, Wow64CommandLine.Length div SizeOf(Result[1]));
    Status := NtWow64ReadVirtualMemory64(hProcess, Wow64CommandLine.Buffer,
      @Result[1], Wow64CommandLine.Length, @ReturnLength);
    if ((not NT_SUCCESS(Status)) or (ReturnLength <> Wow64CommandLine.Length)) then
    begin
      RaiseLastOSError(RtlNtStatusToDosError(Status));
    end;
    Exit;
  end;
  {$ENDIF}
  // Query PEB base address
  Status := NtQueryInformationProcess(hProcess, ProcessBasicInformation,
    @ProcessInfo, SizeOf(ProcessInfo), @ReturnLength);
  if ((not NT_SUCCESS(Status)) or (ReturnLength <> SizeOf(ProcessInfo))) then
  begin
    RaiseLastOSError(RtlNtStatusToDosError(Status));
  end;
  // Read the ProcessParameters pointer
  Status := NtReadVirtualMemory(hProcess, Pointer(NativeUInt(ProcessInfo.PebBaseAddress) +
    OFFSET_PROCESSPARAMETERS), @ProcessParametersPointer, SizeOf(ProcessParametersPointer),
    @ReturnLength);
  if ((not NT_SUCCESS(Status)) or (ReturnLength <> SizeOf(ProcessParametersPointer))) then
  begin
    RaiseLastOSError(RtlNtStatusToDosError(Status));
  end;
  // Read the CommandLine UNICODE_STRING
  Status := NtReadVirtualMemory(hProcess, Pointer(NativeUInt(ProcessParametersPointer) +
    OFFSET_COMMANDLINE), @CommandLine, SizeOf(CommandLine), @ReturnLength);
  if ((not NT_SUCCESS(Status)) or (ReturnLength <> SizeOf(CommandLine))) then
  begin
    RaiseLastOSError(RtlNtStatusToDosError(Status));
  end;
  // Read the actual commandline
  SetLength(Result, CommandLine.Length div SizeOf(Result[1]));
  Status := NtReadVirtualMemory(hProcess, CommandLine.Buffer, @Result[1], CommandLine.Length,
    @ReturnLength);
  if ((not NT_SUCCESS(Status)) or (ReturnLength <> CommandLine.Length)) then
  begin
    RaiseLastOSError(RtlNtStatusToDosError(Status));
  end;
end;
Zusätzlich brauchst du folgende Definitionen:
Delphi-Quellcode:
type
  NTSTATUS = LongInt;
  HANDLE = THandle;

// Set struct alignment and enum size for C compatibility
{$IFDEF WIN32}
  {$A4}
{$ELSE}
  {$A8}
{$ENDIF}
{$Z4}
type
  TProcessInfoClass = (
    ProcessBasicInformation,
    ProcessQuotaLimits,
    ProcessIoCounters,
    ProcessVmCounters,
    ProcessTimes,
    ProcessBasePriority,
    ProcessRaisePriority,
    ProcessDebugPort,
    ProcessExceptionPort,
    ProcessAccessToken,
    ProcessLdtInformation,
    ProcessLdtSize,
    ProcessDefaultHardErrorMode,
    ProcessIoPortHandlers,
    ProcessPooledUsageAndLimits,
    ProcessWorkingSetWatch,
    ProcessUserModeIOPL,
    ProcessEnableAlignmentFaultFixup,
    ProcessPriorityClass,
    ProcessWx86Information,
    ProcessHandleCount,
    ProcessAffinityMask,
    ProcessPriorityBoost,
    ProcessDeviceMap,
    ProcessSessionInformation,
    ProcessForegroundInformation,
    ProcessWow64Information,
    ProcessImageFileName,
    ProcessLUIDDeviceMapsEnabled,
    ProcessBreakOnTermination,
    ProcessDebugObjectHandle,
    ProcessDebugFlags,
    ProcessHandleTracing,
    MaxProcessInfoClass);

type
  TProcessBasicInformation = record
    ExitStatus: Cardinal;
    PebBaseAddress: PVOID;
    AffinityMask: NativeUInt;
    BasePriority: NativeUInt;
    UniqueProcessId: NativeUInt;
    InheritedFromUniqueProcessId: NativeUInt;
  end;
{$IFDEF WIN32}
  TWow64ProcessBasicInformation64 = record
    ExitStatus: Cardinal;
    Pad1: DWord;
    PebBaseAddress: UInt64;
    AffinityMask: UInt64;
    BasePriority: Cardinal;
    Pad2: DWord;
    UniqueProcessId: UInt64;
    InheritedFromUniqueProcessId: UInt64;
  end;
{$ENDIF}

  TUnicodeString = record
    Length: USHORT;
    MaximumLength: USHORT;
    Buffer: Pointer;
  end;
{$IFDEF WIN32}
  TWow64UnicodeString64 = record
    Length: USHORT;
    MaximumLength: USHORT;
    Pad1: DWord;
    Buffer: UInt64;
  end;
{$ENDIF}

{$IFDEF WIN32}
function NtWow64QueryInformationProcess64(ProcessHandle: HANDLE;
  ProcessInformationClass: TProcessInfoClass; ProcessInformation: PVOID;
  ProcessInformationLength: ULONG; ReturnLength: PUInt64): NTSTATUS; stdcall; external 'ntdll.dll';
function NtWow64ReadVirtualMemory64(ProcessHandle: HANDLE; BaseAddress: UInt64; Buffer: Pointer;
  BufferLength: UInt64; ReturnLength: PUInt64): NTSTATUS; stdcall; external 'ntdll.dll';
{$ENDIF}

function NtQueryInformationProcess(ProcessHandle: HANDLE;
  ProcessInformationClass: TProcessInfoClass; ProcessInformation: PVOID;
  ProcessInformationLength: ULONG; ReturnLength: PULONG): NTSTATUS; stdcall; external 'ntdll.dll';
function NtReadVirtualMemory(ProcessHandle: HANDLE; BaseAddress : PVOID; Buffer: PVOID;
  BufferLength: ULONG; ReturnLength: PULONG): NTSTATUS; stdcall; external 'ntdll.dll';
function RtlNtStatusToDosError(Status: NTSTATUS): ULONG; stdcall; external 'ntdll.dll';

function NT_SUCCESS(Status: NTSTATUS): BOOL;
begin
  Result := Status >= 0;
end;
Und der Aufruf wäre z.b. so:
Delphi-Quellcode:
procedure TForm2.Button1Click(Sender: TObject);
var
  hProcess: THandle;
begin
  hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_OPERATION or PROCESS_VM_READ,
    false, 3000);
  if (hProcess <> 0) then
  try
    MessageBox(0, PChar(GetProcessCommandlineFromPEB(hProcess)), 'Info', MB_ICONINFORMATION);
  finally
    CloseHandle(hProcess);
  end;
end;
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.269 Beiträge
 
Delphi 10.4 Sydney
 
#19

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 15. Sep 2014, 08:27
Hallo,

müssen das nicht packed records sein,
oder ist das Alignment in den Records irgendwie geändert worden?


Heiko
Heiko
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

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

AW: CommandLines der Prozesse unter Windows 64 Bit ermitteln?

  Alt 15. Sep 2014, 10:08
müssen das nicht packed records sein,
oder ist das Alignment in den Records irgendwie geändert worden?
Nein, ganz im Gegenteil DÜRFEN die Records sogar auf keinen Fall packed sein. So ziemlich jede Windows API Library, die ich kenne wird mit einem Struct Alignment von 4 (bzw. 8 Byte unter 64 Bit) kompiliert.
Hatte damit früher schon einigen Ärger, deshalb bin ich dazu übergegangen immer explizit {$A4/8} anzugeben, wenn ich irgendwelche Structs für die WinAPI deklariere.

Selbes Spiel mit den Enums. Delphi interpretiert (weiß nicht, ob das immer noch der Fall ist, aber früher war es so) Enums mit < 256 Elementen immer als Byte, wohingegen die meisten C/C++ Compiler Enums auf 4 Byte erweitern. Deshalb auch hier immer ein explizites {$Z4}.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 22:46 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