Как выполнить исполняемый файл, встроенный в качестве ресурса - PullRequest
12 голосов
/ 01 февраля 2010

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

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

Ответы [ 3 ]

7 голосов
/ 26 февраля 2010

Это вполне возможно - я сделал это сам - но это не так просто, как в управляемом коде. Для него нет .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, но если код в нем не пугает вас, вы можете расширить процесс, чтобы охватить исполняемые файлы.

1 голос
/ 26 февраля 2010

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

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

0 голосов
/ 01 февраля 2010

Создать новый процесс из образа памяти не очень просто, все функции ядра направлены на загрузку образа с диска. Для получения дополнительной информации см. Раздел процесса Ссылка на собственный API Windows NT / 2000 - на странице 161 приведен пример ручного разветвления процесса.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...