Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жолнерович, LVEE-2018)

Материал из 0x1.tv

Версия от 21:22, 7 мая 2019; StasFomin (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Докладчик
Владислав Жолнерович.jpg
Владислав Жолнерович

Complex applications work with dynamically linked libraries. Statically linked applications would be very large and have lack of flexibility as with dynamic libraries, because one library can be used by several applications at once. The purpose of this report is precisely to focus on all low-level features of working with these libraries, including such mechanisms like ELF sections, symbol relocations, GOT(global offset table), PLT(procedure linkage table).


На примере языка программирования Си можно выделить три основных этапа с момента написания программного кода до работы получившейся программы в операционной системе.

Это препроцессинг, компиляция, компоновка/линковка. Остановимся на последнем этапе. К этому времени инструкции в процессе компиляции в основном сгенерированы. Компоновщик – это программа, которая выбирает адреса для всех символов(глобальные переменные и функции, либо вспомогательные debug-символы). Без компоновщика мы бы не могли делать раздельную компиляцию. Много обьектных файлов не нужно перекомпилировать с самого начала, если в них нету изменений и пересборка идет только в файлах с изменениями(прим. open office, linux kernel).

ELF – Executable and Linkable Format. Эти файлы можно разделить на три категории:

  • Relocatable files – .o (то что получается после компиляции) является элементом static libraries (.a), т.е. может включать 1 или больше.
  • Executable – программы после этапа линковки, готовые к запуску.
  • Shared – .so dynamic libraries, они должны быть скомпонованы с запускаемым файлом в run-time.

Релокация – это процесс подстановки символу его адреса. Static linker превращает первую категорию во вторую или третью. Dynamic linker подготавливает третью к выполнению.

Видео

on youtube

Посмотрели доклад? Понравился? Напишите комментарий! Не согласны? Тем более напишите.


Презентация

Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018).pdf

Thesis

Инструменты для анализа бинарных файлов =

Список таких инструментов включает:

  • readelf – получение специфичной для формата ELF информации.
  • objdump – дизассемблер, позволяет исследовать обьектные файлы разных форматов.
  • nm – просмотр символов, которые есть в ELF-файле.

В набор GNU Binutils также входят elfedit, elfdump и др., но в данном контексте они не понадобятся.

Структура ELF, содержимое секций

ELF-файл содержит 3 заголовка – File Header, Program Header, и Section Header. Заголовок ELF-файла содержит magic number 7f 45 4c 46 ( 7f + ascii коды букв ELF) и указатели на Program Header и Section Header.

Program Header формируется при помощи компоновщика и содержит информацию о сегментах. Сегменты – это регионы памяти, которые содержат некоторое количество секций.

Section Header содержит информацию про секции .text .data .bss .rodata и множество служебных секций .symtab .line .strtab .debug .got .got.plt. Он необходим для линковки.

хранимый и загружаемый вид

Релокации, GOT, PLT

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

В Linux и в ELF существует два главных способа решить эту проблему:

  • релокация во время загрузки (load-time relocation);
  • код, не зависящий от адреса (position-independent code, PIC).

Релокация во время загрузки – это очень простой и прямолинейный метод. И он работает. Но PIC гораздо более популярен на данный момент и является рекомендуемым способом создания разделяемых библиотек.

У load-time relocation есть проблемы: она занимает время, и секция text (содержащая машинный код) уже не подходит для разделения между процессами.

Поэтому существует такая модель, как Global Offset Table. GOT – это просто таблица с адресами, которая находится в секции data.

Предположим, что какая-то инструкция в секции code хочет обратиться к переменной. Вместо того, чтобы обратится к ней через абсолютный адрес (который потребует релокации), она обращается к записи в GOT. Поскольку GOT имеет строго определённое место в секции data, и линкер знает о нём, это обращение тоже является относительным. А запись в GOT уже содержит абсолютный адрес переменной:

Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018) 2018-08-04 23-19-44 image0.png


Однако суть разделяемых библиотек на сегодняшний день в том, что в них может содержаться 10 000 различных функций, но использовать оттуда мы, например, будем лишь № 1 или № 4. Чтобы каждый раз подгружать абсолютно все функции в GOT, мы используем процедуру “ленивого связывания”, т.е. связывание функции из библиотеки с программой происходит при непосредственном вызове её. Помогает в этом механизм Procedure Linkage Table (PLT).

PLT – это часть секции text в бинарнике, состоящая из набора элементов (один элемент на одну внешнюю функцию, которую вызывает библиотека). Каждый элемент в PLT – это небольшой кусок выполняемого машинного кода. Вместо вызова функции напрямую вызывается кусок кода из PLT, который уже сам вызывает функцию. Такой подход часто называют «трамплином». Каждый элемент из PLT имеет собственный элемент в GOT, который содержит реальное смещение для функции (конечно после того как загрузчик определит её).

Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018) 2018-08-04 23-20-49 image0.png

В коде вызывается функция func. Компилятор переводит этот вызов в вызов func@plt, который является одним из элементов PLT. После этого идет обращение в GOT, и с учетом того что функция вызывалась в первый раз – управление передаётся обратно PLT, где т. н. resolver устанавливает связь между названием функции и её кодом из библиотеки. После такого первого связывания схема будет выглядеть немного по-другому:

Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018) 2018-08-04 23-21-15 image0.png

Библиотека при этом абсолютно не зависит от адреса, по которому она будет загружена: ведь единственное место, где используется абсолютный адрес – это GOT, а она находится в секции data и будет релоцирована загрузчиком во время загрузки. Даже PLT не зависит от адреса загрузки, так что она может находиться в секции text, доступной только для чтения.

Эксперимент с перенаправлением обращений к функциям из библиотек

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

  • создание паттерна “Proxy” для вызова функций (которые, в свою очередь, используют системные функции) из заранее откопилированных (пользовательских) библиотек без их прямого изменения;
  • перенаправление их вызовов в свой интерфейс, для дальнейшего вызова тех самых системных функций из пользовательских библиотек.
Низкоуровневый взгляд на динамические ELF-библиотеки (Владислав Жалнерович, LVEE-2018) 2018-08-04 23-20-49 image0.png

Примечания и ссылки


Plays:80   Comments:0