2010-02-01 8 views
12

Est-il possible d'exécuter un fichier exe inclus dans le projet en tant que ressource? Puis-je récupérer le fichier sous la forme d'un tableau d'octets et l'exécuter en mémoire?Comment exécuter un exécutable incorporé en tant que ressource

Je ne veux pas écrire le fichier dans un emplacement temporaire et l'exécuter ici. Je cherche une solution où je peux l'exécuter en mémoire. (Ce n'est pas un ensemble de .NET.)

+1

http://stackoverflow.com/questions/1224149/how-to-run-unmanaged-executable-from-memory-rather-than-disc –

+0

Pourquoi ne voulez-vous pas créer un fichier temporaire? – Kramii

+1

parce que je préfère exécuter du code propre sans avoir à créer des fichiers temporaires à chaque fois. si je le lance en mémoire, je n'ai pas à penser aux droits d'écriture dans le dossier temporaire. – MichaelD

Répondre

7

C'est tout à fait possible - je l'ai fait moi-même - mais c'est plutôt fiddly et plus de code managé. Il n'y a pas d'API .NET pour cela, ni d'API native pour PInvoke. Vous devrez donc manipuler la charge à la main, ce qui nécessitera une certaine connaissance du format de fichier PE (Portable Executable) utilisé pour les modules tels que DLL et EXE - http://msdn.microsoft.com/en-us/magazine/cc301805.aspx. Il y aura beaucoup de manipulation de pointeur (imposant l'utilisation de blocs {} dangereux) et PInvoke.

Commencez par charger le fichier PE en mémoire (ou utilisez MapViewOfFile). Un fichier PE est composé de différentes sections contenant du code, des données ou des ressources. Les décalages de chaque section dans le fichier ne correspondent pas toujours aux décalages en mémoire prévus, donc quelques ajustements mineurs sont nécessaires.

Chaque fichier PE suppose qu'il sera chargé à une certaine adresse de base dans la mémoire virtuelle. À moins que vous ne puissiez vous en assurer, vous devrez parcourir la table de relocalisation du fichier PE pour ajuster les pointeurs en conséquence.

Chaque fichier PE a également une liste de table d'importation que d'autres fonctions de DLL qu'il veut appeler. Vous devrez parcourir cette table et appeler LoadLibrary()/GetProcAddress() pour remplir chaque importation.

Ensuite, la protection de la mémoire doit être correctement définie pour chaque section. En-tête de chaque section note la protection qu'il veut, il suffit donc d'appeler VirtualProtect() pour chaque section avec les bons drapeaux. Au minimum, vous aurez besoin de VirtualProtect le module chargé avec PAGE_EXECUTE_READWRITE ou il est peu probable que vous puissiez exécuter du code.

Enfin une DLL vous devez appeler son point d'entrée, dont l'adresse se trouve dans l'en-tête de PE; vous pouvez alors appeler librement les fonctions exportées.

Puisque vous voulez exécuter un fichier EXE, vous avez des maux de tête supplémentaires. Vous pouvez simplement créer un nouveau thread et appeler le point d'entrée du fichier EXE, mais de nombreux fichiers EXE peuvent être dérangés car le processus est configuré pour vous, pas le fichier EXE. Il peut également tuer votre processus quand il essaie de sortir. Vous pourriez donc lancer un nouveau processus - peut-être une autre copie de votre EXE principal avec des arguments spéciaux pour lui dire qu'il va exécuter du code différent - auquel cas vous devrez fenager l'EXE dans son espace mémoire. Vous voudrez probablement faire la plupart du travail ci-dessus dans le nouveau processus, pas l'ancien. Vous pouvez soit créer un canal nommé et envoyer les données d'un EXE à l'autre, soit allouer une zone de mémoire partagée nommée avec MapViewOfFile.Bien sûr, le fichier EXE peut encore se fâcher puisque le processus dans lequel il s'exécute n'est pas le sien.

Dans l'ensemble, il est beaucoup plus simple d'écrire dans un fichier temporaire, puis d'utiliser Process.Start().

Si vous voulez toujours le faire à la dure, jetez un oeil à cet exemple en code non managé: http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/. Cela ne couvre pas les exécutables, seulement les DLL, mais si le code ne vous effraie pas, vous devriez bien étendre le processus pour couvrir les exécutables.

+0

Le lien vers le code à la fin ne fonctionne plus – mgttlinger

+1

Fixe, merci. On dirait que la page originale a été déplacée. –

0

Son pas très facile de créer un nouveau processus à partir d'une image mémoire, toutes les fonctions du noyau sont orientées vers le chargement d'une image à partir du disque. Pour plus d'informations, reportez-vous à la section sur les processus du Windows NT/2000 native API reference. La page 161 présente un exemple de forking manuel d'un processus.

S'il est autorisé à exécuter le code à partir de votre propre processus, vous pouvez créer une petite DLL qui utilisent un pointeur sur l'exécutable de données et l'exécuter.

+0

page 161 n'est pas affiché :) – MichaelD

+0

Étrange. Voici un lien direct vers p161: http://books.google.com/books?id=Fp1ct-bKYdcC&lpg=PP1&ots=ciLzfYAKbI&dq=%22gary%20nebbett%22%20windows%20api&pg=RA1-PA161#v=onepage&q=&f= false –

1

Une façon beaucoup mieux est de créer un fichier DLL temporaire avec l'attribut FILE_FLAG_DELETE_ON_CLOSE. De cette façon, le fichier sera automatiquement supprimé lorsqu'il ne sera plus utilisé.

Je ne pense pas qu'il y ait un moyen de charger DLL à partir d'une mémoire (au lieu d'un fichier).

+0

Un problème avec ce drapeau est que dès que vous fermez le fichier, il sera supprimé (par exemple, dès que vous avez écrit le fichier sur le disque dur, il sera supprimé). Et vous * devez * fermer votre handle au fichier avant de pouvoir "l'exécuter", car le fichier sera verrouillé par votre processus - et vous ne pourrez pas l'exécuter. –

Questions connexes