Распаковка исполняемого файла из библиотеки в C / C ++ - PullRequest
2 голосов
/ 25 июня 2009

Я занимаюсь разработкой библиотеки, которая использует один или несколько вспомогательных исполняемых файлов в процессе ведения бизнеса. Моя текущая реализация требует, чтобы у пользователя был установлен вспомогательный исполняемый файл в системе в известном месте. Для правильной работы библиотеки вспомогательное приложение должно находиться в правильном месте и иметь правильную версию.

Я бы хотел убрать требование, чтобы система была настроена вышеописанным способом.

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

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

Можно ли выполнить такую ​​задачу без записи исполняемого файла на диск (возможно, какой-нибудь RAM-диск)? Я мог бы представить себе определенные антивирусные сканеры и другое защитное программное обеспечение, возражающее против такой операции. Есть ли другие проблемы, о которых я должен беспокоиться?

Библиотека разрабатывается на C / C ++ для кроссплатформенного использования в Windows и Linux.

Ответы [ 7 ]

6 голосов
/ 25 июня 2009

«Умный человек решает проблему. мудрый человек избегает этого. "- Альберт Эйнштейн

В духе этой цитаты я рекомендую вам просто связать этот исполняемый файл вместе с конечным приложением.

Только мои 2 цента.

2 голосов
/ 18 сентября 2009

Вы можете использовать xxd для преобразования двоичного файла в файл заголовка C.

$ echo -en "\001\002\005" > x.binary

$ xxd -i x.binary 
unsigned char x_binary[] = {
  0x01, 0x02, 0x05
};
unsigned int x_binary_len = 3;

xxd довольно стандартно в * nix системах и доступно в Windows с Cygwin или MinGW, или Vim также включает его в стандартный установщик. Это чрезвычайно кроссплатформенный способ включения двоичных данных в скомпилированный код.

Другой подход заключается в использовании objcopy для добавления данных в конец исполняемого файла - IIRC вы можете получить objcopy и использовать его для PE в Windows.

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

Если вы добавляете двоичные данные, они работают как с файлами Windows PE, так и с файлами * nix ELF - ни один из них не читает «предел» исполняемого файла.

Конечно, если вам нужно добавить несколько файлов, вы можете либо добавить файл tar / zip к вашему exe-файлу, либо вам понадобится немного более продвинутая структура данных, чтобы прочитать то, что было добавлено.

Вы также, вероятно, захотите UPX своих исполняемых файлов перед их добавлением.

Возможно, вас также заинтересует библиотека LZO , которая, как сообщается, является одной из самых быстро распаковывающихся библиотек сжатия. У них есть библиотека MiniLZO, которую вы можете использовать для очень легкого декомпрессора. Однако библиотеки LZO лицензированы по GPL, так что может означать, что вы не можете включить его в свой исходный код, если ваш код также не GPL. С другой стороны, есть коммерческие лицензии.

1 голос
/ 18 сентября 2009

Qt имеет отличный метод для достижения этой цели: QResource

"Система ресурсов Qt является независимым от платформы механизмом хранения двоичных файлов в исполняемом файле приложения."

Вы не говорите, используете ли вы в настоящее время Qt, но говорите «C ++ для кроссплатформенного использования в Windows и Linux», поэтому, даже если вы его не используете, вы можете рассмотреть возможность запуска. *

1 голос
/ 25 июня 2009

Для правильной работы библиотеки вспомогательное приложение должно быть в правильном место

В Windows это будет каталог Program Files или System32?

Это может быть проблемой. Когда приложение установлено, особенно в корпоративной среде, оно обычно происходит в контексте с правами администратора. В Vista и более поздних версиях с включенным UAC (по умолчанию) это необходимо для записи в определенные каталоги. И большинство разновидностей Unix имеют разумные ограничения, подобные тому, что может запомнить каждый.

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

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

Сказав все это, вы говорите, что рассматриваете возможность распаковки помощников во временный каталог, так что, возможно, это все спорный вопрос.

1 голос
/ 25 июня 2009

Немного другой подход, чем использование массива char без знака, - поместить весь исполняемый файл в качестве ресурса библиотеки DLL. Во время выполнения вы можете сохранить двоичные данные как локальный временный файл и запустить приложение. Однако я не уверен, есть ли способ выполнить исполняемый файл в памяти.

0 голосов
/ 26 июня 2009

Что ж, моей первой мыслью было бы: что делает этот исполняемый файл-помощник, чего нельзя сделать в самом коде вашей библиотеки, возможно, при необходимости используя вторичный поток. Это может быть что-то, чтобы рассмотреть.

Но что касается самого вопроса ... Если ваша "библиотека" фактически упакована как dll (или даже exe), то, по крайней мере, Windows имеет относительно простую поддержку для встраивания файлов в вашу библиотеку.

Механизм ресурсов, который позволяет встраивать такие вещи, как информация о версии и значки, в исполняемые файлы, также может разрешать произвольные порции данных. Поскольку я не знаю, какую среду разработки вы используете, я не могу точно сказать, как это сделать. Но, грубо говоря, вам нужно создать пользовательский ресурс с типом «ФАЙЛ» или чем-то вроде этого и указать его на исполняемый файл, который вы хотите встроить.

Затем, когда вы хотите извлечь его, вы должны написать что-то вроде

HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_MY_EMBEDDED_FILE), "FILE");
HGLOBAL hResourceData = LoadResource(NULL, hResource);
LPVOID pData = LockResource(hResourceData);
HANDLE hFile = CreateFile("DestinationPath\\Helper.exe", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwBytesWritten = 0;
WriteFile(hFile, pData, SizeofResource(NULL, hResource), &dwBytesWritten, NULL);
CloseHandle(hFile);

(ввод вашего собственного желаемого пути, имени файла и любой соответствующей проверки ошибок, конечно)

После этого вспомогательный exe-файл существует как обычный exe-файл, и вы можете выполнить его, как обычно.

Для удаления файла после использования вы должны изучить флаги для CreateFile, в частности FILE_FLAG_DELETE_ON_CLOSE. Вы также можете посмотреть на использование MoveFileEx при объединении флага MOVEFILE_DELAY_UNTIL_REBOOT с NULL, переданным для нового имени файла. И, конечно, вы всегда можете удалить его в своем собственном коде, если можете сказать, когда закончился исполняемый файл.

Я недостаточно знаю об исполняемых файлах Linux, поэтому не знаю, доступна ли там подобная функция.

Если Linux не предоставляет какого-либо удобного механизма и / или если эта идея не соответствует вашим потребностям в Windows, то я полагаю, что ваша идея генерировать массив unsigned char из содержимого вспомогательного exe-файла будет следующим лучшим способ вставить exe в вашу библиотеку.

0 голосов
/ 25 июня 2009

В Windows есть способ запустить исполняемый файл из памяти, не записывая его на диск. Проблема в том, что из-за современных систем безопасности (DEP) это, вероятно, не будет работать на всех системах, и почти любой сканер антивирусных программ обнаружит его и предупредит пользователя.

Мой совет - просто упаковать исполняемый файл в ваш дистрибутив, это, безусловно, самый надежный способ добиться этого.

...