Вопрос или проблема
Я пытаюсь вычислить значение -o
для извлечения файла .AppImage
, используя unsquashfs
на иностранных архитектурах/ОС, но вместо readelf
использую objdump
для большей совместимости с ОС, такими как macOS.
unsquashfs
Usage:
-o BYTES, -offset BYTES
skip BYTES at start of FILESYSTEM. Optionally a suffix of K, M or G can be given to specify Kbytes, Mbytes or Gbytes respectively (default 0
bytes).
Я следую инструкциям этого решения, которое использует readelf
для вычисления значения смещения -o
. Это отлично работает на Ubuntu, но не работает для macOS из-за общего отсутствия readelf
.
Однако я хотел бы использовать objdump
при возможности. Я нашел несколько вопросов, объясняющих, как найти точку входа/смещение исполняемого бинарника, но какие бы значения я ни пробовал, я не могу найти способ получить правильное значение для unsquashfs
. Я перевожу шестнадцатеричные значения в десятичные, но ничего из objdump
не совпадает с значениями readelf
ниже, даже при использовании уравнения Employed Russian: ehdr->e_entry - phdr->p_vaddr + phdr->p_offset.
- https://stackoverflow.com/a/71367851
- https://stackoverflow.com/a/57841768
- https://stackoverflow.com/a/16019798
Например, возьмем AppImage Audacity:
https://github.com/audacity/audacity/releases/download/Audacity-3.7.1/audacity-linux-3.7.1-x64-22.04.AppImage
- Вызов
readelf -h audacity-linux-3.7.1-x64-22.04.AppImage
дает мне некоторые полезные значения, такие какStart of section headers
,Size of section headers
,Number of section headers
. - Затем, используя логику
$START_OF_SECTION + $SECTION_SIZE * $SECTION_NO
Мартина Высочила, я могу получить правильное значение191680 + 64 * 32
, которое равно193728
. - Следующая команда выполняется успешно (на macOS и Ubuntu):
unsquashfs -o 193728 audacity-linux-3.7.1-x64-22.04.AppImage squashfs-root
… но как я могу вычислить это смещение с помощью objdump
вместо readelf
?
Пока вы знаете, какие байты читать в заголовке ELF, вы можете применить формулу напрямую с помощью инструмента, который может обрабатывать бинарные файлы (python
, perl
и т. д.).
Вот как выглядит заголовок ELF (см. man elf
):
typedef struct {
unsigned char e_ident[16]; // байты идентификации ELF
uint16_t e_type; // Тип файла
uint16_t e_machine; // Требуемая архитектура для этого файла
uint32_t e_version; // Должен быть равен 1
uintN_t e_entry; // Адрес для перехода к началу программы
uintN_t e_phoff; // Смещение таблицы заголовков программы, в байтах
uintN_t e_shoff; // Смещение таблицы заголовков секций, в байтах
uint32_t e_flags; // Флаги, специфичные для процессора
uint16_t e_ehsize; // Размер заголовка ELF, в байтах
uint16_t e_phentsize; // Размер записи в таблице заголовков программы
uint16_t e_phnum; // Количество записей в таблице заголовков программы
uint16_t e_shentsize; // Размер записи в таблице заголовков секций
uint16_t e_shnum; // Количество записей в таблице заголовков секций
uint16_t e_shstrndx; // Индекс таблицы имен секций в таблице заголовков секций
};
Примечание: N
в uintN_t
может быть 32
или 64
, в зависимости от значения e_ident[4]
Вычисление смещения
Следующая “однострочница” на perl
рассчитает смещение, необходимое для unsquashfs, но только для ELF64-LSB app изображений (мне было лень обрабатывать возможные размеры адресации и эндиянность):
perl -le '
read STDIN, $_, 64;
($off,$sz,$nb) = unpack "x40Q<x10S<S<";
print $off + $sz * $nb;
' < audacity-linux-3.7.1-x64-22.04.AppImage
вывод:
193728
Помимо этого
Я решил, что необходимо рефакторить скрипт @MartinVyskočil:
readelf -h file.appimage |
awk '
/of section headers:/ { h[$1] = $5 }
END { print h["Start"] + h["Size"] * h["Number"] }
'
Ответ или решение
Теория
Для извлечения файлов из формата .AppImage
с использованием unsquashfs
на разных операционных системах необходимо вычислить смещение байтов (-o
), чтобы правильно пропустить данные в начале файловой системы. Обычно это значение можно получить с помощью утилиты readelf
, но в macOS она недоступна. В таких случаях предлагается использовать objdump
, который доступен на macOS. Задача заключается в том, чтобы скриптом или командами рассчитать нужное смещение с помощью данных, которые предоставляют эти инструменты.
Пример
При использовании readelf
, необходимая информация для расчета смещения байтов может быть получена из заголовков ELF (Executable and Linkable Format), таких как Start of section headers
, Size of section headers
, и Number of section headers
. Эти параметры позволяют вычислить искомое смещение байтов.
Применение
Если мы хотим достичь того же результата с использованием objdump
, это возможно за счет перебора и анализа бинарной структуры ELF. Другие инструменты, такие как скрипты Perl
, Python
и другие языки программирования, могут быть использованы для прямой работы с бинарными данными, извлеченными из ELF.
Возможное Решение
-
Использование
objdump
: Узнайте в каком из разделов объектов ELF находится информация, соответствующая смещению, затем проведите необходимые расчеты. За это отвечает флаг--headers
уobjdump
, который выводит данные о разделах. -
Скрипт на Perl: Если у вас на руках объект ELF, то смещение можно рассчитать примерно таким образом:
perl -le ' read STDIN, $_, 64; ($off, $sz, $nb) = unpack "x40Q<x10S<S<"; print $off + $sz * $nb; ' < ваш_файл.AppImage
Этот скрипт считывает первые 64 байта ELF-файла и делает необходимые вычисления на основе извлеченной информации.
-
Сравнение результатов: Проверьте полученное значение смещения, запустив
unsquashfs
с вашим значением:unsquashfs -o <ваше_значение_смещения> ваш_файл.AppImage squashfs-root
Это решение позволяет избежать зависимости от конкретных утилит и делает процесс извлечения универсальным для использования на системах, где readelf
недоступен, например, на macOS.