Как удалить строки из скомпилированного двоичного файла (.so)
Как удалить строки из /obfuscate скомпилированного двоичного файла? Цель состоит в том, чтобы избежать того, чтобы люди читали имена функций/методов внутри.
Это динамическая библиотека (.so), скомпилированная из кода С++ для Android с инструментами NDK (включая GCC)
Я компилирую с помощью -O3
и уже использую arm-eabi-strip -g mylib.so
для удаления отладочных символов, но когда я делаю strings mylib.so
, все имена функций/методов все еще доступны для чтения.
Ответы
Ответ 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
Они неизбежны. Эти строки - это средства, с помощью которых загрузчик связывает разделяемые библиотеки во время выполнения.