Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi _STARTUPINFO.lpReserved2 [Transfer Data to a new process] (https://www.delphipraxis.net/182801-_startupinfo-lpreserved2-%5Btransfer-data-new-process%5D.html)

Snify 19. Nov 2014 09:47


_STARTUPINFO.lpReserved2 [Transfer Data to a new process]
 
Hab das schon vor längerem geschrieben und benutze es auch ab und zu...
Die Idee war, Informationen in einen Prozess ein zu bringen BEVOR er gestartet wird via der CreateProcess API. Dabei wollte ich auch binäre daten "versteckt" übermitteln (Parameter kann man global einsehen)...
Das einzigste Problem WAR, Windows Vista 64Bit, hab aber dann dazu einen Workaround gefunden ( getestet und funktioniert 8-) ), es angepasst und sollte nun ohne Probleme auch auf Windows 2000 (Bis Win8.1 x64) funktionieren.
Bitte beachtet dass manche Programme auf lpReserved2 angewiesen sind, hatte aber mit Delphi Applikationen noch keine Probleme.
Das Limit beschränkt sich auf 65535 bytes, jedoch kann man darüber ganz einfach hinaus und vor dem start nochmals Speicher anfordern mit VirtualAllocEx, etc. und weitere Zeiger miteinander kombinieren.

Mehr Infos gibt es hier http://www.catch22.net/tuts/undocumented-createprocess (Pass arbitrary data to a child process!)

Delphi-Quellcode:
program CreateProcessTest;

{$APPTYPE CONSOLE}

uses
  Windows;

  var
    SI                     : TStartupInfo;
    PI                     : TProcessInformation;
    Buffer                 : array of byte;
    WideStr                : WideString;
    VistaWorkAround        : DWORD;
  Const
    AuthString = WideString ('delphipraxis.net');

begin
  SetLength(Buffer, (Length (AuthString) * SizeOf(WideChar)) + SizeOf(DWORD) + SizeOf(WideChar) );
  if ParamStr(1) = '' then begin
    ZeroMemory(@Buffer[0], Length(Buffer));
    VistaWorkAround := ((( Length(Buffer) - 4) div 5) + 2);
    CopyMemory (@Buffer[0], @VistaWorkAround, SizeOf(DWORD));
    CopyMemory (@Buffer[4], @AuthString[1], Length(AuthString) * SizeOf(WideChar));
    Si.cbReserved2 := Length(Buffer);
    Si.lpReserved2 := @Buffer[0];
    if CreateProcess (pchar(paramstr(0)), '- CreateProcessTest' , NIL, NIL, False, 0, NIL, NIL, SI, PI) then begin
      Exit;
    end else begin
      writeln ('Error - CreateProcess failed.');
    end;
  end else begin
    GetStartupInfo(SI);
    if Si.lpReserved2 <> NIL then begin
      SetLength(Buffer, SI.cbReserved2 - SizeOf(DWORD));
      ZeroMemory(Buffer, Length(Buffer));
      CopyMemory (@Buffer[0], Pointer(Integer(SI.lpReserved2) + 4), Length(Buffer));
      if PWideChar(@Buffer[0]) = AuthString then begin
        writeln ('Success - lpReserved2 injection was successfull.');
      end else begin
        writeln ('Error - lpReserved2 injection was NOT successfull.');
      end;
    end else begin
      writeln ('Error - lpReserved2 is NIL');
    end;
  end;
  writeln ('');
  writeln ('Thank you for testing!');
  readln;
end.
Mein erster Beitrag, bitte nicht so kritisch, jedoch bin ich gerne eines besseren belehrt :thumb:

himitsu 19. Nov 2014 10:15

AW: _STARTUPINFO.lpReserved2 [Transfer Data to a new process]
 
Dein Code dient also dazu so erstmal nur dazu, einen "geheimen" Parameter zu übergeben, um den Start der Anwendung zu autorisieren?



Erste "Kritik": Verwende doch für Delphi-Codes bitte die [DELPHI]-Tags, anstatt der [CODE]-Tags.

Wenn per CopyMemory eh alles überschrieben wird, dann kann man sich das ZeroMemory davor auch sparen.

Da du danach den Buffer einfach so blind nach PWideChar casterst, dann solltes du den Buffer besser 2 Byte größer machen und das Ende immer mit #0 füllen.
Es knallt sonst eventuell, wenn in dem Buffer kein #0 vorkommt und das Lesen/Charkonvertieren dann unkontrolliert weitergeht.

Wenn du eh schon weißt, daß es eh immer nur maximal 64 KB werden können und das nicht wirklich viel ist (bei 2 GB oder mehr), könnte man die dynamischen Speicherreservierungen weglassen und einfach mit einem 64 KB + 2 Byte großem statischem Array arbeiten. (ist nicht schlimm, aber vereinfacht/verkürzt den Code etwas)

Oder du verwendest direkt ein WideChar-Array, anstatt des Byte-Array. Man kann im Debugger auch leichter nachgucken was drin steht und man spart sich die wilden Casts.
Delphi hat einen Automatismus für statische Char-Arrays (bei 0 beginnend) welche sich automatisch/implizit nach String casten, beim Auslesen/Vergleichen mit einem anderen String.




Und nun noch ein paar andere Varianten für Inter-process communication, welche mit dem CL-Beitrag nichts zu tun haben:
* Named MMF (memory mapped files)
* Named Pipes
Entweder mit einem "globalen" Namen oder der Name via Parameter übergeben.
http://msdn.microsoft.com/en-us/libr.../aa365574.aspx
http://de.wikipedia.org/wiki/Interprozesskommunikation
http://en.wikipedia.org/wiki/Inter-p..._communication

Man könnte auch mit aktuellen Laufzeitdaten (Uhrzeit auf ein paar Sekunden genau) und sonstige veränderliche und von beiden Programmen bekannte Parameter benutzen, um verschlüsselt+gehasht via Parameter ein Startpasswort zu übergeben. (egal ob das jemand sieht, denn es ist ja gleich wieder ungültig)
Eventuell auch kombiniert, indem man auch noch nachsieht, ob gleichzeitig einfach nur eine bestimmte NamedPipe/NamedMMF existiert oder eine bestimmte Datei in Temp liegt.

Snify 19. Nov 2014 10:32

AW: _STARTUPINFO.lpReserved2 [Transfer Data to a new process]
 
Zitat:

Zitat von himitsu (Beitrag 1280300)
Dein Code dient also dazu so erstmal nur dazu, einen "geheimen" Parameter zu übergeben, um den Start der Anwendung zu autorisieren?



Erste "Kritik": Verwende doch für Delphi-Codes bitte die [DELPHI]-Tags, anstatt der [CODE]-Tags.

Wenn per CopyMemory eh alles überschrieben wird, dann kann man sich das ZeroMemory davor auch sparen.

Da du danach den Buffer einfach so blind nach PWideChar casterst, dann solltes du den Buffer besser 2 Byte größer machen und das Ende immer mit #0 füllen.
Es knallt sonst eventuell, wenn in dem Buffer kein #0 vorkommt und das Lesen/Charkonvertieren dann unkontrolliert weitergeht.

Wenn du eh schon weißt, daß es eh immer nur maximal 64 KB werden können und das nicht wirklich viel ist (bei 2 GB oder mehr), könnte man die dynamischen Speicherreservierungen weglassen und einfach mit einem 64 KB + 2 Byte großem statischem Array arbeiten. (ist nicht schlimm, aber vereinfacht/verkürzt den Code etwas)

Oder du verwendest direkt ein WideChar-Array, anstatt des Byte-Array. Man kann im Debugger auch leichter nachgucken was drin steht und man spart sich die wilden Casts.
Delphi hat einen Automatismus für statische Char-Arrays (bei 0 beginnend) welche sich automatisch/implizit nach String casten, beim Auslesen/Vergleichen mit einem anderen String.




Und nun noch ein paar andere Varianten für Inter-process communication, welche mit dem CL-Beitrag nichts zu tun haben:
* Named MMF (memory mapped files)
* Named Pipes
Entweder mit einem "globalen" Namen oder der Name via Parameter übergeben.
http://msdn.microsoft.com/en-us/libr.../aa365574.aspx
http://de.wikipedia.org/wiki/Interprozesskommunikation
http://en.wikipedia.org/wiki/Inter-p..._communication

Man könnte auch mit aktuellen Laufzeitdaten (Uhrzeit auf ein paar Sekunden genau) und sonstige veränderliche und von beiden Programmen bekannte Parameter benutzen, um verschlüsselt+gehasht via Parameter ein Startpasswort zu übergeben. (egal ob das jemand sieht, denn es ist ja gleich wieder ungültig)
Eventuell auch kombiniert, indem man auch noch nachsieht, ob gleichzeitig einfach nur eine bestimmte NamedPipe/NamedMMF existiert oder eine bestimmte Datei in Temp liegt.

Danke für deinen Beitrag =)
Ich werd versuchen im Laufe der Tage alles ein wenig besser zu gestalten.
Warum ich hier spezifisch WideChars (& WideStrings) benutzt habe, weiß ich nicht mehr.

himitsu 19. Nov 2014 11:54

AW: _STARTUPINFO.lpReserved2 [Transfer Data to a new process]
 
Das WideString hilft dabei den Code auch vor Delphi 2009 nutzbar zu machen.
Es ging aber nicht um das Wide, sondern um das "unnötige" Byte dazwischen. :zwinker:
Wenn man es direkt auf WideChar mappt, dann bräuchte man nicht "böse" casten.

PS: Es gibt auch noch die Funktion Delphi-Referenz durchsuchenSetString.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:29 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