2009-06-25 2 views
2

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

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

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

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

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

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

+1

Поместите вспомогательную функцию в lib и fork(), но не выполните exec(). Не уверен в Windows, хотя – sigjuice

ответ

2

Вы можете использовать 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 и использовать его для PEs на Windows.

Один подход Мне немного лучше, чем просто добавить исходные данные прямо в конец исполняемого файла. В исполняемом файле вы ищете конец файла и читаете число, указывающее размер прикрепленных двоичных данных. Затем вы запрашиваете назад столько байтов и fread, что данные и скопируйте их в файловую систему, где вы можете рассматривать ее как исполняемый файл. Это, кстати, the way that many, if not all, self-extracting executables are created.

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

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

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

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

1

Немного другой подход, чем использование массива unsigned char *, состоит в том, чтобы поместить весь исполняемый двоичный файл в качестве ресурса dll. Во время выполнения вы можете сохранить двоичные данные в виде локального файла temp и выполнить приложение. Я не уверен, есть ли способ выполнить исполняемый файл в памяти.

6

«Умный человек решает проблему». A мудрый человек избегает этого ». - Albert Einstein

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

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

+0

Мне нравится цитата :) +1 –

+0

Моя цель - не заставлять разработчиков конечного приложения (будь то моя организация или сторонняя организация) управлять вспомогательными приложениями. – Marc

+1

@ Маркс, я понимаю, и я ценю ваши амбиции. Попробуйте. Запишите файл в ОЗУ и запустите его оттуда. Я не знаю, как это сделать, пожалуйста, напишите свое решение, если найдете его. Я нашел эту небольшую полезность, возможно, это поможет: http://deadnode.org/sw/bin2h/ – StackedCrooked

0

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

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

+0

DEP не проблема. Вам просто нужно сказать Windows, что теперь он должен обрабатывать блок памяти как код и больше не как данные. И этот вызов функции, очевидно, должен исходить из существующего кода. Даже программы, достаточно глупые для вызова gets(), впоследствии не будут отмечать этот буфер как исполняемый. – MSalters

1

Для библиотеки, чтобы функционировать должным образом помощник приложение должно быть в правильном месте

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

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

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

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

Имея сказал, что все, что вы говорите, вы рассматриваете распаковку помощников во временную директорию, так что, может быть, это все спорно.

0

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

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

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

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

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, то я полагаю, что ваша идея генерации беззнакового массива символов из содержимого вспомогательного exe будет следующей лучший способ встраивания exe в вашу библиотеку.

1

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

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

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

Смежные вопросы