Igor先前在SO上发布了一个关于ARM上Linux内核映像格式的好答案。二进制的?

评论

您认为在什么基础上有符号?它们可能已被剥离,因为仅需要它们(例如)来加载内核模块。如果所有内容都链接到内核,则不需要符号。 ARM在嵌入式设备上的使用不成比例,可能有充分的理由将符号剥离出来而不用担心尺寸。在(类似)运行的内核上(或在类似QEMU的仿真器中),您是否尝试过Igor的建议来查看符号是否存在?

@ 0xC0000022L我有一个运行中的内核副本,可以存储/ proc / kallsyms,但它们没有地址,只有名称(地址显示为0)。我试图了解(1)这些名称是从哪里来的-我假设它来自压缩表,但是我对看到它很感兴趣。 (2)如何解析地址。

0xC0000022L保留符号是可以在菜单配置中选择的选项。没有符号,内核oops将毫无意义。我有充分的理由相信这些符号没有被剥离。

@Mellowcandle您是否偶然知道哪个菜单配置选项会删除符号?

@mrduclaw:公平地说,只是试图确保我们所有人都没有追赶鬼;)-Mellowcandle:如果大小是主要动机,那么内核OOPS本身就毫无意义,因为如果内核不适合设备,反正不会运行:)

#1 楼

解压缩并加载内核后,您需要找到几个对压缩符号表进行编码的表。它们是(按照通常的顺序放置在二进制文件中):



kallsyms_addresses-内核中所有公共符号的地址表

kallsyms_num_syms-不是表,而只是一个带有符号总数的整数(应该与上一个表匹配)

kallsyms_names-长度固定的字节数组的列表,这些数组将索引编码到令牌表中
kallsyms_token_table-256个以符号结尾的零终止令牌的列表,

kallsyms_token_index-指向kallsyms_token_table中相应条目的256个短裤


通过一些经验,他们并不难找到。查找第一个的好方法是连续查找多个0xC0008000值,因为典型的内核符号表的开始是这样的:

C0008000 T __init_begin
C0008000 T _sinittext
C0008000 T _stext
C0008000 T stext


找到表后符号恢复是微不足道的。我为IDA编写了一个脚本,该脚本会自动执行此操作,您可以在此处找到它(工具zip中的kallsyms.py)。

有关在内核中如何实现的更多详细信息,请参见kernel/kallsyms.c

评论


啊,这正是我想要的。谢谢!到目前为止,我已经能够识别kallsyms_addresses,kallsyms_num_syms和kall_syms_names。我以为我找到了另外两个,但是您的脚本无法对名称进行解码。我确定我做错了。似乎很难知道kallsyms_names表的大小。你有什么建议吗?再次感谢你!

–mrduclaw
13年4月26日在2:22

kallsyms_token_table应该很明显-它看起来类似于“ tcp _”,0,“ ca”,0,“ unc _”,0,...等。

–伊戈尔·斯科钦斯基♦
13年4月26日在2:49

该死的,我认为那是我找到的那个。我会再玩一点。我敢肯定,这对我来说真是不可思议。再次感谢!

–mrduclaw
2013年4月26日下午3:06

#2 楼

您提到您确实有一个正在运行的内核。通过读取/proc/kallsyms可以从正在运行的内核中获取符号信息。在较新的发行版中,出于安全原因(默认情况下,所有信息都将显示为0x0地址),默认情况下将禁用此信息,但是您可以通过以root用户身份运行以下命令来手动启用它:

echo 0 > /proc/sys/kernel/kptr_restrict >
一旦获得了内核符号/地址对的列表,就可以轻松转换为所需的任何格式,例如用于导入的IDA .idc脚本。

评论


@ 0xC0000022L他在评论中回答了您:“我有一个运行中的内核副本,可以存储/ proc / kallsyms,但它们没有地址,只有名称(地址显示为0)。”

–mncoppola
13-4-25在14:42

#3 楼

如果不亲自回答问题并根据问题和链接的答案验证一些假设,回答这个问题就比较棘手。但是,让我尝试一下,如果您进一步详细说明文件的某些方面,也许我们可以进一步扩展它。

我们知道这是一个ARM文件,从您的描述来看,这听起来像是ARM内核映像为U-Boot。现在的问题是,我不知道那是不是真的,但是您可以在文件上运行经常提到的binwalkfirmware-mod-kit,看看能给您带来什么。

如果这是U-的ARM内核映像,引导,您可以通过跳过映像的前64个字节来获取gzip数据(请参阅StackOverflow上的此答案)。要点是:

dd if=<image> of=<recovered file> bs=64 skip=1


这将跳过1个64字节的块,否则将数据从<image>写入<recovered file>。从本质上讲,它部分扭转了U引导程序mkimage的作用。

现在,假设到目前为止一切正常,这是一个巨大的假设,您应该能够解压(gzip -d)生成的文件,最后得到可以希望的东西。如果是您,请使用grep检查文件的类型,如果碰巧从文件中获取了有意义的信息,请进行进一步处理。如果不是,我将再次使用file处理该文件,并在其上运行binwalk失败。


编辑x + 1: 。下载了这个Debian软件包,将其解压缩,得到一个strings,然后我在010 Editor中对其进行了查看,的确,根据标记,这是一个ARM内核映像(请参见下面的阅读部分):



之后,我尝试跳过前64个字节,然后解压缩其余字节,无济于事。调查更多。

如果您使用此不完整的答案设法获得更多信息,请编辑您的问题,一旦发现您的修改,我将修改答案,以添加更多(希望是有用的)信息。

编辑x + 2 :

好吧,对于我所原始回答中提到的zImage而言,zImage-2.6.28.10-power51至少可以处理文件并输出:

12900           0x3264          gzip compressed data, from Unix, last modified: Mon Jul 23 13:41:37 2012, max compression


可爱。让我们运行binwalk来提取dd的东西,然后将其提取:

dd if=zImage-2.6.28.10-power51 of=extract.gz bs=12900 skip=1 && gunzip extract.gz && ls -l extract


一旦我将其提取,在注意到gzip没有产生结果之后,我再次运行binwalk

DECIMAL         HEX             DESCRIPTION
-------------------------------------------------------------------------------------------------------
135456          0x21120         gzip compressed data, from Unix, last modified: Mon Jul 23 13:38:47 2012, max compression
973460          0xEDA94         ELF
1070320         0x1054F0        CramFS filesystem, big endian size 2126262976 CRC 0xdc0a0e1, edition 4040895977, 78662882 blocks, 271618533 files


但是,我不想在没有您进一步输入的情况下立即进行操作。只是一个如何进行调查的示例。 file还会再产生一个符号列表,但是由于我想您想要符号及其地址,因此我认为还有很多地方要研究。


进一步阅读:



本文档将验证这是否确实是我们期望/假定的格式的ARM内核映像。特别要检查一下可以在偏移量strings处找到0x016F2818的假设。您必须切断uRamdisk / uRecRam的64字节标头:

0x24

dd if=uRamdisk of=uRamdisk.cpio.gz bs=64 skip=1

gunzip uRamdisk.cpi.gz


,这实际上意味着您必须期望在偏移量64处使用cpio -i -F uRamdisk.cpio(因此为CPIO格式)。也就是说,“内核映像”实际上是嵌入initrd的旧内核格式(另请参见initrd手册页)在“创建旧的旧版图片”下)。