
Ein Tool, um aus einem rohen Kernel eine vollständig analysierbare .ELF-Datei wiederherzustellen, indem die Kernel-Symboltabelle (kallsyms) extrahiert wird.
Dieses Tool ermöglicht es, aus einem vmlinux/vmlinuz/bzImage/zImage-Kernelabbild (entweder einem rohen Binär-Blob oder einer bereits vorhandenen, aber von Symbolen befreiten .ELF-Datei) eine vollständig analysierbare .ELF-Datei mit wiederhergestellten Funktions- und Variablensymbolen zu erzeugen.
Zu diesem Zweck durchsucht es Ihren Kernel nach einer Kernel-Symboltabelle (kallsyms), einer komprimierten Symboltabelle, die in fast jedem Kernel nahezu unverändert vorhanden ist.
Da die betreffende Symboltabelle ursprünglich komprimiert ist, sollten damit Zeichenketten wiederhergestellt werden können, die im ursprünglichen Binärbild nicht sichtbar sind.
Es erzeugt eine .ELF-Datei, die Sie mit IDA Pro und Ghidra analysieren können. Dieses Tool ist daher für das Reverse Engineering eingebetteter Systeme nützlich.
Verwendung:
# Command line:
vmlinux-to-elf <input_kernel.bin> <output_kernel.elf>
# Command line, list symbol addresses only:
kallsyms-finder <input_kernel.bin> # If installed with uv
vmlinux-to-elf.kallsyms-finder # If installed with snap
# Command line, just decompress the kernel:
vmlinuz-decompressor <input_kernel.bin> <output_kernel.bin> # If installed with uv
vmlinux-to-elf.vmlinuz-decompressor # If installed with snap
# Graphical:
vmlinux-to-elf-gui # If installed with uv
vmlinux-to-elf.gui # If installed with snap
flatpak run re.fossplant.vmlinux-to-elf # If installed with flatpak
Installation:
# Install CLI+GUI with Snap (recommended on Ubuntu)
sudo snap install vmlinux-to-elf
# Install CLI+GUI with yay (recommended on Arch, Manjaro)
yay -S vmlinux-to-elf libadwaita python-gobject
# Install CLI+GUI with uv (example with Fedora)
sudo dnf install -y uv glib2-devel libadwaita-devel gtk4-devel \
gobject-introspection-devel python3-gobject-devel \
python3-devel cairo-devel @development-tools
uv tool install vmlinux-to-elf[gui]
vmlinux-to-elf-gui --install-metadata # Install .desktop file
# Install CLI with uv and GUI with Flatpak (recommended on
# distributions with libadwaita < 1.6)
sudo dnf install -y uv flatpak @development-tools
uv tool install vmlinux-to-elf
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install re.fossplant.vmlinux-to-elf
Einrichtung der lokalen Entwicklungsumgebung:
sudo snap install --classic astral-uv
sudo apt install git
git clone [email protected]:marin-m/vmlinux-to-elf.git
# Dependencies for the GTK-4 GUI
sudo apt install libgirepository-2.0-dev libadwaita-1-dev \
gir1.2-adw-1 gir1.2-gtk-4.0 python3-dev blueprint-compiler
cd vmlinux-to-elf
cp -a .github/hooks/* .git/hooks/
# Download Python modules and initialize virtualenv (creates ".venv",
# call "source .venv/bin/activate" to set up)
uv sync --extra gui
# Add vmlinux-to-elf to $PATH, so that the commands are callable
# system-wide (creates a symlink to the source in "~/.local/bin")
uv tool install -e .[gui]
boot.img-Dateien entpacken, die mit einer ANDROID!- oder UNCOMPRESSED_IMG-Magic beginnen [OK]Eine kurze Geschichte der „kallsyms“-Symboltabelle finden Sie am Anfang der Datei „kallsyms.py“. Kurz gesagt wurde sie circa 2004 in ihrer aktuellen Form in den Linux-Kernel eingeführt und dient unter anderem dazu, die „Kernel Oops“-Meldungen auszugeben.
Sie enthält Tupel aus „Symbolname“, „Symboladresse“ und „Symboltyp“ (Symboltypen werden mit einem einzelnen Buchstaben bezeichnet, ähnlich wie beim nm-Dienstprogramm); diese Informationen sind mit einem einfachen Komprimierungsalgorithmus dicht gepackt.
Das folgende Schema zeigt, wie diese Informationen im Kernel serialisiert werden, wobei der Offset der jeweiligen Struktur von vmlinux-to-elf durch Heuristiken erkannt wird:
Diese Felder haben unterschiedliche Ausrichtungen und Feldgrößen. Die Feldgrößen können auch je nach Architektur und Kernelversion variieren. Aus diesem Grund wurde vmlinux-to-elf in verschiedenen Fällen getestet.
OpenWRT hat seit 2013 einen Patch, der die Komprimierung der kallsyms-Tabelle standardmäßig entfernt (wenn die Erstellung von kallsyms vom Benutzer aktiviert wurde). Dies geschieht, um Speicherplatz zu sparen, wenn der Kernel erneut mit LZMA komprimiert wird.
Das bedeutet, dass die Einträge kallsyms_token_table und kallsyms_token_address verschwinden und die Symbolnamen stattdessen einfachen ASCII-Text verwenden. Dieser Fall wird ebenfalls unterstützt.
In Standard-Linux-6.2-Kernels sind die kallsyms-Arrays in der folgenden Reihenfolge kodiert:
kallsyms_addresses (bzw. kallsyms_offsets + kallsyms_relative_base)kallsyms_num_symskallsyms_nameskallsyms_markerskallsyms_seqs_of_names (nur 6.2+)kallsyms_token_tablekallsyms_token_indexBei Linux-Kernels ab 6.4 ändert sich dieses Layout zu:
kallsyms_num_symskallsyms_nameskallsyms_markerskallsyms_token_tablekallsyms_token_indexkallsyms_addresses (bzw. kallsyms_offsets + kallsyms_relative_base)kallsyms_seqs_of_namesDiese werden vom Parsing-Algorithmus von vmlinux-to-elf in der folgenden Reihenfolge geparst:
kallsyms_token_table (vorletzte Struktur)kallsyms_token_index (letzte Struktur, vorwärts)kallsyms_markers (rückwärts)kallsyms_names (wieder rückwärts)kallsyms_num_syms (wieder rückwärts)kallsyms_addresses (bzw. kallsyms_offsets + kallsyms_relative_base) (wieder rückwärts)Es sollte Kernel ab Version 2.6.10 (Dezember 2004) bis zur aktuellen Version 6.4 (Stand August 2023) unterstützen. Nur Kernel, die ausdrücklich ohne CONFIG_KALLSYMS konfiguriert wurden, sollten nicht unterstützt werden. Wenn diese Kernel-Konfigurationsvariable beim Build nicht gesetzt war, erhalten Sie: KallsymsNotFoundException: No embedded symbol table found in this kernel.
Bei rohen Kerneln können die folgenden Architekturen erkannt werden (unter Verwendung der Magie-Werte von binwalk): MIPSEL, MIPSEB, ARMEL, ARMEB, PowerPC, SPARC, x86, x86-64, ARM64, MIPS64, SuperH, ARC.
Die folgenden Kernel-Komprimierungsformate können automatisch erkannt werden: XZ, LZMA, GZip, BZ2, LZ4, LZO und Zstd.
Sie können auch eine reine Textausgabe der Symbolnamen, -adressen und -typen des Kernels erhalten, indem Sie das ebenfalls in diesem Tool enthaltene Dienstprogramm kallsyms-finder verwenden. Das Format seiner Ausgabe ähnelt der Datei /proc/kallsyms aus dem procfs-Dateisystem.
Einige Parameter, die vom Tool automatisch abgeleitet werden sollten (wie Befehlssatz oder Basisadresse), können bei Problemen überschrieben werden. Die vollständige Spezifikation der Argumente, mit denen das möglich ist, wird unten dargestellt:
$ 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]
[--bss-size BSS_SIZE] [--use-absolute]
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
options:
-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)
--bss-size BSS_SIZE Size in megabytes of the .bss section in the binary
--use-absolute Assume kallsyms offsets are absolute addresses
Zögern Sie nicht, für jeden Verbesserungsvorschlag ein Issue zu eröffnen.
Bitte nutzen Sie vorrangig die Issues und Pull Requests des aktuellen GitHub-Repositorys, um Fehler zu melden, Fragen zu stellen usw.
Alternativ können Sie diesen Matrix-Kanal nutzen, wenn Sie direkt mit dem Autor des Projekts Kontakt aufnehmen möchten. Bitte betrachten Sie dies jedoch als sekundären Kanal, z. B. zum Senden von Kernel-Beispielen; was sonst hierher gelangt, geht eher verloren.
| Array-Name | Beschreibung | Beispielinhalte |
|---|
kallsyms_addresses (bzw. kallsyms_offsets + kallsyms_relative_base) | Die Adressen (bzw. in neueren Kerneln Offsets relativ zu einer Basis) jedes Symbols, als Array | 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 | Die Gesamtzahl der Symbole als Ganzzahl (nützlich zur Überprüfung von Endianness, Ausrichtung und korrekter Dekodierung der Symboltabelle) | 54 D4 00 00 |
kallsyms_names | Die komprimierten, längengetrennten Symbolnamen selbst. Jedes Byte in den komprimierten Symbolzeichenketten verweist auf einen Index im "kallsyms_token_index"-Array, das wiederum auf den Offset eines Zeichens oder Zeichenkettenfragments im "kallsyms_token_table"-Array verweist. | 09 54 64 6F 5F E1 F1 66 F5 25 05 54 F3 74 AB 74 0E 54 FF AB ... |
kallsyms_markers | Eine Nachschlagetabelle, die dazu dient, den ungefähren Offset eines komprimierten Symbolnamens in "kallsyms_names" schnell zu finden: Alle 256 Symbole wird ein Offset zu dem betreffenden Symbol in "kallsyms_names" als Long-Wert zu dieser Tabelle hinzugefügt. | 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 | Diese Nachschlagetabelle (nur in Kernels ab 6.2 vorhanden) enthält eine Array-Sequenz gepackter 3-Byte-Ganzzahlen, wobei die Array-Indizes der alphanumerischen Reihenfolge für einen bestimmten Symbolnamen entsprechen und die Array-Werte den entsprechenden Eintragsindizes in den kallsyms_addresses- und kallsyms_names-Arrays entsprechen | |
kallsyms_token_table | NUL-terminierte Zeichenkettenfragmente oder Zeichen, die in Kernel-Symbolnamen enthalten sein können. Dies kann höchstens 256 Zeichenkettenfragmente oder Zeichen enthalten. Indizes, die ASCII-Codepunkten entsprechen, die tatsächlich in einem Kernel-Symbol verwendet werden, entsprechen dem betreffenden ASCII-Zeichen; andere Positionen enthalten ein statistisch ausgewähltes Zeichenkettenfragment. Dieses Tool versucht, dieses Array zunächst heuristisch in der übergebenen Datei zu finden, um die kallsyms-Symboltabelle zu finden. | 73 69 00 67 70 00 74 74 00 79 6E 00 69 6E 74 5F 00 66 72 00 ... |
kallsyms_token_index | 256 Wörter, die jeweils auf die Offsets der Zeichen oder Zeichenkettenfragmente abbilden, die durch ihre jeweiligen Indizes in "kallsyms_token_table" bezeichnet werden. | 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 ... |