2009-07-29 7 views
26

Puisque je n'ai pas trouvé de réponse to the question asked previously here J'essaie une approche différente.Partage de mémoire entre deux processus (C, Windows)

Existe-t-il un moyen de partager la mémoire entre deux processus?

Le deuxième processus obtient l'information d'une injection car c'est un programme hérité qui n'est plus supporté. Mon idée est d'injecter du code là, dans la structure que je passe au programme injecté passer l'adresse (ou autre) à la mémoire de partage où se trouvent les données que je dois exécuter. Une fois que j'obtiens les données, je vais remplir mes propres variables à l'intérieur du fil injecté.

Est-ce possible? Comment?

Le code est apprécié.

EDIT:

Je pense que ce n'est pas clair, donc je vais clarifier. Je sais comment injecter. Je le fais déjà. Le problème ici est de transmettre des données dynamiques à l'injection.

+0

Quel genre de programme? Windows, interface graphique, console? –

+0

tous. Je peux lancer à partir d'un service, ou d'une interface graphique ou d'une console – wonderer

+0

Il y a un bon encapsuleur C++ facile à utiliser pour les fichiers mappés en mémoire dans le projet POCO. http://pocoproject.org/download/index.html Je l'ai trouvé après avoir essayé à plusieurs reprises d'utiliser les trucs de Boost, ce que d'autres personnes pourraient trouver facile à utiliser, mais j'ai trouvé brutalement difficile à utiliser correctement. –

Répondre

9

Vous pouvez essayer un memory-mapped file.

This donne un peu plus de détails étape par étape.

+0

Si vous ne voulez pas aller jusqu'aux appels Raw Win32, je suggère les classes de wrapper testées pré-construites du projet POCO. http://pocoproject.org/download/index.html Beaucoup plus léger et lisible que Boost. –

24

Bien que Windows prenne en charge la mémoire partagée via son file mapping API, vous ne pouvez pas injecter directement un mappage de mémoire partagée dans un autre processus, car MapViewOfFileEx ne prend pas d'argument de processus. Toutefois, vous pouvez injecter des données en allouant de la mémoire dans un autre processus en utilisant VirtualAllocEx et WriteProcessMemory. Si vous deviez copier dans un handle à l'aide de DuplicateHandle, puis injectez un stub qui appelle MapViewOfFileEx, vous pouvez établir un mappage de mémoire partagée dans un autre processus. Comme il semble que vous injecter du code de toute façon, cela devrait bien fonctionner pour vous.

Pour résumer, vous devez:

  • Créer une poignée de segment de mémoire partagée anonyme en appelant CreateFileMapping avec INVALID_HANDLE_VALUE pour hFile et NULL pour lpName.
  • Copiez cette poignée dans le processus cible avec DuplicateHandle
  • Allouer de la mémoire pour le code en utilisant VirtualAllocEx, avec flAllocationType = MEM_COMMIT | MEM_RESERVE et flProtect = PAGE_EXECUTE_READWRITE
  • Ecrivez votre code de dérivation dans cette mémoire, en utilisant WriteProcessMemory. Ce talon devra probablement être écrit en assembleur. Passez le HANDLE de DuplicateHandle en l'écrivant ici quelque part. Exécutez votre talon à l'aide de CreateRemoteThread. Le talon doit alors utiliser le HANDLE qu'il a obtenu pour appeler le MapViewOfFileEx. Les processus auront alors un segment de mémoire partagée commun.

Vous trouverez peut-être un peu plus facile si votre talon charge une bibliothèque externe - à savoir, l'ont suffit d'appeler LoadLibrary (trouver l'adresse de LoadLibrary est laissée en exercice au lecteur) et faire votre travail de la Le principal point d'entrée de la bibliothèque. Dans ce cas, l'utilisation de la mémoire partagée nommée risque d'être plus simple que de se disputer avec DuplicateHandle.Voir l'article MSDN sur CreateFileMapping pour plus de détails, mais, essentiellement, passer INVALID_HANDLE_VALUE pour hFile et un nom pour lpName.

Modifier: Puisque votre problème est de transmettre des données et pas d'injection de code réelle, voici quelques options.

  1. Utilisez une mémoire partagée de taille variable. Votre talon obtient la taille et le nom ou un handle de la mémoire partagée. Ceci est approprié si vous n'avez besoin d'échanger des données qu'une seule fois. Notez que la taille d'un segment de mémoire partagée ne peut pas être facilement modifiée après la création.
  2. Utilisez un named pipe. Votre talon obtient le nom ou une poignée du tuyau. Vous pouvez ensuite utiliser un protocole approprié pour échanger des blocs de taille variable - par exemple, écrivez size_t pour length, suivi du message réel. Ou utilisez PIPE_TYPE_MESSAGE et PIPE_READMODE_MESSAGE et observez ERROR_MORE_DATA pour déterminer où les messages se terminent. Ceci est approprié si vous devez échanger des données plusieurs fois.

Edit 2: Voici un croquis de la façon dont vous pourriez mettre en œuvre la poignée ou le stockage de pointeur pour votre talon:

.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... 

Vous pouvez aussi utiliser un nom fixe, ce qui est probablement plus simple.

+0

En tant que personne non-windows qui a seulement une idée théorique de ce qui se passe ici, devrais-je être un peu effrayé que ce possible? Existe-t-il un processus Unix comparable pour ce faire? –

+0

Oui, cela peut être fait dans unix. Utilisez PTRACE_POKEUSER pour frois registres pour un appel mmap anonyme. Une fois l'appel terminé, utilisez PTRACE_POKEDATA ou mmapping/proc/pid/mem pour écrire le code. Ensuite, demandez au code de faire quelque chose. – bdonlan

+0

Pour clarifier, ce qui précède était pour Linux. D'autres unix auront probablement quelque chose de similaire. Si vous voulez votre propre thread, appelez libpthread à partir de votre talon injecté. – bdonlan

1

Si vous parlez de Windows, le barrage routier principal est que les processus vivent chacun dans leur propre espace d'adressage virtuel. Vous ne pouvez malheureusement pas transmettre les adresses mémoire normales d'un processus à l'autre et obtenir les résultats attendus. (Les threads, d'autre part, vivent tous dans le même espace d'adressage, ce qui explique pourquoi les threads peuvent voir la mémoire de la même manière.)

Windows dispose cependant d'un espace mémoire partagé que vous devez faire très attention gérer correctement. Tout processus qui alloue de l'espace dans l'espace mémoire partagé est responsable de la libération explicite de cette mémoire. Ceci est en contraste avec la mémoire locale, qui disparaît plus ou moins lorsque le processus meurt. Voir this MSDN sample article pour des idées sur la façon dont vous pourriez utiliser l'espace de mémoire partagée pour conquérir le monde. Er, interface avec un logiciel existant. Ou quoi que ce soit :) Bonne chance tout ce que vous finissez par faire!

+0

Merci pour les commentaires. Ils clarifient un peu plus la situation. Cet article ne dit pas vraiment quel type d'API ou de méthodologies utiliser. – wonderer

+3

Le tas global est process-local dans win32. L'utiliser pour la mémoire partagée ne fonctionnera pas sur n'importe quoi basé sur NT (XP et amis), au moins. – bdonlan

+0

@bdonlan - ?? Peut-être que nous ne parlons pas de la même chose ici. Le tas global vit dans la mémoire globale, qui est partagée entre tous les processus. Toutes les allocations sont basées sur des poignées, pas sur des pointeurs, etc. Je pense que vous pourriez avoir raison si nous parlions. NET - Je ne me souviens pas si la terminologie CLR gérée a «global» signifie quelque chose d'autre. Bdonlan, pouvez-vous s'il vous plaît développer votre commentaire? Je voudrais m'assurer que je comprends de quoi je parle :) – Mike

0

Vous pouvez essayer d'utiliser Boost.Interprocess pour communiquer entre deux processus. Mais pour injecter du code dans un logiciel déjà existant, non pris en charge, vous devrez probablement utiliser @ bdonlan en utilisant WriteProcessMemory.

+0

Merci. Peux-tu élaborer? Je sais comment injecter, ce n'est pas le problème. – wonderer

+0

J'utilise writeprocessmemory. j'ai juste besoin de transmettre des informations qui changent parfois de taille – wonderer

1

Avez-vous essayé d'utiliser des canaux (pour la mémoire) ou même la sérialisation (pour vos objets)? Vous pouvez utiliser des fichiers pour gérer la mémoire entre les processus. Les prises sont également bonnes pour obtenir la communication entre les processus.

0

Le mappage de la mémoire est la solution, vous n'avez même pas besoin de créer un espace mémoire permanent, le secteur de la mémoire est hors de portée lorsque tous les processus qui le partagent sont arrêtés. Il y a d'autres façons aussi. Une manière simple et rapide de transmettre des données d'une application C à une autre est simplement d'utiliser le système d'exploitation. Au niveau de la ligne de commande, tapez app1 | app2. Cela fait app2 être la destination de sortie de app1 ou si une commande printf de app1 l'enverrait à app2 (ceci est appelé tuyauterie).

Questions connexes