Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

  • Используйте атрибут 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")));

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

Ответ 2

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

void foo()

становится

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

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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