Speicher zwischen zwei Prozessen teilen (C, Windows)

Lesezeit: 8 Minuten

Benutzer-Avatar
Wunderer

Da ich hier keine Antwort auf die zuvor gestellte Frage gefunden habe, versuche ich einen anderen Ansatz.

Gibt es eine Möglichkeit, den Speicher zwischen zwei Prozessen zu teilen?

Der zweite Prozess erhält die Informationen von einer Injektion, da es sich um ein veraltetes Programm handelt, das nicht mehr unterstützt wird.

Meine Idee ist, dort etwas Code einzufügen, in der Struktur, die ich an das injizierte Programm übergebe, übergebe die Adresse (oder was auch immer) an den Share-Speicher, wo sich die Daten befinden, die ich ausführen muss. Sobald ich die Daten erhalte, werde ich meine eigenen Variablen innerhalb des injizierten Threads füllen.

Ist das möglich? Wie?

Code wird geschätzt.

BEARBEITEN:

Ich denke, es ist nicht klar, also werde ich klären. Ich weiß, wie man spritzt. Ich mache es schon. Hier geht es darum, dynamische Daten an die Injektion zu übergeben.

  • Was für ein Programm? Windows, GUI, Konsole?

    – Chris K

    29. Juli 2009 um 15:13 Uhr

  • alle von ihnen. Ich kann von einem Dienst, einer GUI oder einer Konsole aus ausgeführt werden

    – Wunderer

    29. Juli 2009 um 15:24 Uhr

  • Es gibt einen schönen, einfach zu verwendenden C++-Wrapper für speicherabgebildete Dateien im POCO-Projekt. pocoproject.org/download/index.html Ich fand es, nachdem ich wiederholt mühsam versucht hatte, das Boost-Zeug zu verwenden, das andere Leute vielleicht einfach zu benutzen finden, aber ich fand es brutal schwierig, es richtig zu benutzen.

    – Warren P

    14. Juni 2013 um 5:37 Uhr


Benutzer-Avatar
bdonlan

Obwohl Windows Shared Memory durch seine unterstützt Dateizuordnungs-APIkönnen Sie eine Shared-Memory-Zuordnung nicht einfach direkt in einen anderen Prozess einfügen, da MapViewOfFileEx akzeptiert kein Prozessargument.

Sie können jedoch einige Daten einfügen, indem Sie Speicher in einem anderen Prozess zuweisen VirtualAllocEx und WriteProcessMemory. Wenn Sie ein Handle mit kopieren würden DuplicateHandledann injizieren Sie einen Stub, der anruft MapViewOfFileEx, könnten Sie in einem anderen Prozess eine Shared-Memory-Zuordnung erstellen. Da es so klingt, als würden Sie sowieso Code injizieren, sollte dies für Sie gut funktionieren.

Zusammenfassend müssen Sie Folgendes tun:

  • Erstellen Sie durch Aufrufen ein anonymes Shared-Memory-Segment-Handle CreateFileMapping mit INVALID_HANDLE_VALUE für hFile und NULL für lpName.
  • Kopieren Sie dieses Handle mit in den Zielprozess DuplicateHandle
  • Weisen Sie etwas Speicher für die Verwendung von Code zu VirtualAllocEx, mit flAllocationType = MEM_COMMIT | MEM_RESERVE und flProtect = PAGE_EXECUTE_READWRITE
  • Schreiben Sie Ihren Stub-Code mit in diesen Speicher WriteProcessMemory. Dieser Stub muss wahrscheinlich in Assembler geschrieben werden. Übergeben Sie den HANDLE von DuplicateHandle, indem Sie ihn irgendwo hier hineinschreiben.
  • Führen Sie Ihren Stub mit aus CreateRemoteThread. Der Stub muss dann den erhaltenen HANDLE zum Aufrufen verwenden MapViewOfFileEx. Die Prozesse haben dann ein gemeinsames Shared-Memory-Segment.

Sie finden es vielleicht etwas einfacher, wenn Ihr Stub eine externe Bibliothek lädt – das heißt, Sie rufen einfach LoadLibrary auf (das Finden der Adresse von LoadLibrary bleibt dem Leser als Übung überlassen) und erledigen Ihre Arbeit vom dllmain-Einstiegspunkt der Bibliothek aus. In diesem Fall ist die Verwendung von Named Shared Memory wahrscheinlich einfacher, als mit DuplicateHandle herumzuspielen. Siehe den MSDN-Artikel auf CreateFileMapping für weitere Details, aber übergeben Sie im Wesentlichen INVALID_HANDLE_VALUE für hFile und einen Namen für lpName.

Bearbeiten: Da Ihr Problem darin besteht, Daten und nicht die eigentliche Code-Injektion zu übergeben, sind hier einige Optionen.

  1. Verwenden Sie gemeinsam genutzten Speicher mit variabler Größe. Ihr Stub erhält die Größe und entweder den Namen oder ein Handle für den gemeinsam genutzten Speicher. Dies ist sinnvoll, wenn Sie nur einmal Daten austauschen müssen. Beachten Sie, dass die Größe eines gemeinsam genutzten Speichersegments nach der Erstellung nicht einfach geändert werden kann.
  2. Verwenden ein benanntes Rohr. Ihr Stub erhält den Namen oder ein Handle für die Pipe. Sie können dann ein geeignetes Protokoll verwenden, um Blöcke mit variabler Größe auszutauschen – schreiben Sie beispielsweise ein size_t für length, gefolgt von der eigentlichen Nachricht. Oder verwenden Sie PIPE_TYPE_MESSAGE und PIPE_READMODE_MESSAGE und achten Sie auf ERROR_MORE_DATA, um festzustellen, wo Nachrichten enden. Dies ist sinnvoll, wenn Sie Daten mehrfach austauschen müssen.

Bearbeiten 2: Hier ist eine Skizze, wie Sie die Handle- oder Zeigerspeicherung für Ihren Stub implementieren könnten:

.db B8            ;; mov eax, imm32
.dl handle_value  ;; fill this in (located at the start of the image + one byte)
;; handle value is now in eax, do with it as you will
;; more code follows...

Sie könnten auch einfach einen festen Namen verwenden, was wahrscheinlich einfacher ist.

  • Als Nicht-Windows-Person, die nur eine fiktive Vorstellung davon hat, was hier vor sich geht, sollte ich ein wenig erschrocken sein, dass dies möglich ist? Gibt es dafür einen vergleichbaren Unix-Prozess?

    – Newtonfälle

    29. Juli 2009 um 15:36 Uhr

  • Ja, das ist unter Unix möglich. Verwenden Sie PTRACE_POKEUSER, um Register für einen anonymen mmap-Aufruf auszulesen. Sobald der Aufruf abgeschlossen ist, verwenden Sie PTRACE_POKEDATA oder mmapping /proc/pid/mem, um Code einzuschreiben. Lassen Sie dann den Code tun, was auch immer.

    – bdonlan

    29. Juli 2009 um 15:41 Uhr

  • Zur Verdeutlichung, das Obige war für Linux. Andere Unixe werden wahrscheinlich etwas Ähnliches haben. Wenn Sie Ihren eigenen Thread haben möchten, rufen Sie libpthread von Ihrem injizierten Stub auf.

    – bdonlan

    29. Juli 2009 um 15:41 Uhr

  • Das klingt nach einer guten Lösung. Ich weiß, wie man injiziert, und ich habe bereits funktionierenden Code. Könnten Sie ein Beispiel posten, wie Sie das Ganze verwenden (was Sie gerade beschrieben haben). Vielen Dank!

    – Wunderer

    29. Juli 2009 um 15:48 Uhr

  • Nicht jetzt, fürchte ich. Ich bin mir sicher, dass Sie es herausfinden können – der schwierigste Teil von all dem ist das Schreiben des Stubs für die Code-Injektion. 🙂

    – bdonlan

    29. Juli 2009 um 15:52 Uhr

Benutzer-Avatar
Scott Marlowe

Sie können versuchen, a speicherabgebildete Datei.

Dies gibt ein bisschen mehr Schritt-für-Schritt-Detail.

  • Wenn Sie nicht bis zu Raw-Win32-Aufrufen gehen möchten, empfehle ich die vorgefertigten, getesteten Wrapper-Klassen des POCO-Projekts. pocoproject.org/download/index.html Weitaus leichter und lesbarer als Boost.

    – Warren P

    14. Juni 2013 um 5:39 Uhr

  • Können Sie eine speicherabgebildete Datei erstellen, aber die Datei berührt nie das Dateisystem und ist stattdessen eine speichergestützte Datei?

    – Brandon Ros

    9. Oktober 2021 um 22:49 Uhr

Sie können Shared Memory verwenden

  • Geteilte Erinnerung ist speicherabgebildete Dateien. Was versuchst du zu machen?

    – bdonlan

    29. Juli 2009 um 15:34 Uhr

  • Entschuldigung, ich meinte Rohre. Lassen Sie mich diesen Kommentar löschen

    – Wunderer

    29. Juli 2009 um 15:50 Uhr

Benutzer-Avatar
Hackus

Haben Sie versucht, Pipes (für Speicher) oder sogar Serialisierung (für Ihre Objekte) zu verwenden? Sie können Dateien verwenden, um den Speicher zwischen Prozessen zu verwalten. Sockets sind auch gut für die Kommunikation zwischen Prozessen.

Benutzer-Avatar
Gummibärchen

Speicherzuordnung ist der richtige Weg, Sie müssen nicht einmal einen permanenten Speicherplatz erstellen, der Speichersektor geht aus dem Bereich, wenn alle Prozesse, die ihn teilen, heruntergefahren werden. Es gibt auch andere Wege. Eine schnelle und schmutzige Möglichkeit, Daten von einer C-App an eine andere weiterzugeben, besteht darin, einfach das Betriebssystem zu verwenden. Geben Sie in der Befehlszeile ein app1 | app2. Dies bewirkt, dass app2 das Ausgabeziel von app1 ist, oder wenn ein printf-Befehl von app1 es an app2 senden würde (dies wird als Piping bezeichnet).

Sie können versuchen, es zu verwenden Boost.Interprozess zwischen zwei Prozessen zu kommunizieren. Aber um Code in eine bereits vorhandene, nicht unterstützte Software einzufügen, müssen Sie wahrscheinlich die Methode von @bdonlan verwenden WriteProcessMemory.

Benutzer-Avatar
Assad Ebrahim

Wenn Sie über Windows sprechen, besteht das Haupthindernis darin, dass alle Prozesse in ihrem eigenen virtuellen Adressraum leben. Sie können leider keine normalen Speicheradressen von Prozess zu Prozess weitergeben und die erwarteten Ergebnisse erhalten. (Threads hingegen befinden sich alle im selben Adressraum, weshalb Threads den Speicher auf die gleiche Weise sehen können.)

Windows hat jedoch einen gemeinsam genutzten Speicherplatz, den Sie sehr sorgfältig verwalten müssen, um ihn richtig zu verwalten. Jeder Prozess, der Speicherplatz im gemeinsam genutzten Speicherbereich zuweist, ist dafür verantwortlich, diesen Speicher explizit freizugeben. Dies steht im Gegensatz zum lokalen Speicher, der mehr oder weniger verschwindet, wenn der Prozess stirbt.

Sehen diesen MSDN-Beispielartikel für einige Ideen, wie Sie den gemeinsam genutzten Speicherplatz nutzen könnten, um die Welt zu erobern. Ähm, Schnittstelle mit Legacy-Software. Oder was auch immer 🙂 Viel Glück, was auch immer Sie tun!

  • Danke für die Kommentare. Sie klären die Situation ein wenig mehr. Dieser Artikel sagt jedoch nicht wirklich, welche Art von APIs oder Methoden verwendet werden sollen.

    – Wunderer

    29. Juli 2009 um 15:29 Uhr

  • Der globale Heap ist in win32 prozesslokal. Die Verwendung für gemeinsam genutzten Speicher funktioniert zumindest nicht auf NT-basierten Geräten (XP und Freunde).

    – bdonlan

    29. Juli 2009 um 15:31 Uhr

  • @bdonlan – ?? vielleicht reden wir hier nicht vom selben. Der globale Heap lebt im globalen Speicher, der von allen Prozessen gemeinsam genutzt wird. Alle Zuweisungen basieren auf Handles, nicht auf Zeigern usw. Ich denke, Sie könnten Recht haben, wenn wir über .NET sprechen. Ich erinnere mich nicht, ob die Terminologie der verwalteten CLR “global” etwas anderes bedeutet. bdonlan, kannst du bitte deinen Kommentar erweitern? Ich möchte sichergehen, dass ich verstehe, wovon ich rede 🙂

    – Mike

    29. Juli 2009 um 15:49 Uhr

  • “Die Windows-Speicherverwaltung bietet keinen separaten lokalen und globalen Heap. Daher sind die Funktionen GlobalAlloc und LocalAlloc im Wesentlichen gleich.” msdn.microsoft.com/en-us/library/aa366574%28VS.85%29.aspx

    – bk1e

    29. Juli 2009 um 16:15 Uhr

  • Ah! Jetzt verstehe ich meine Verwirrung. Ich habe völlig falsch “haufen” gesagt. Ich dachte an den gemeinsamen Speicherbereich. Das ist kein Haufen. 🙂 danke bdonlan!

    – Mike

    29. Juli 2009 um 16:33 Uhr

1382700cookie-checkSpeicher zwischen zwei Prozessen teilen (C, Windows)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy