Подтвердить что ты не робот

Как выполнить исполняемый файл, встроенный в качестве ресурса

Возможно ли выполнить exe файл, который включен в проект в качестве ресурса? Можно ли получить файл в виде байтового массива и выполнить его в памяти?

Я не хочу писать файл во временное место и выполнять его там. Я ищу решение, где я могу выполнить его в памяти. (Это не сборка .NET.)

4b9b3361

Ответ 1

Это вполне возможно - я сделал это сам, но это было странно и, более того, из управляемого кода. Для него нет .NET API, и нет встроенного API, для которого вы можете PInvoke. Таким образом, вам придется вручную определять нагрузку, что потребует некоторого знания формата файла PE (Portable Executable), используемого для таких модулей, как библиотеки DLL и EXE - http://msdn.microsoft.com/en-us/magazine/cc301805.aspx. Там будет много манипуляций с указателями (обязательное использование небезопасных {} блоков) и PInvoke.

Сначала загрузите PE файл в память (или используйте MapViewOfFile). PE файл состоит из разных разделов, содержащих код, данные или ресурсы. Смещения каждого раздела в файле не всегда соответствуют смещенным смещениям памяти, поэтому требуются небольшие корректировки.

Каждый PE файл предполагает, что он будет загружен с определенным базовым адресом в виртуальной памяти. Если вы не сможете этого сделать, вам нужно будет перемещать таблицу перемещения PE файлов, чтобы соответственно настроить указатели.

В каждом PE файле также есть таблица импорта, в которой перечислены функции других DLL-функций, которые она хочет вызвать. Вам нужно будет пройти эту таблицу и вызвать LoadLibrary()/GetProcAddress(), чтобы заполнить каждый импорт.

Затем защита памяти должна быть правильно установлена ​​для каждого раздела. Каждый заголовок раздела отмечает, какую защиту он хочет, поэтому он просто вызывает вызов VirtualProtect() для каждого раздела с правильными флагами. Как минимум вам понадобится VirtualProtect загруженного модуля с PAGE_EXECUTE_READWRITE или вы вряд ли сможете выполнить какой-либо код.

Наконец, для DLL вам нужно вызвать его точку входа, адрес которой можно найти в заголовке PE; вы можете свободно вызывать экспортированные функции.

Поскольку вы хотите запустить EXE, у вас есть дополнительные головные боли. Вы можете просто развернуть новый поток и вызвать из него точку входа EXE, но многие EXE могут расстраиваться, так как процесс настроен для вас, а не EXE. Он также может убить ваш процесс, когда он попытается выйти. Возможно, вы захотите создать новый процесс - возможно, еще одну копию вашего основного EXE со специальными аргументами, чтобы сказать, что он будет запускать какой-то другой код, - и в этом случае вам придется помещать EXE в его пространство памяти. Вероятно, вы захотите сделать большую часть работы над новым процессом, а не старым. Вы могли бы создать именованный канал и отправить данные через один EXE в другой или назначить именованную область общей памяти с помощью MapViewOfFile. Конечно, EXE может все еще расстраиваться, так как процесс его работы по-прежнему не является его собственным.

Всем гораздо проще просто записать во временный файл, а затем использовать Process.Start().

Если вы все еще хотите сделать это трудным способом, посмотрите на этот пример в неуправляемом коде: http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/. Это не распространяется на исполняемые файлы, а только на библиотеки DLL, но если код в нем вас не пугает, вы бы прекрасно расширили процесс для покрытия исполняемых файлов.

Ответ 2

Лучше всего создать временный DLL файл с атрибутом FILE_FLAG_DELETE_ON_CLOSE. Таким образом, файл будет удален автоматически, если он больше не используется.

Я не думаю, что есть способ загрузить DLL из памяти (а не файла).

Ответ 3

Нелегко создать новый процесс из образа памяти, все функции ядра направлены на загрузку изображения с диска. Подробнее см. В разделе процесса справочная ссылка на Windows NT/2000 для получения дополнительной информации. На странице 161 приведен пример ручного форматирования процесса.

Если это нормально для запуска кода из вашего собственного процесса, вы можете создать небольшую DLL, которая возьмет указатель на исполняемые данные и запустит их.