在如何从 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
在某些情况下,除了新存档不太大(例如是否存在重定位)之外,简单地使用可能就足够了。