Вставить статически связанные двоичные файлы
Существует хорошо известная техника для вставки динамически связанных двоичных файлов: создание разделяемой библиотеки и использование переменной LD_PRELOAD. Но это не работает для статически связанных двоичных файлов.
Одним из способов является написание статической библиотеки, которая вставляет функции и связывает ее с приложением во время компиляции. Но это не практично, потому что перекомпиляция не всегда возможна (подумайте о сторонних двоичных файлах, библиотеках и т. Д.).
Поэтому мне интересно, есть ли способ вставить статически связанные двоичные файлы в один и тот же LD_PRELOAD, работающий для динамически связанных двоичных файлов, т.е. без изменений кода или повторной компиляции существующих двоичных файлов.
Я заинтересован только в ELF на Linux. Так что не проблема, если потенциальное решение не является "портативным".
3 ответа
Одним из способов является написание статической библиотеки, которая вставляет функции и связывает ее с приложением во время компиляции.
Одна из сложностей такого промежуточного устройства заключается в том, что он не может легко вызвать исходную функцию (так как она имеет то же имя).
Компоновщик --wrap=<symbol>
Вариант может помочь здесь.
Но это не практично, потому что перекомпиляция
Перекомпиляция здесь не нужна, только перекомпоновка.
не всегда возможно (подумайте о сторонних двоичных файлах, библиотеках и т. д.).
Сторонние библиотеки работают нормально (перекомпоновка), но двоичные файлы сложнее.
Это все еще возможно сделать с использованием техники смещенного выполнения, но реализация довольно сложна, чтобы получить право.
Я предполагаю, что вы хотите вставить символы в основной исполняемый файл, полученный из статической библиотеки, что эквивалентно вставке символа, определенного в исполняемом файле. Таким образом, вопрос сводится к тому, возможно ли перехватить функцию, определенную в исполняемом файле.
Это невозможно (РЕДАКТИРОВАТЬ: по крайней мере, без большой работы - см. Комментарии к этому ответу) по двум причинам:
- по умолчанию символы, определенные в исполняемом файле, не экспортируются, поэтому недоступны для динамического компоновщика (вы можете изменить это с помощью
-export-dynamic
или экспортировать списки, но это имеет неприятные побочные эффекты производительности или обслуживания) - даже если вы экспортируете необходимые символы, ELF требует, чтобы динамический symtab исполняемого файла всегда сначала просматривался во время разрешения символов (см. раздел 1.5.4 "Область поиска" в dsohowto); Симтаб из
LD_PRELOAD
библиотека всегда будет следовать за исполняемым файлом и, следовательно, не сможет перехватить символы
То, что вы ищете, называется бинарным инструментарием (например, с использованием Dyninst или ptrace
). Идея состоит в том, что вы пишете программу-мутатор, которая присоединяет (или статически переписывает) вашу исходную программу (называемую mutatee) и вставляет код по вашему выбору в определенные моменты в mutatee. Основная проблема обычно заключается в поиске точек ввода с использованием API, предоставляемого механизмом инструментовки. В вашем случае, так как вы в основном ищете статические символы, это может быть довольно сложным и, вероятно, потребует эвристики, если у мутанта нет лишних динамических символов.