Как удалить строки из скомпилированного двоичного файла (.so)

Как я удаляю строки из / запутывают скомпилированный двоичный файл? Цель состоит в том, чтобы не читать людей названия функций/методов внутри.

Это - динамическая библиотека (.so) скомпилированный из кода C++ для Android с инструментами NDK (включает GCC),

Я компилирую с -O3 и уже используйте arm-eabi-strip -g mylib.so удалить отладочную информацию, но когда я делаю strings mylib.so все названия функций/методов все еще читаемы.

15
задан Stéphane 20 May 2010 в 12:12
поделиться

4 ответа

Эти строки находятся в таблице динамических символов , которая используется, когда библиотека загружается во время выполнения. readelf -p .dynstr mylib.so покажет эти записи.

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

Есть два основных способа сообщить компилятору, какие функции являются частными.

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

  2. Используйте атрибут gcc «visibility», чтобы пометить функции как видимые или скрытые. У вас есть два варианта: либо пометить все частные функции как скрытые, либо изменить видимость по умолчанию на скрытую с помощью параметра компилятора -fvisibility = hidden и отметить все общедоступные функции как видимые. Последнее, вероятно, лучший вариант для вас, поскольку это означает, что вам не нужно беспокоиться о том, что вы случайно добавите функцию и забудете пометить ее как скрытую.

Если у вас есть функция:

int foo(int a, int b);

, то синтаксис для пометки ее скрытой:

int foo(int a, int b) __attribute__((visibility("hidden")));

, а синтаксис для пометки ее видимой:

int foo(int a, int b) __attribute__((visibility("default")));

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

25
ответ дан 1 December 2019 в 01:45
поделиться

Есть некоторые коммерческие обфускаторы, которые достигают этого. По сути, они переписывают все символы на ходу. Что-то вроде этого:

void foo()

становится

void EEhj_y33() // usually much, much longer and clobbered

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

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

Я не рекомендую их использовать, но они доступны. Простая обфускация значимых имен символов не остановит того, кто решил узнать, как работает ваша библиотека/программа. Кроме того, вы ничего не сможете сделать с тем, кто отслеживает системные вызовы. Действительно, в чем смысл? Некоторые утверждают, что это помогает держать "случайного наблюдателя" на расстоянии, я же утверждаю, что тот, кто выполняет ltrace strace и strings, обычно является кем угодно, только не случайным наблюдателем.

Если только вы не имеете в виду строковые литералы , а не символы ? С ними ничего нельзя поделать, если только вы не храните литералы в зашифрованном формате, который ваш код должен расшифровать перед использованием. Это не просто трата, а вопиющая трата, не приносящая никакой пользы.

7
ответ дан 1 December 2019 в 01:45
поделиться

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

-2
ответ дан 1 December 2019 в 01:45
поделиться

Предполагая, что вы правильно указали скрытую видимость для g ++ для всех ваших исходных файлов (как рекомендовали другие авторы), есть вероятность, что вы столкнулись с этой ошибкой GCC: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38643

Попробуйте сбросить отображаемые символы в вашем двоичном файле ( readelf -Wa mylib.so | c ++ filter | less ); Если после разборки вы видите только символы vtable и VTT, то ошибка gcc может быть вашей проблемой.

Изменить: если можете, попробуйте GCC 4.4.0 или более позднюю версию, поскольку она там исправлена.

3
ответ дан 1 December 2019 в 01:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: