从 vmlinux.bin (嵌入 initramfs)重新打包文件系统映像而不重建?

从 vmlinux.bin (嵌入 initramfs)重新打包文件系统映像而不重建?

如何从 vmlinux.bin 中提取文件系统映像?https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging提供了获取和解包内核映像中包含的嵌入式 initramfs/initrd 的方法。

现在我想将修改后的文件系统(cpio+可能使用例如打包lzma)插入内核可执行文件中,而无需重新编译它。是否可以通过这种方式修改内核的ELF镜像?如果是这样那怎么办?如果我只是简单地替换字节(也许是一些散列?),我是否需要保留一些东西?


objdump-h输出:
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

答案1

是的,这是可能的,但更改 .init.ramfs 部分大小和地址还不够,因为内核的 ELF 可执行文件与虚拟地址静态链接开始和结束initramfs 部分。

在 Linux 源代码中,相关代码位于 iniramfs.c 源文件中:

void __init populate_rootfs(void)
{
  char *err = unpack_to_rootfs(__initramfs_start, __initramfs_end - __initramfs_start, 0); 
...
}

因此,您还需要更改调用 unpack_to_rootfs() 函数的机器代码中的这两个偏移量,该函数位于 .init.text 部分。 (注意重定位表中的任何相关条目!...如果存在的话)

另外,参考 Icarus 的回复,对 initramfs 部分大小、文件偏移量和起始虚拟地址以及上述两个偏移量( unpack_to_rootfs() 函数的参数)的操作使您能够添加自己的自定义更大initramfs 部分加载到 ELF 文件的最大虚拟地址之上。程序头 (PHeader) 的“内存大小”字段也需要修改,以便反映在旧虚拟地址空间末尾附加的更大的 initramfs 部分。

聚苯乙烯 将原始 init.ramfs 部分移动到新的高起始虚拟地址后,内核虚拟地址空间中剩余的“漏洞”不会造成任何损害,因为相关内存稍后会被 init 中定义的 free_initmem(void) 函数释放。 .c 源文件。

答案2

正如在答案中提到的关于替换reverseengineering.se 中讨论的 ELF 部分的类似问题dd在某些情况下,除了新存档不太大(例如是否存在重定位)之外,简单地使用可能就足够了。

相关内容