该工具允许从vmlinux/vmlinuz/bzimage/zimage内核图像获得完全可分析的.eff文件(恢复功能和可变符号,都可以使用原始的二进制斑点或已删除的drake trepeefef。
为此,它会扫描您的内核中的内核符号表(kallsyms),这是一个压缩符号表,几乎每个内核都存在,大部分都没有改变。
由于相关符号表最初是压缩的,因此应恢复原始二进制中不可见的字符串。
它会生成一个.fly文件,您可以使用IDA Pro和Ghidra进行分析。因此,该工具对于嵌入式系统逆向工程很有用。
用法:
./vmlinux-to-elf < input_kernel.bin > < output_kernel.elf >整个系统安装(可能不需要第二个命令,因为PIP应该在setup.py中找到依赖项):
sudo apt install python3-pip liblzo2-dev
sudo pip3 install --upgrade lz4 zstandard git+https://github.com/clubby789/python-lzo@b4e39df
sudo pip3 install --upgrade git+https://github.com/marin-m/vmlinux-to-elfboot.img ANDROID!或未UNCOMPRESSED_IMG魔术[OK]可以在“ kallsyms_finder.py”文件的顶部找到“ kallsyms”符号表的简短历史记录。简而言之,这是在2004年的Linux内核中以其当前形式引入的,用于打印“内核OOPS”消息等。
它包含“符号名称”,“符号地址”,“符号类型”的元素(符号类型(用类似于nm实用程序的单个字母)指定的符号类型),此信息与简单的压缩算法紧密包装。
下面的模式显示了如何将此信息序列化到内核中,这是通过启发式方法检测到的vmlinux-to-elf所检测到的每个相应结构的偏移:
| 数组名称 | 描述 | 样本内容 |
|---|---|---|
kallsyms_addresses (或kallsyms_offsets + kallsyms_relative_base ) | 每个符号作为数组 | 80 82 00 C0 80 82 00 C0 80 82 00 C0 0C 84 00 C0 B4 84 00 C0 5C 85 00 C0 60 85 00 C0 60 85 00 C0 ... |
kallsyms_num_syms | 符号的总数,作为整数(用于检查底色,对齐,正确解码符号表) | 54 D4 00 00 |
kallsyms_names | 压缩,长度分离的符号本身。压缩符号字符串中的每个字节引用了“ kallsyms_token_index”数组中的索引,该数个数组本身引用了“ kallsyms_token_table”阵列中字符或字符串片段的偏移。 | 09 54 64 6F 5F E1 F1 66 F5 25 05 54 F3 74 AB 74 0E 54 FF AB ... |
kallsyms_markers | 查找表可快速找到“ kallsyms_names”中的压缩符号名称的近似偏移:每256个符号,“ kallsyms_names”中相关符号的偏移是在此表中添加的。 | 00 00 00 00 03 0C 00 00 0C 18 00 00 1B 24 00 00 0F 31 00 00 DA 3D 00 00 CF 4A 00 00 ... |
kallsyms_seqs_of_names | 此查找表(仅在6.2+内存中)包含一个包装的3字节整数的数组序列,其中阵列索引符合给定符号名称的字母数字顺序,并且阵列值与kallsyms_addresses和kallsyms_names中的相应输入索引匹配 | |
kallsyms_token_table | 可包含内核符号名称中的零终止的字符串片段或字符。这最多可以包含256个字符串片段或字符。与ASCII代码点相对应的索引,实际上在任何内核符号中使用的索引将与相关的ASCII字符相对应,其他位置将包含统计选择的字符串片段。该工具试图首先在传递的文件上启发上找到此数组,以找到kallsyms符号表。 | 73 69 00 67 70 00 74 74 00 79 6E 00 69 6E 74 5F 00 66 72 00 ... |
kallsyms_token_index | 256个单词,每个映射到“ kallsyms_token_table”中各自索引指定的字符或字符串片段的偏移。 | 00 00 03 00 06 00 09 00 0C 00 11 00 14 00 1B 00 1E 00 22 00 2C 00 30 00 35 00 38 00 ... |
这些字段具有可变的对齐和字段大小。场地的大小可能会因体系结构和内核版本而异。因此, vmlinux-to-elf已在多种情况下进行了测试。
自2013年以来,OpenWrt的补丁程序默认情况下可以在kallsyms表上删除压缩(用户启用了kallsyms时)。他们这样做是为了在使用LZMA重新压缩内核时节省空间。
这意味着kallsyms_token_table和kallsyms_token_address条目消失了,并且符号名称使用纯文本ascii。此案也得到了支持。
在标准Linux 6.2内核中, kallsyms数组按以下顺序进行编码:
kallsyms_addresses (或kallsyms_offsets + kallsyms_relative_base )kallsyms_num_symskallsyms_nameskallsyms_markerskallsyms_seqs_of_names (仅6.2+)kallsyms_token_tablekallsyms_token_index对于Linux 6.4+内核,此布局更改为:
kallsyms_num_symskallsyms_nameskallsyms_markerskallsyms_token_tablekallsyms_token_indexkallsyms_addresses (或kallsyms_offsets + kallsyms_relative_base )kallsyms_seqs_of_names虽然它们按以下顺序解析了vmlinux-to-elf的解析算法:
kallsyms_token_table (持久结构)kallsyms_token_index (最后一个结构,向前)kallsyms_markers (向后)kallsyms_names (再次向后)kallsyms_num_syms (再次向后)kallsyms_addresses (或kallsyms_offsets + kallsyms_relative_base )(再次向后) 它应支持2.6.10版(2004年12月)的内核,直到当前6.4(截至2023年8月)。不得支持没有CONFIG_KALLSYMS的明确配置的内核。如果在构建中未设置此内核配置变量,则您将获得: KallsymsNotFoundException: No embedded symbol table found in this kernel 。
对于RAW内核,可以检测到以下架构(使用BinWalk的MAGIC):MIPSEL,MIPSEB,ARMEL,ARMEB,ARMEB,POWERPC,SPARC,SPARC,X86,X86-64,ARM64,MIPS64,MIPS64,SUPERH,ARC。
可以自动检测到以下内核压缩格式:XZ,LZMA,GZIP,BZ2,LZ4,LZO和ZSTD。
您还可以通过使用kallsyms-finder实用程序获得内核符号名称,地址和类型的仅文本输出,并与此工具捆绑在一起。其输出格式将类似于/proc/kallsyms procfs文件。
如果在发行问题的情况下,该工具应自动推断的某些参数(例如指令集或基本地址)可能会被覆盖。允许这样做的参数的完整规范如下:
$ vmlinux-to-elf -h
usage: vmlinux-to-elf [-h] [--e-machine DECIMAL_NUMBER] [--bit-size BIT_SIZE]
[--file-offset HEX_NUMBER] [--base-address HEX_NUMBER]
input_file output_file
Turn a raw or compressed kernel binary, or a kernel ELF without symbols, into
a fully analyzable ELF whose symbols were extracted from the kernel symbol
table
positional arguments:
input_file Path to the
vmlinux/vmlinuz/zImage/bzImage/kernel.bin/kernel.elf
file to make into an analyzable .ELF
output_file Path to the analyzable .ELF to output
optional arguments:
-h, --help show this help message and exit
--e-machine DECIMAL_NUMBER
Force overriding the output ELF "e_machine" field with
this integer value (rather than auto-detect)
--bit-size BIT_SIZE Force overriding the input kernel bit size, providing
32 or 64 bit (rather than auto-detect)
--file-offset HEX_NUMBER
Consider that the raw kernel starts at this offset of
the provided raw file or compressed stream (rather
than 0, or the beginning of the ELF sections if an ELF
header was present in the input)
--base-address HEX_NUMBER
Force overriding the output ELF base address field
with this integer value (rather than auto-detect)
$ kallsyms-finder -h
usage: kallsyms-finder [-h] [--bit-size BIT_SIZE] input_file
Find the kernel's embedded symbol table from a raw or stripped ELF kernel
file, and print these to the standard output with their addresses
positional arguments:
input_file Path to the kernel file to extract symbols from
optional arguments:
-h, --help show this help message and exit
--bit-size BIT_SIZE Force overriding the input kernel bit size, providing
32 or 64 bit (rather than auto-detect)
不要犹豫,为任何改进的建议打开一个问题。