Autor Beitrag
Radioactive
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 179

Win 98, Win XP Home SP2
D3 Prof, D7 Pers, D2005 Pers
BeitragVerfasst: So 31.10.04 14:46 
Ich habe ein Programm mit CREATETOOLHLEP32SNAPSHOT und TERMINATEPROCESS geschrieben, dass andere Prozesse killen kann und dass seine Arbeit gut verrichtet. Nun bin ich auf folgendes Problem gestoßen: wenn ich z.B. zwei mal den Editor laufen habe, heißen beide Prozesse "notepad.exe", nur die PID unterscheidet sich.
Das Programm, dass ich abschießen will (ein von mir selbst programmiertes Programm) unterscheidet sich von seinem "gleichnamigen Bruder" nur durch einen Parameter.

:?: Nun die eigentliche Frage: Gibt es eine Möglichkeit, bei einem laufenden Programm/Prozess auszulesen, mit welchen/welchem Parameter es gestartet wurde?

Es ist z.B. mit dem Process Explorer von Sysinternals möglich, die "Command line" eines Programms/Prozesses in den Properties auszulesen.

Danke schon mal im Voraus,
Radioactive


Moderiert von user profile iconKlabautermann: Topic aus Off Topic verschoben am So 31.10.2004 um 15:42
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: So 31.10.04 16:08 
Das kannst du mir Suche im MSDN VIRTUALQUERYEX auslesen.

_________________
Ciao, Sprint.
uall@ogc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: So 31.10.04 18:01 
VirtualQuery schaut doch nur nach einem bestimmten speicherbeichnach, welche rechte der hat etc. damit kann man (glaube ich) nicht achschaun mit welchen parameter der preozess gestartet wurde
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: Mo 01.11.04 00:30 
uall@ogc hat folgendes geschrieben:
VirtualQuery schaut doch nur nach einem bestimmten speicherbeichnach, welche rechte der hat etc. damit kann man (glaube ich) nicht achschaun mit welchen parameter der preozess gestartet wurde

VirtualQueryEx in Verbindung mit ReadProcessMemory. Bei Adresse $00020498 sollte der Environment Block anfangen und danach kommen diese geheimnisvollen Informationen die der Fragesteller haben möchte.

_________________
Ciao, Sprint.
uall@ogc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Mo 01.11.04 14:24 
trotzdem kann man mit VirtualQuery das net auslesen, mit ReadProcessmemory schon eher
VirtualQuery schaut nur nach ob der speicher da ist
ausserdem sollte man nen VirtualProectEx noch drüber laufen lassen (oder net ;P)
Radioactive Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 179

Win 98, Win XP Home SP2
D3 Prof, D7 Pers, D2005 Pers
BeitragVerfasst: Mi 03.11.04 19:41 
Titel: hää?
Danke, aber ich ich kapier nicht wirklich viel. :shock:
Könntet ihr nicht mal ein anschauliches beispiel posten (z.b. eine funktion, in die man die PID einsetzt und die dann die Command line zurückgibt)?
Was ist VirtualQueryEx? Und ReadProcessMemory? Wie benutzt man das?
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: Mi 03.11.04 20:27 
Bei jedem erstellten Win32 Prozess wird an der Adresse $20000 eine Datenstruktur gespeichert, die in Visual C++ so aufgebaut ist...
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
typedef struct _RTL_USER_PROCESS_PARAMETERS {
  ULONG                   MaximumLength;
  ULONG                   Length;
  ULONG                   Flags;
  ULONG                   DebugFlags;
  PVOID                   ConsoleHandle;
  ULONG                   ConsoleFlags;
  HANDLE                  StdInputHandle;
  HANDLE                  StdOutputHandle;
  HANDLE                  StdErrorHandle;
  UNICODE_STRING          CurrentDirectoryPath;
  HANDLE                  CurrentDirectoryHandle;
  UNICODE_STRING          DllPath;
  UNICODE_STRING          ImagePathName;
  UNICODE_STRING          CommandLine;
  PVOID                   Environment;
  ULONG                   StartingPositionLeft;
  ULONG                   StartingPositionTop;
  ULONG                   Width;
  ULONG                   Height;
  ULONG                   CharWidth;
  ULONG                   CharHeight;
  ULONG                   ConsoleTextAttributes;
  ULONG                   WindowFlags;
  ULONG                   ShowWindowFlags;
  UNICODE_STRING          WindowTitle;
  UNICODE_STRING          DesktopName;
  UNICODE_STRING          ShellInfo;
  UNICODE_STRING          RuntimeData;
  RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
}
 RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

Meine Erfahrungen haben gezeigt, das das Auslesen nur bedingt mit Delphi möglich ist (WideString/WideChar). Mit den Funktionen wcsncpy, wcslen & Co. aus der MSVCRT.DLL klappt es schon besser.

_________________
Ciao, Sprint.
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: Mi 03.11.04 20:30 
@Admins & Mods: Darf ich meine eigenen Beiträge nicht mehr editieren?



ausblenden Quelltext
1:
2:
3:
4:
5:
6:
typedef struct _RTL_DRIVE_LETTER_CURDIR {
  USHORT                  Flags;
  USHORT                  Length;
  ULONG                   TimeStamp;
  UNICODE_STRING          DosPath;
} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;

_________________
Ciao, Sprint.
.Chef
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1112



BeitragVerfasst: Mi 03.11.04 20:31 
Sprint hat folgendes geschrieben:
@Admins & Mods: Darf ich meine eigenen Beiträge nicht mehr editieren?

Ist im Moment deaktiviert (hab ich vorhin irgendwo gelesen) ...

_________________
Die Antworten auf die 5 häufigsten Fragen:
1. Copy(), Pos(), Length() --- 2. DoubleBuffered:=True; --- 3. Application.ProcessMessages bzw. TThread --- 4. ShellExecute() --- 5. Keine Vergleiche von Real-Typen mit "="!
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: Mi 03.11.04 20:36 
.Chef hat folgendes geschrieben:
Ist im Moment deaktiviert (hab ich vorhin irgendwo gelesen) ...

Okay. Danke.

_________________
Ciao, Sprint.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 03.11.04 20:39 
Welche Länge sind denn die WideChar-Strings? Oder sind die als PWChar realisiert und nehmen ein DWORD ein?

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: Do 04.11.04 04:14 
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
function GetProcessCmdLine(ProcessId: DWORD): String;
var
  ProcessHandle: THandle;
  MBI: TMemoryBasicInformation;
  Buffer: Pointer;
  SystemInfo: TSystemInfo;
  Size: DWORD;
  BytesRead: DWORD;
  Position: PByte;
begin

  FillChar(SystemInfo, SizeOf(TSystemInfo), 0);
  GetSystemInfo(SystemInfo);
  GetMem(Buffer, SystemInfo.dwPageSize);
  try
    ProcessHandle := OpenProcess(PROCESS_VM_READ or PROCESS_QUERY_INFORMATION, False, ProcessId);
    if ProcessHandle <> 0 then
    begin
      Size := SizeOf(TMemoryBasicInformation);
      FillChar(MBI, Size, 0);
      if VirtualQueryEx(ProcessHandle, Pointer($00020000), MBI, Size) = Size then
      begin
        if ReadProcessMemory(ProcessHandle, MBI.BaseAddress, Buffer, SystemInfo.dwPageSize, BytesRead) then
        begin
          Position := Buffer;
          Inc(Position, $498);
          Inc(Position, (Length(PWideChar(Position)) + 2) * SizeOf(WideChar));
          Inc(Position, (Length(PWideChar(Position)) + 2) * SizeOf(WideChar));
          Result := PWideChar(Position);
        end else
          RaiseLastOSError;
      end else
        RaiseLastOSError;
    end else
      RaiseLastOSError;
  finally
    FreeMem(Buffer);
  end;

end;


In Zeile 27 und 28 kann es ein Problem geben. Komischerweise sind die Strings manchmal mit einem Byte getrennt.
Richtig wäre aber ja zwei Bytes. Wenn es ein nullterminieter WideString ist, dann müsste ein Zeichen gleich zwei Bytes sein.
Irgendwie haut das aber nicht bei jedem Programm hin.

_________________
Ciao, Sprint.
Radioactive Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 179

Win 98, Win XP Home SP2
D3 Prof, D7 Pers, D2005 Pers
BeitragVerfasst: Fr 05.11.04 17:43 
Titel: Danke!
Erst mal Danke! Ein guter Quelltext! :D

Bei mir gibt es keine Probleme, nur ein paar Systemprozessen (z.B.: smss.exe) tritt ein Error auf. Wenn ich den Quelltext so wie beschrieben übernehme, werden die Commandline der meisten Prozesse angezeigt. Bei manchen fehlt jedoch z.B. das erste Anführungszeichen, (")
am Schluss steht jedoch eines. Auch kann ich die CmdLine von winlogon.exe nur korrekt auslesen, wenn ich den Quelltext wie folgt ändere oder bei anderen Prozessen anders ändere (Zeile 27/28):
ausblenden Quelltext
1:
2:
Inc(Position, (Length(PWideChar(Position)) + 1) * SizeOf(WideChar));
Inc(Position, (Length(PWideChar(Position)) + 5) * SizeOf(WideChar));

Dann kann ich aber andere CmdLines nicht mehr ansehen. Bei vielen wird auch gar nichts angezeigt. Es ist auch so, dass ich eine CmdLine mal nicht anzeigen kann, wenn ich aber mein Testprogramm neu starte, geht es doch.
Vielleicht liegt das aber auch an Delphi und es geht mit anderen Sprachen besser. Trotzdem, vielen Dank!

Wer Ideen hat, soll sich melden!

Radioactive
toms
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1099
Erhaltene Danke: 2



BeitragVerfasst: Fr 05.11.04 22:36 
Zitat:
Vielleicht liegt das aber auch an Delphi und es geht mit anderen Sprachen besser.


Hi,

Das liegt ganz sicher nicht an Delphi sondern an der Funktion.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Sa 06.11.04 01:04 
Ich hab mal mit einem RAM-Editor das Problem erforscht: Setzt mal Position auf das DWord an der Position $00020044. Dann braucht ihr zum einen die weiteren Inc-Befehle nicht und zum anderen erhaltet ihr damit sofort und zuverlässig die richtigen Informationen.

Achso: Einige Prozesse können nicht ausgelesen werden, da sie vom System gestartet werden. Um sie dennoch auslesen zu können, muss mn Admin sein und über gewisse Exployts Erbe des System-Prozesses werden. Danach sollte auch dies kein Problem mehr sein. Allerdings sei hier davon abgeraten, da eure Anwendung ansonsten mit großer Wahrscheinlichkeit früher oder später von Virenscannern eliminiert wird.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: Fr 03.12.04 09:12 
Hab mein Beispiel nochmal überarbeitet und sollte jetzt fehlerfrei laufen.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
function GetProcessCmdLine(ProcessId: DWORD): String;
var
  ProcessHandle: THandle;
  MBI: TMemoryBasicInformation;
  Buffer: Pointer;
  SystemInfo: TSystemInfo;
  Size: DWORD;
  CmdLine: WideString;
  LengthCmdLine: Word;
  PosCmdLine: Pointer;
begin

  Result := '';
  FillChar(SystemInfo, SizeOf(TSystemInfo), 0);
  GetSystemInfo(SystemInfo);
  GetMem(Buffer, SystemInfo.dwPageSize);
  try
    ProcessHandle := OpenProcess(PROCESS_VM_READ or PROCESS_QUERY_INFORMATION, False, ProcessId);
    if ProcessHandle <> 0 then
    begin
      Size := SizeOf(TMemoryBasicInformation);
      FillChar(MBI, Size, 0);
      if VirtualQueryEx(ProcessHandle, Pointer($00020000), MBI, Size) = Size then
        if ReadProcessMemory(ProcessHandle, MBI.BaseAddress, Buffer, SystemInfo.dwPageSize, DWORD(nil^)) then
        begin
          LengthCmdLine := PWord(Longint(Buffer) + $42)^;
          if LengthCmdLine < (MAX_PATH * 2then
          begin
            SetLength(CmdLine, LengthCmdLine);
            PosCmdLine := Pointer(PLongint(Longint(Buffer) + $44)^);
            if ReadProcessMemory(ProcessHandle, PosCmdLine, PWideChar(CmdLine), LengthCmdLine, DWORD(nil^)) then
              Result := Trim(Copy(CmdLine, 1, Pos(#0, CmdLine) - 1));
          end;
        end;
      CloseHandle(ProcessHandle);
    end;
  finally
    FreeMem(Buffer);
  end;

end;

_________________
Ciao, Sprint.
no1likeyou
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Di 07.08.07 11:45 
Titel: 64 Bit CommandLine
Bei 32Bit Prozessen funktioniert das gut aber leider nicht bei Prozessen die mit 64bit compiliert wurden.
Liegt das vielleicht an der Speicheradresse von VirtualQueryEx?

>> if VirtualQueryEx(ProcessHandle, Pointer($00020000), MBI, Size) = Size then

Wenn ja wie könnte man die je nach Prozess-Typ verbiegen?
Oder gibt es mittlerweile eine elegantere Lösung um an die CommandLine eines Prozesses zu gelangen?