In Wie extrahiere ich das Dateisystem-Image aus vmlinux.bin? und https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging-Methoden werden zum Abrufen und Entpacken eines eingebetteten initramfs / initrd vorgestellt, das im Kernel-Image enthalten ist.
Jetzt möchte ich das modifizierte Dateisystem ( cpio
+ möglicherweise mit z. B. gepackt lzma
) in die ausführbare Datei des Kernels einfügen, ohne es neu kompilieren zu müssen. Wäre es möglich, das ELF-Image des Kernels auf diese Weise zu ändern? Wenn ja, wie dann? Würde ich etwas respektieren müssen, wenn ich einfach die Bytes an Ort und Stelle ersetzen würde (vielleicht etwas Hash?)?
objdump-h
Ausgabe:
vmlinux.64.orig: file format elf64-big
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 004162b8 ffffffff80100000 ffffffff80100000 00010000 2**7
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 __ex_table 000063a0 ffffffff805162c0 ffffffff805162c0 004262c0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .notes 00000024 ffffffff8051c660 ffffffff8051c660 0042c660 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .rodata 0041f700 ffffffff8051d000 ffffffff8051d000 0042d000 2**8
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .pci_fixup 00000d40 ffffffff8093c700 ffffffff8093c700 0084c700 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 __ksymtab 0000a430 ffffffff8093d440 ffffffff8093d440 0084d440 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 __ksymtab_gpl 00004ff0 ffffffff80947870 ffffffff80947870 00857870 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 __ksymtab_strings 00010f14 ffffffff8094c860 ffffffff8094c860 0085c860 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 __init_rodata 00000500 ffffffff8095d778 ffffffff8095d778 0086d778 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 __param 00001388 ffffffff8095dc78 ffffffff8095dc78 0086dc78 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .data 000508c0 ffffffff80960000 ffffffff80960000 00870000 2**14
CONTENTS, ALLOC, LOAD, DATA
11 .init.text 0002b084 ffffffff809b1000 ffffffff809b1000 008c1000 2**5
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .init.data 00bc6d78 ffffffff809dc088 ffffffff809dc088 008ec088 2**3
CONTENTS, ALLOC, LOAD, DATA
13 .exit.text 000019e0 ffffffff815a2e00 ffffffff815a2e00 014b2e00 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .data.percpu 00003680 ffffffff815a5000 ffffffff815a5000 014b5000 2**7
CONTENTS, ALLOC, LOAD, DATA
15 .bss 00068fb0 ffffffff815b0000 ffffffff815b0000 014b8680 2**16
ALLOC
16 .mdebug.abi64 00000000 ffffffff81618fb0 ffffffff81618fb0 014b8680 2**0
CONTENTS, READONLY
17 .comment 0000cd74 0000000000000000 0000000000000000 014b8680 2**0
CONTENTS, READONLY
18 .gnu.attributes 00000010 0000000000000000 0000000000000000 014c53f4 2**0
objdump -h kernel.elf
zur Frage hinzufügen ? Insbesondere sollte der Abschnitt.init.ramfs
die initramfs enthalten. Wir können wahrscheinlich ein kleineres modifiziertes Dateisystem an seiner Stelle einfügen und das Datum anpassen, das seine Länge angibt. Es ist nicht klar, ob es sich im Allgemeinen lohnt, dies zu tun, aber wenn Sie einen Kernel haben, z. B. für ein eingebettetes Gerät, bei dem Sie nicht über die gesamte Kernelquelle verfügen, die neu erstellt werden kann, kann ich einen Anwendungsfall sehenAntworten:
Ja, es ist möglich, aber das Ändern der Abschnittsgröße und -adressen von .init.ramfs reicht nicht aus, da die ausführbare ELF-Datei des Kernels statisch mit der virtuellen Adresse des Beginns und Endes des Abschnitts von initramfs verknüpft ist .
In den Linux-Quellen befindet sich der relevante Code in der Quelldatei iniramfs.c:
Daher müssen Sie diese beiden Offsets auch im Maschinencode des Aufrufs der Funktion unpack_to_rootfs () ändern, die sich im Abschnitt .init.text befindet. (Achten Sie auf relevante Einträge in der Umzugstabelle! ... falls vorhanden)
In Bezug auf die Antwort von Icarus können Sie durch Manipulieren der Größe des Initramfs-Abschnitts, des Dateiversatzes und der virtuellen Startadresse sowie dieser beiden oben genannten Offsets (Argumente für die Funktion unpack_to_rootfs ()) Ihren eigenen benutzerdefinierten LARGER hinzufügen initramfs-Abschnitt, der ÜBER der maximalen virtuellen Adresse der ELF-Datei geladen wird. Das Feld "Speichergröße" des Programm-Headers (PHeader) muss ebenfalls geändert werden, um den größeren initramfs-Abschnitt widerzuspiegeln, der nach dem Ende des alten virtuellen Adressraums angehängt wird.
PS Die "Lücke" im virtuellen Adressraum des Kernels, die nach dem Verschieben des ursprünglichen Abschnitts init.ramfs in eine neue virtuelle Adresse mit hohem Start verbleibt, schadet nichts, da der zugehörige Speicher später durch die in init definierte Funktion free_initmem (void) freigegeben wird .c Quelldatei.
quelle
Wie in der Antwort auf eine ähnliche Frage zum Ersetzen von ELF-Abschnitten erwähnt, die unter reverseengineering.se besprochen wurde, kann die einfache Verwendung
dd
unter bestimmten Umständen ausreichen, abgesehen davon, dass das neue Archiv nicht größer ist, z. B. ob es Umzüge gibt.quelle