#c #linux #clang #linker-errors #reverse-engineering
#c #linux #clang #компоновщик-ошибки #обратная разработка
Вопрос:
Сегодня я обнаружил странное поведение clang с конструкторами. Когда g экспортирует _ZN14string_wrapperC1EPcm
и _ZN14string_wrapperC2EPcm
конструкторы. Только экспорт Clang _ZN14string_wrapperC2EPcm
, и моя внедренная библиотека не может разрешить symbol во время выполнения.
Примечание: -rdynamic
указывает компилятору экспортировать все символы из двоичного файла. Следовательно, символы связаны во время выполнения. Почему в моем коде нет объявлений этой функции.(см injector.cpp )
Пожалуйста, посоветуйте мне, как исправить ошибку времени выполнения. Я думаю, нужно что-то вроде библиотеки импорта из Windows. Дело в том, что нужно сообщить компоновщику, что символы объявлены в моем ./output/binary
файле. Теперь он помечен как UND (неопределенный) и будет разрешен во время выполнения.
$ readelf -Ws output/injector.so | grep _ZN
2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _ZN14string_wrapper5printEv
3: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _ZN14string_wrapperC1EPcm
binary.cpp:
#include <cstdio>
class string_wrapper {
private:
char *data;
size_t size;
public:
string_wrapper(char *data, size_t size) : data(data), size(size) {}
void print() {
printf("%sn", data);
}
};
int main() {
char data[] = "regular string from this executable";
string_wrapper string = string_wrapper(data, sizeof(data));
string.print();
return 0;
}
injector.cpp:
#include <cstdio>
class string_wrapper {
private:
char *data;
size_t size;
public:
string_wrapper(char *data, size_t size);
void print();
};
__attribute__((constructor))
static void injector_init() {
puts("injected into process");
char data[] = "custom string from injector.so";
string_wrapper string = string_wrapper(data, sizeof(data));
string.print();
}
Makefile:
all: targets binary injector run
targets:
mkdir -p output
binary:
clang -rdynamic binary.cpp -o output/binary
injector:
clang -fPIC -shared injector.cpp -o output/injector.so
run:
LD_PRELOAD=./output/injector.so ./output/binary
$ make
mkdir -p output
clang -rdynamic binary.cpp -o output/binary
clang -frewrite-imports -fPIC -shared injector.cpp -o output/injector.so
LD_PRELOAD=./output/injector.so ./output/binary
injected into process
./output/binary: symbol lookup error: ./output/injector.so: undefined symbol: _ZN14string_wrapperC1EPcm
Makefile:9: recipe for target 'run' failed
make: *** [run] Error 127
Комментарии:
1. Ваш код нарушает одно правило определения, потому что два определения
string_wrapper
не идентичны. Поведение не определено. Поместите определение вашего класса в заголовочный файл, а#include
его — в оба источника.2. @n.’местоимения’m. спасибо, но это всего лишь пример. Кроме того, у меня обычно нет исходного кода
binary.cpp
, и заголовки this были бы перепроектированы.3. Я не могу сказать вам, что не так с кодом, который я не вижу. Если у вас возникли проблемы с каким-либо другим кодом, пожалуйста, опубликуйте этот другой код. Если у вас возникли проблемы с обратным проектированием чего-либо, пожалуйста, задайте вопрос о обратном проектировании.
4. @n.’местоимения’m. нет, этот вопрос больше связан с ошибками компоновщика. Ограничениями является невозможность изменения флагов компиляции для двоичного файла. Можно коснуться только библиотеки инжекторов.
5. Пожалуйста, укажите свое ограничение и все остальное, что вы можете найти важным в самом вопросе. В любом случае,
string_wrapper
конструктор не экспортируется, потому что он не существует как отдельный символ. Он встроенный. Вы ничего не можете с этим поделать.