Essa ferramenta permite obter um arquivo .ELF totalmente analisável de uma imagem do kernel VMLinux/vmlluz/bzimage/zimage (um blob binário bruto ou um arquivo .ELF preexistente, mas despojado), com função recuperada e símbolos variáveis.
Para isso, ele digitaliza seu kernel em busca de uma tabela de símbolos do kernel (Kallsyms), uma tabela de símbolos compactados que está presente em quase todos os núcleos, principalmente inalterados.
Como a tabela de símbolos em questão é originalmente compactada, ela deve recuperar seqüências de caracteres que não são visíveis no binário original.
Produz um arquivo .Elf que você pode analisar usando o IDA Pro e Ghidra. Esta ferramenta é, portanto, útil para sistemas incorporados engenharia reversa.
Uso:
./vmlinux-to-elf < input_kernel.bin > < output_kernel.elf > Instalação em todo o sistema (o segundo comando não pode ser necessário, pois o PIP deve encontrar as dependências no arquivo 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 , começando com um ANDROID! ou UNCOMPRESSED_IMG mágica [ok]Uma breve história da tabela de símbolos "Kallsyms" pode ser encontrada na parte superior do arquivo "Kallsyms_finder.py". Resumidamente, isso foi introduzido por volta de 2004 no kernel Linux em sua forma atual e é usado para imprimir as mensagens "kernel oops", entre outras coisas.
Ele contém tuplas de "nome do símbolo", "endereço de símbolo", "tipo de símbolo" (tipos de símbolos sendo designados com uma única letra de uma maneira semelhante ao utilitário nm ), essas informações sendo fortemente embaladas com um algoritmo de compressão simples.
O esquema abaixo exibe como essas informações são serializadas no kernel, o deslocamento de cada estrutura respectiva sendo detectada pelo vmlinux-to-elf através de heurísticas:
| Nome da matriz | Descrição | Conteúdo de amostra |
|---|---|---|
kallsyms_addresses (ou kallsyms_offsets + kallsyms_relative_base ) | Os endereços (ou compensações em relação a uma base, em kernels recentes) de cada símbolo, como uma matriz | 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 | O número total de símbolos, como um número inteiro (útil para verificar a Endianness, alinhamento, decodificação correta da tabela de símbolos) | 54 D4 00 00 |
kallsyms_names | O símbolo compactado e separado por comprimento se nomeia. Cada byte nas seqüências de símbolos compactadas referencia um índice na matriz "Kallsyms_token_index", que ela por si só referencia o deslocamento de um caractere ou fragmento de string na matriz "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 | Uma tabela de pesquisa que serve para encontrar rapidamente o deslocamento aproximado de um nome de símbolo comprimido em "Kallsyms_names": cada 256 símbolos, um deslocamento para o símbolo em questão em "Kallsyms_names" é adicionado como um longo tempo a esta tabela. | 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 | Esta tabela de pesquisa (presente apenas em 6,2 kernels) contém uma sequência de matriz de números inteiros de 3 bytes embalados, onde os índices de matriz correspondem à ordem alfanumérica para um determinado nome de símbolo, e os valores da matriz correspondem aos índices de entrada correspondentes nos Índices de kallsyms_addresses e kallsyms_names | |
kallsyms_token_table | Fragmentos de cordas ou caracteres terminados nulos que podem estar contidos nos nomes de símbolos do kernel. Isso pode conter no máximo 256 fragmentos ou caracteres de string. Os índices correspondentes aos pontos de código ASCII que são realmente usados em qualquer símbolo do kernel corresponderão ao caractere ASCII em questão, outras posições conterão um fragmento de string estatisticamente escolhido. Essa ferramenta tenta encontrar heuristicamente essa matriz no arquivo passado primeiro para encontrar a tabela de símbolos 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 palavras, cada um mapeando para as compensações dos caracteres ou fragmentos de string designados por seus respectivos índices em "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 ... |
Esses campos têm alinhamento variável e tamanho de campo. Os tamanhos de campo também podem variar em relação à arquitetura e à versão do kernel. Por esse motivo, vmlinux-to-elf foi testado em vários casos.
O OpenWrt desde 2013 possui um patch que remove a compactação sobre a tabela kallsyms por padrão (ao criar kallsyms , foi ativado pelo usuário). Eles fazem isso para economizar espaço ao recomprar o kernel usando LZMA.
Isso significa que as entradas kallsyms_token_table e kallsyms_token_address desaparecem e que os nomes de símbolos usam texto sem formatação ASCII. Este caso também é suportado.
Nos kernels do Linux 6.2 padrão, as matrizes kallsyms são codificadas na seguinte ordem:
kallsyms_addresses (ou kallsyms_offsets + kallsyms_relative_base )kallsyms_num_symskallsyms_nameskallsyms_markerskallsyms_seqs_of_names (somente 6.2+)kallsyms_token_tablekallsyms_token_indexPara os kernels Linux 6.4+, este layout é alterado para:
kallsyms_num_symskallsyms_nameskallsyms_markerskallsyms_token_tablekallsyms_token_indexkallsyms_addresses (ou kallsyms_offsets + kallsyms_relative_base )kallsyms_seqs_of_names Embora estes sejam analisados na seguinte ordem pelo algoritmo de análise do vmlinux-to-elf :
kallsyms_token_table (estrutura antes do reto)kallsyms_token_index (última estrutura, para a frente)kallsyms_markers (para trás)kallsyms_names (para trás novamente)kallsyms_num_syms (para trás novamente)kallsyms_addresses (ou kallsyms_offsets + kallsyms_relative_base ) (para trás novamente) Ele deve suportar kernels da versão 2.6.10 (dezembro de 2004), até o atual 6.4 (em agosto de 2023). Somente kernels configurados explicitamente sem CONFIG_KALLSYMS não devem ser suportados. Se essa variável de configuração do kernel não foi definida no Build, você obterá: KallsymsNotFoundException: No embedded symbol table found in this kernel .
Para grãos crus, as seguintes arquiteturas podem ser detectadas (usando mágicas de Binwalk): Mipsel, Mipseb, Armel, ArmEb, PowerPC, SPARC, X86, X86-64, ARM64, MIPS64, Superh, Arc.
Os seguintes formatos de compressão do kernel podem ser detectados automaticamente: XZ, LZMA, GZIP, BZ2, LZ4, LZO e ZSTD.
Você também pode obter uma saída somente de texto dos nomes, endereços e tipos de símbolos do kernel usando o utilitário kallsyms-finder , também incluído com esta ferramenta. O formato de sua saída será semelhante ao arquivo /proc/kallsyms procfs.
Alguns parâmetros que devem ser inferidos automaticamente pela ferramenta (como o conjunto de instruções ou o endereço base) podem ser substituídos em caso de problema. A especificação completa dos argumentos que permitem fazer isso é apresentada abaixo:
$ 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)
Não hesite em abrir um problema para qualquer sugestão de melhoria.