#c #linux #mips
Вопрос:
Я пытаюсь отладить API, используемый сторонним приложением. Стороннее приложение имеет конфигурацию, которую я считал невозможной:
Двоичный файл приложения содержит экспорт, необходимый для одной из зависимостей его общей библиотеки. То есть они динамически связали свою зависимость, но зависимость этой зависимости связана статически.
Это происходит в Linux на базе MIPS с древним ядром.
Я подтвердил это, используя Ghidra для разборки исполняемой/общей библиотеки.
В основном у нас есть двоичный файл и общий объект
file initApp
initApp: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
file libhyCoreSdk.so
libhyCoreSdk.so: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, stripped
objdump -T libhyCoreSdk.so | grep -i IMP_ISP_Open
00047900 DF *UND* 00000000 IMP_ISP_Open
initApp вызывает «coreAvInit» в libhyCoreSdk.so, а затем libhyCoreSdk.so вызывает IMP_ISP_Open() обратно в initApp.
Возможно, вы думаете: «Это не так уж необычно, вы можете сделать это с помощью обратных вызовов, передачи указателей, вызова dlsym и т. Д. и т. Д.». Но это не что-то из этого, это прямой импорт/экспорт символов, именно то, что вы ожидали бы увидеть, если бы Libhycore зависел от другой общей библиотеки.
Все это в стороне, моя настоящая проблема в том, что я пытаюсь выяснить, какие параметры передаются IMP_ISP_Open, и LD_PRELOAD не помогает этому странному/уникальному обстоятельству. У меня есть еще один пример приложения, которое вызывает те же API для версии API с общей библиотекой. Когда я использую LD_PRELOAD (загружаю небольшую программу-перехватчик, которую я написал) против этой версии, она отлично работает. Но когда я использую его против этой версии, которая ссылается на двоичный файл, он не работает.
Я надеюсь, что у кого-то есть идеи о том, как я могу перехватывать эти вызовы API.
Частичное Решение:
Дэниел Кляйнштейн дал мне хорошее начало. Я переименовал целевые функции из IMP_… в XMP_… (например, IMP_ISP_DisableSensor-> XMP_ISP_DisableSensor). Теперь датчик IMP_ISP_DisableSensor из моей LD_PRELOAD правильно выбран. К сожалению, я все еще сталкиваюсь с проблемами. Вызов dlsym(RTLD_DEFAULT, «XMP_ISP_DisableSensor») возвращает значение NULL без очевидной причины… Это означает, что я не могу перенаправить обратно к исходной функции.
Несмотря на то, что objdump показывает это:
objdump -T initApp_mod | grep -i XMP
0061fb5c g DF .text 00000338 Base XMP_FrameSource_CreateChn
00613c6c g DF .text 00000204 Base XMP_ISP_DisableSensor
006097f0 g DF .text 00000eb0 Base XMP_Encoder_CreateChn
Комментарии:
1. «но зависимость этой зависимости статически связана». но
file libhyCoreSdk.so
показывает, что она динамически связана? Чтоobjdump -T libhyCoreSdk.so
показываетIMP_ISP_Open
импорт?2. @DanielKleinstein Я добавил то, что он показывает. Честно говоря, это мне мало о чем говорит. Глядя на вывод readelf, я вижу, что IMP_ISP_Open-это динамический символ, но в списке .dynamic нет записи «initApp». (Что имеет смысл, не знаю, как это может быть)
3. В вашей общей библиотеке есть неопределенный символ, который разрешается исполняемым файлом, а не какой-либо общей библиотекой, указанной по мере НЕОБХОДИМОСТИ в динамическом разделе. Здесь нет ничего невозможного или необычного (или действительно статически связанного). (Это невозможно в мире Windows и библиотек DLL, но общие библиотеки не являются библиотеками DLL).
4. @n.1.8e9-где-моя-доля. Похоже, что это действительно так, и, возможно, мой фон Windows сделал это таким безумным. Но эта реальность не решает моих проблем с LD_PRELOAD. Есть какие-нибудь мысли по этому поводу? Почему символ LD_PRELOAD не имеет приоритета над символом из исполняемого файла?
5. @wd40bomber27
LD_PRELOAD
здесь не работает, потому что он не имеет приоритета над символами, экспортируемыми самим основным исполняемым файлом, — просто над символами, экспортируемыми общими библиотеками. Я не уверен, в чем именно заключается ваш случай (бинарное исследование? Производственный код?), Но в вашем случае я мог бы попробовать исправить сам двоичный файл, чтобы переименовать импортированный символ (или проще, переименовать экспортированный символ основного исполняемого файла), чтобы разрешитьLD_PRELOAD
подключение.
Ответ №1:
Ваша динамическая зависимость статически не связана с вашим основным исполняемым файлом. Когда динамическая зависимость загружается, выполняется поиск ее импорта и разрешается символом, экспортируемым исполняемым файлом — действительно, символы исполняемого файла всегда будут разрешаться раньше любых других динамических зависимостей.
К сожалению, это также препятствует вашему использованию LD_PRELOAD
.
LD_PRELOAD
не работает, потому что его введенная библиотека не имеет приоритета над символами, экспортируемыми самим основным исполняемым файлом, — только над символами, экспортируемыми общими библиотеками.
Если вы хотите перехватить вызов с помощью LD_PRELOAD
, грубым, но эффективным решением является исправление экспортированного символа основного исполняемого файла под другим именем — таким образом, он не будет разрешен при загрузке динамической зависимости, и ваша введенная библиотека может предоставить символ.
Комментарии:
1. Еще одна проблема, с которой я столкнулся, заключалась в том, что, что бы я ни делал, я не мог разрешить исходный (теперь переименованный) символ. По какой-то причине использование API DL не работало. Это изначально помешало мне перенаправить на исходные функции после моего символа LD_PRELOAD’d. Мое решение для этого было столь же грубым. Моя (MIPS-файл, работающий на древнем ядре Linux) платформа имеет нулевой ASLR. Посмотрев символы, которые я заменял с помощью objdump, я смог напрямую заменить вызов dl на исходное смещение. Спасибо за вашу помощь!