Этот инструмент позволяет получить полностью анализируемый файл .elf с изображения ядра vmlinux/vmlinuz/bzimage/Zimage (либо необработанная двоичная капля, либо ранее существовавший, но разбросанный файл.
Для этого он сканирует ваше ядро на таблицу символов ядра (Kallsyms), сжатую таблицу символов, которая присутствует практически в каждом ядре, в основном неизменным.
Поскольку заинтересованная таблица символов изначально сжимается, она должна восстанавливать строки, которые не видны в исходном двоичном файле.
Он создает файл .elf, который вы можете проанализировать с помощью IDA Pro и Ghidra. Следовательно, этот инструмент полезен для встроенных систем.
Использование:
./vmlinux-to-elf < input_kernel.bin > < output_kernel.elf > Установка по всей системе (вторая команда может не понадобиться, поскольку PIP должна найти зависимости в файле setup.py ):
sudo apt install python3-pip liblzo2-dev
sudo pip3 install --upgrade lz4 zstandard git+https://github.com/clubby789/python-lzo@b4e39df
sudo pip3 install --upgrade git+https://github.com/marin-m/vmlinux-to-elfboot.img , начиная с ANDROID! или UNCOMPRESSED_IMG магия [ОК]Краткую историю таблицы символов "Kallsyms" можно найти в верхней части файла "kallsyms_finder.py". Вкратце, это было введено около 2004 года в ядре Linux в его текущей форме и используется для печати сообщений «ядра упс», среди прочего.
Он содержит кортежи «Имя символа», «Адрес символа», «тип символа» (типы символов обозначаются с одной буквой в моде, похожей на утилиту nm ), эта информация плотно упакована с помощью простого алгоритма сжатия.
Приведенная ниже схема отображает, как эта информация сериализуется в ядро, смещение каждой соответствующей структуры, обнаруженной vmlinux-to-elf через эвристику:
| Имя массива | Описание | Содержимое образца |
|---|---|---|
kallsyms_addresses (или kallsyms_offsets + kallsyms_relative_base ) | Адреса (или смещения относительно базы, в недавних ядрах) каждого символа, как массив | 80 82 00 C0 80 82 00 C0 80 82 00 C0 0C 84 00 C0 B4 84 00 C0 5C 85 00 C0 60 85 00 C0 60 85 00 C0 ... |
kallsyms_num_syms | Общее количество символов, как целое число (полезно для проверки на эндианство, выравнивание, правильное декодирование таблицы символов) | 54 D4 00 00 |
kallsyms_names | Сжатые, разделенные длиной символы имена сами. Каждый байт в строках сжатых символов ссылается на индекс в массиве «kallsyms_token_index», который сам сам по себе ссылается на смещение символа или фрагмента строки в массиве «kallsyms_token_table». | 09 54 64 6F 5F E1 F1 66 F5 25 05 54 F3 74 AB 74 0E 54 FF AB ... |
kallsyms_markers | Таблица поиска, служащая, чтобы быстро найти приблизительное смещение сжатого имени символа в «kallsyms_names»: каждые 256 символов, смещение соответствующего символа в «kallsyms_names», добавляется в качестве долгого таблицы. | 00 00 00 00 03 0C 00 00 0C 18 00 00 1B 24 00 00 0F 31 00 00 DA 3D 00 00 CF 4A 00 00 ... |
kallsyms_seqs_of_names | Эта таблица поиска (присутствует только в ядрах 6,2+) содержит последовательность массива упакованных 3-байтовых целых чисел, где индексы массива соответствуют буквенному порядку для данного имени символа, а значения массива соответствуют соответствующим индексам входа в kallsyms_addresses и kallsyms_names | |
kallsyms_token_table | Строковые фрагменты или символы с нулевым находом, которые могут содержаться в именах символов ядра. Это может содержать не более 256 фрагментов или символов. Индексы, соответствующие кодовым точкам ASCII, которые фактически используются в любом символе любого ядра, будут соответствовать соответствующему символу ASCII, другие позиции будут содержать статистически выбранную фрагмент строки. Этот инструмент пытается эвристически найти этот массив сначала в пропущенном файле, чтобы найти таблицу символов kallsyms . | 73 69 00 67 70 00 74 74 00 79 6E 00 69 6E 74 5F 00 66 72 00 ... |
kallsyms_token_index | 256 слов, каждое сопоставление с смещениями символов или фрагментов струн, обозначенных их соответствующими индексами в «kallsyms_token_table». | 00 00 03 00 06 00 09 00 0C 00 11 00 14 00 1B 00 1E 00 22 00 2C 00 30 00 35 00 38 00 ... |
Эти поля имеют переменную выравнивание и размер поля. Размеры поля могут также варьироваться от архитектуры и версии ядра. По этой причине vmlinux-to-elf был протестирован в различных случаях.
OpenWRT с 2013 года имеет патч, который по умолчанию удаляет сжатие по таблице kallsyms (при создании kallsyms был включен пользователь). Они делают это, чтобы сохранить пространство при повторной категории над ядром с помощью LZMA.
Это означает, что записи kallsyms_token_table и kallsyms_token_address исчезают, и что имена символов используют простой текст ASCII. Этот случай также поддерживается.
В стандартных ядрах Linux 6.2 массивы kallsyms кодируются в следующем порядке:
kallsyms_addresses (или kallsyms_offsets + kallsyms_relative_base )kallsyms_num_symskallsyms_nameskallsyms_markerskallsyms_seqs_of_names (только 6,2+)kallsyms_token_tablekallsyms_token_indexДля ядра Linux 6.4+ этот макет изменен на:
kallsyms_num_symskallsyms_nameskallsyms_markerskallsyms_token_tablekallsyms_token_indexkallsyms_addresses (или kallsyms_offsets + kallsyms_relative_base )kallsyms_seqs_of_names В то время как они проанализированы в следующем порядке алгоритмом анализа vmlinux-to-elf :
kallsyms_token_table (до-до-структуры)kallsyms_token_index (последняя структура, вперед)kallsyms_markers (назад)kallsyms_names (снова назад)kallsyms_num_syms (снова назад)kallsyms_addresses (или kallsyms_offsets + kallsyms_relative_base ) (снова обратно) Он должен поддерживать ядра из версии 2.6.10 (декабрь 2004 г.), до текущего 6.4 (по состоянию на август 2023 г.). Только ядра, явно настроенные без CONFIG_KALLSYMS , не должны поддерживаться. Если эта переменная конфигурации ядра не была установлена при сборке, то вы получите: KallsymsNotFoundException: No embedded symbol table found in this kernel .
Для сырых ядер можно обнаружить следующие архитектуры (с использованием магии из Binwalk): Mipsel, Mipseb, Armel, Armeb, Powerpc, Sparc, x86, x86-64, ARM64, MIPS64, SuperH, Arc.
Следующие форматы сжатия ядра могут быть автоматически обнаружены: XZ, LZMA, GZIP, BZ2, LZ4, LZO и ZSTD.
Вы также можете получить текстовый вывод имен символов и типов ядра, используя утилиту kallsyms-finder , также в комплекте с этим инструментом. Формат его вывода будет похож на файл /proc/kallsyms procfs.
Некоторые параметры, которые должны быть автоматически выведены с помощью инструмента (например, набор инструкций или базовый адрес), могут быть переопределены в случае проблемы. Полная спецификация аргументов, позволяющих сделать это, представлена ниже:
$ vmlinux-to-elf -h
usage: vmlinux-to-elf [-h] [--e-machine DECIMAL_NUMBER] [--bit-size BIT_SIZE]
[--file-offset HEX_NUMBER] [--base-address HEX_NUMBER]
input_file output_file
Turn a raw or compressed kernel binary, or a kernel ELF without symbols, into
a fully analyzable ELF whose symbols were extracted from the kernel symbol
table
positional arguments:
input_file Path to the
vmlinux/vmlinuz/zImage/bzImage/kernel.bin/kernel.elf
file to make into an analyzable .ELF
output_file Path to the analyzable .ELF to output
optional arguments:
-h, --help show this help message and exit
--e-machine DECIMAL_NUMBER
Force overriding the output ELF "e_machine" field with
this integer value (rather than auto-detect)
--bit-size BIT_SIZE Force overriding the input kernel bit size, providing
32 or 64 bit (rather than auto-detect)
--file-offset HEX_NUMBER
Consider that the raw kernel starts at this offset of
the provided raw file or compressed stream (rather
than 0, or the beginning of the ELF sections if an ELF
header was present in the input)
--base-address HEX_NUMBER
Force overriding the output ELF base address field
with this integer value (rather than auto-detect)
$ kallsyms-finder -h
usage: kallsyms-finder [-h] [--bit-size BIT_SIZE] input_file
Find the kernel's embedded symbol table from a raw or stripped ELF kernel
file, and print these to the standard output with their addresses
positional arguments:
input_file Path to the kernel file to extract symbols from
optional arguments:
-h, --help show this help message and exit
--bit-size BIT_SIZE Force overriding the input kernel bit size, providing
32 or 64 bit (rather than auto-detect)
Не стесняйтесь открывать проблему для любого предложения об улучшении.