我正在尝试反汇编一个由多个部分组成的复合文件,其中之一是夹在几个其他文件之间的未压缩内核。我试图找到内核部分的确切长度,但这被证明是困难的。
vmlinux 标头中是否有指示引导加载程序在执行之前应读取多少数据,或者是否假设 vmlinux 文件的所有内容都将在引导加载程序切换时加载?
答案1
简单的回答是“不”,但如果这是一个 ELF 图像,那么通过一些黑客攻击,你可能会找到内核。请参阅readelf
下面的黑客。
引导加载程序负责了解内核和根文件系统所在的任何文件的格式。这包括了解内核文件的大小,无论其格式如何。在 PowePC 和 Blackfin 上,引导加载程序负责解压缩整个内核(如果已压缩),并将其写入 RAM 中的最终位置。在 ARM 上,内核可以自解压,引导加载程序只需将原始内核文件复制到 RAM 中方便的位置并开始执行。
如果内核是自解压的,那么指示压缩内核文件大小的符号可能会也可能不会出现在文件开头的解压代码中,具体取决于所使用的解压算法,但您无法知道在没有特定内核构建的链接器映射的情况下在哪里。当然引导加载程序无法知道。
未压缩的内核代码本身由两个符号括起来,_stext
其_end
地址是内核本身的开头和结尾,但不包括任何包含的 initramfs 的范围(如果 initramfs 已链接到内核二进制文件)。 initramfs 的范围由链接器在两个内核符号__initramfs_start
和中设置__initramfs_end
。引导加载程序通常没有能力读取内核符号表(它在文件中System.map
),如果没有这种能力,它们将无法知道_end
和__initrams_end
符号在内核文件中的位置。也就是说,符号的位置不是距二进制文件开头的固定偏移量。它是在链接时确定的,并且可能根据内核构建配置而变化。
177 E L F
对于 ELF 格式的未压缩内核,您可以通过查找 ELF 标头(在od -c
复合文件的转储中)来识别 vmlinux 文件的开头。然后,您可以从此时开始对文件的其余部分执行readelf -e
“或”操作objdump -h
,以查找具有最高文件偏移量 ( ) 的部分.shstrtab
。将部分大小添加到此偏移量中,这会将您带到 vmlinux 的末尾。我使用未剥离的 PPC vmlinux 测试了此方法,并获得了与独立 vnlinux 文件大小完全匹配的大小。剥离内核后,此方法给出的结果比剥离的图像大小少了 1283 字节。
嵌入式系统通常使用一种文件格式来mkimage
打包内核、rootfs、设备树和其他组件。例如,U-boot 可以识别 mkimage,因此它知道内核二进制文件在 mkimage 文件内的开始和结束位置,并且知道内核是否被压缩以及将内核文件写入哪个 RAM 地址。