Linux

從 vmlinux.bin(嵌入式 initramfs)重新打封包件系統映像而不重建?

  • July 25, 2018

如何從 vmlinux.bin 中提取文件系統映像?https://wiki.gentoo.org/wiki/Custom_Initramfs#Salvaging方法用於獲取和解壓包含在核心映像中的嵌入式 initramfs/initrd。

現在我想將修改後的文件系統(cpio+ 可能使用 eg 打包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

正如在 reverseengineering.se 上討論的關於替換 ELF 部分的類似問題的答案中所提到的,dd在某些情況下,除了新存檔不會更大(例如是否有重定位)之外,簡單地使用可能就足夠了。

是的,這是可能的,但是改變 .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() 函式的參數)的操作,使您能夠添加自己的自定義LARGER在 ELF 文件的最大虛擬地址之上傳入的 initramfs 部分。程序頭 (PHeader) 的“記憶體大小”欄位也需要修改,以反映在舊虛擬地址空間結束後附加的更大的 initramfs 部分。

PS 在將原始 init.ramfs 部分移動到新的高起始虛擬地址後,核心的虛擬地址空間中剩餘的“洞”不會造成任何傷害,因為相關的記憶體稍後會由 init 中定義的 free_initmem(void) 函式釋放.c 源文件。

引用自:https://unix.stackexchange.com/questions/342298