Как выполнить команду отладчика из приложения

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

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

Мое текущее решение вычисляет смещение этой частной функции относительно известной экспортированной функции во время сборки, используя nm. Это решение ограничивает возможности отладки, поскольку оно зависит от конкретной сборки общей библиотеки.

Предпочтительное решение должно обеспечивать восстановление адреса во время выполнения.

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

Каковы мои варианты?


person Kentzo    schedule 08.01.2020    source источник
comment
Что вы пытаетесь сообщить отладчику? Адрес функции? Можете ли вы просто распечатать его, а затем ввести вручную в отладчик?   -  person kaylum    schedule 08.01.2020
comment
Рассматриваемая функция взята из стороннего образа, находящегося вне моего контроля. Мне нужно восстановить его адрес по имени с помощью отладчика, чтобы я мог использовать его в другом месте в коде приложения.   -  person Kentzo    schedule 08.01.2020
comment
Звучит так, как будто вы действительно хотите запросить базу данных отладки для получения информации о символе.   -  person 1201ProgramAlarm    schedule 08.01.2020
comment
Я не совсем уверен, что этот символ доступен только через базу данных отладки: может также быть флаг компоновщика, о котором я не знаю.   -  person Kentzo    schedule 08.01.2020


Ответы (2)


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

Отладчик не волшебный единорог. Если таблица символов доступна отладчику, она также доступна и вашему приложению.

Мне нужно восстановить его адрес по имени с помощью отладчика...

Это совершенно неправильный подход.

Вместо использования отладчика прочитайте таблицу символов для библиотеки в вашем приложении и используйте полученную информацию для вызова целевой функции.

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

person Employed Russian    schedule 08.01.2020
comment
Моя целевая платформа — macOS, поэтому формат — MachO. Вы случайно не знаете, присутствуют ли в системе заголовки с необходимыми определениями структур? - person Kentzo; 08.01.2020
comment
@Kentzo Я мало что знаю о MacOS, за исключением того, что на ней можно построить и GDB, и LLDB. Для GDB не требовалось ничего, кроме Xcode, поэтому требуемые заголовки должны быть доступны в Xcode. - person Employed Russian; 08.01.2020
comment
Вы также можете анализировать двоичные файлы Mach-O и извлекать из них информацию о DWARF. Вот пример на Python: github.com/sevaa/dwex/blob/ master/dwex/formats.py Библиотеки filebytes и pyelftools доступны через pip. - person Seva Alekseyev; 07.02.2020

В lldb вы можете быстро найти адрес, установив символическую точку останова, если она известна отладчику каким-либо образом:

b symbolname

Если вы хотите вызвать неэкспортированную функцию из библиотеки без подключенного отладчика, есть несколько вариантов, но каждый из них будет ненадежным в долгосрочной перспективе:

  • Жестко закодируйте смещение из экспортированной библиотеки и вызовите exportedSymbol+offset (это будет работать для конкретной двоичной версии библиотеки, но, вероятно, сломается для чего-либо еще)
  • Попытайтесь найти двоичную подпись вашей неэкспортируемой функции в загруженной библиотеке. (чуть менее подвержен поломке, но двоичная подпись всегда может измениться)

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

Обновление:
Поскольку lldb каким-то образом знает об этом символе, я подозреваю, что он определен в команде загрузки Mach-O LC_SYMTAB вашей библиотеки. Чтобы убедиться, что вы можете проверить двоичный файл lib с помощью таких инструментов, как MachOView или MachOExplorer . Или otool от Apple, или jtool/jtool2 Джонатана Левина в консоли.

Вот пример из самой первой записи символа, полученной из LC_SYMTAB в MachOView. Это двоичный файл /usr/lib/dyld введите здесь описание изображения В данном примере 0x1000 — это виртуальный адрес. Ваша библиотека, скорее всего, будет 64-битной, поэтому ожидайте 0x10000000 и выше. Фактическая база рандомизируется ASLR, но вы можете проверить текущее значение с помощью

sample yourProcess

yourProcess является исполняемым файлом, использующим нужную вам библиотеку. Вывод должен содержать:

Binary Images:
       0x10566a000 -        0x105dc0fff  com.apple.finder (10.14.5 - 1143.5.1) <3B0424E1-647C-3279-8F90-4D374AA4AC0D> /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
       0x1080cb000 -        0x1081356ef  dyld (655.1.1) <D3E77331-ACE5-349D-A7CC-433D626D4A5B> /usr/lib/dyld
...

Это загруженные адреса 0x100000000, сдвинутые ASLR. Может быть больше нюансов, как именно эти адреса выбираются для dylib, но вы поняли идею.

Tbh Мне никогда не приходилось находить такой адрес программно, но это определенно выполнимо (поскольку /usr/bin/sample может это сделать).

Отсюда добиться чего-то практически:

  1. Проанализируйте заголовок Mach-o вашего двоичного файла lib (проверьте это и это для начала)
  2. Найдите LC_SYMTAB команду загрузки
  3. Найдите запись на основе текста вашего символа и найдите виртуальный адрес (материал красного поля)
  4. Рассчитайте ASLR и примените сдвиг

Существует некоторый C Apple API для разбора Mach-O. Также некоторый код Python существует в дикой природе (он популярен среди людей, занимающихся обратным проектированием).

Надеюсь, это поможет.

person Kamil.S    schedule 08.01.2020
comment
Вы хорошо разобрались в проблеме: мое текущее решение почти точно такое же, как вы предложили! Отредактировал вопрос с более подробной информацией. - person Kentzo; 08.01.2020
comment
Не могли бы вы уточнить синтаксический анализ MachO? - person Kentzo; 08.01.2020
comment
Добавляет некоторые ссылки, вы также можете проверить MachOView или MachOExplorer , хотя я бы рекомендовал придерживаться чего-то довольно простого. Также ознакомьтесь с существующими ответами на SO, которые охватывают некоторую обработку Mach-O, чтобы понять, как это делается. Прежде чем приступать к кодированию, я рекомендую проверить то, что я написал в MachOView, чтобы убедиться, что это действительно применимо к вашему случаю. - person Kamil.S; 08.01.2020
comment
Здорово, кажется, это проще, чем я думал. Нужно выяснить, как найти адрес загрузки библиотеки во время выполнения. - person Kentzo; 08.01.2020
comment
@Kentzo, пожалуйста, поделитесь своими выводами и / или кодом в качестве ответа, если вы двинетесь дальше, поскольку это довольно интересный случай. - person Kamil.S; 09.01.2020