2010-10-27 3 views
9

Предположим, что у меня есть бинарный файл ELF, связанный динамически, и я хочу переопределить/перенаправить определенные вызовы библиотеки. Я знаю, что могу сделать это с помощью LD_PRELOAD, но я хочу, чтобы решение было постоянным в двоичном формате, независимо от среды, и это работает для двоичных файлов setuid/setgid, ни один из которых не может достичь LD_PRELOAD.Патч-код/​​символы в динамически связанный двоичный файл ELF

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

Пожалуйста, не дайте мне ответов по строке «Вы не хотите этого делать!» или «Это не переносимо!» То, над чем я работаю, - это способ сопряжения двоичных файлов с небольшими ABI-несовместимыми альтернативными реализациями совместно используемых библиотек. Под этой платформой стоит i386-linux (т. Е. 32-разрядная версия), если это имеет значение. Если я не ошибаюсь в том, что возможно, я мог бы написать некоторые инструменты для анализа файлов ELF и выполнения своих хаков, но я подозреваю, что есть фантастический способ использовать GNU-компоновщик и другие инструменты для этого, не набирая новый код.

+0

Я не знаю, если это что-нибудь для вас, но проверьте системную команду «nm» (возможно, вы уже знаете об этом). Дает довольно много информации о так. – Marm0t

+0

Ничего себе, трюк LD_PRELOAD выглядит забавно! Я тоже ищу способ сделать это в бинарном режиме. Моя проблема заключается в том, что мой двоичный код имеет символ, который не может разрешить компоновщик BeagleBone. – CJxD

ответ

5

Я предлагаю elfsh и др. инструменты из проекта ERESI, если вы хотите сами использовать файлы ELF. Совместимость с i386-linux не является проблемой, так как я сам использовал ее для этой же цели.

Соответствующие инструкции: here.

+0

Похоже, что это займет некоторое время, но я думаю, что это инструмент, который я искал. Благодаря! –

+0

Есть ли какая-либо * документация для ERESI? Я не могу найти «начало», примеры и т. Д. –

+0

Хм, похоже, что нет (все ссылки указывают на svn?). –

0

Вы можете обрабатывать некоторые динамические ссылки в самой программе. Прочтите справочную страницу для dlsym (3) в частности и dlopen (3), dlerror (3) и dlclose (3) для остальной части интерфейса динамической компоновки.

Простой пример - скажем, я хочу переопределить dup2 (2) из ​​libc. Я мог бы использовать следующий код (назовем его "dltest.c"):

#define _GNU_SOURCE 

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <dlfcn.h> 

int (*prev_dup2)(int oldfd, int newfd); 

int dup2(int oldfd, int newfd) { 
    printf("DUP2: %d --> %d\n", oldfd, newfd); 
    return prev_dup2(oldfd, newfd); 
} 

int main(void) { 
    int i; 

    prev_dup2 = dlsym(RTLD_NEXT, "dup2"); 
    if (!prev_dup2) { 
     printf("dlsym failed to find 'dup2' function!\n"); 
     return 1; 
    } 
    if (prev_dup2 == dup2) { 
     printf("dlsym found our own 'dup2' function!\n"); 
     return 1; 
    } 

    i = dup2(1,3); 
    if (i == -1) { 
     perror("dup2() failed"); 
    } 

    return 0; 
} 

Compile с:

gcc -o dltest dltest.c -ldl 

Функция статически dup2() перекрывает dup2() из библиотеки. Это работает, даже если функция находится в другом .c файле (и скомпилирована как отдельный .o).

Если ваши функции переопределения сами связаны динамически, вы можете использовать dlopen(), а не доверять компоновщику, чтобы получить библиотеки в правильном порядке.

EDIT: Я подозреваю, что если другая функция в переопределенной библиотеке вызывает переопределенную функцию, вместо нее вызывается функция оригинала, а не переопределение. Я не знаю, что произойдет, если одна динамическая библиотека вызовет другую.

+0

Я пытаюсь изменить двоичные файлы, а не источник. –

2

ld имеет опцию --wrap, которая позволяет вам заменить данный символ наподобие malloc символом, который вы назвали бы __wrap_malloc. С этим вы могли бы написать несколько заглушек для интересующих вас функций и связать их с соответствующей библиотекой.

+0

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

+0

R .: Я не понимаю, почему вы не можете делать то, что вы задали в своем вопросе, с тем, что я предлагаю. «__wrap_malloc' не требует вызова старого« malloc », он просто заменяет один символ другим символом. 'ld' - лучший инструмент для управления двоичными файлами, которые я знаю, портативными, гибкими, все, что вы просили. Но у вас, кажется, есть определенные типы ответов в вашей голове, которые не обязательно отражаются в вашем вопросе. –

+0

Если вы имеете в виду, что есть способ взять существующий исполняемый файл ELF и добавить в него код, чтобы определить некоторые символы, которые в противном случае были бы разрешены для общего кода библиотеки, используя только GNU 'ld', я бы хотел знать, как это сделать. Но, пожалуйста, имейте в виду, что входные программы, к которым это нужно применить, являются исполняемыми файлами ELF, а не '.o' -файлами или источником. –

1

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

Итак, я, кажется, имеет схожие USECASE, но я явно найти какие-либо изменения в существующие двоичные файлы неприемлемых (для меня), поэтому я ищу для автономного прокси подход: Proxy shared library (sharedlib, shlib, so) for ELF?