이 도구를 사용하면 vmlinux/vmlinuz/bzimage/zimage 커널 이미지 (원시 바이너리 블로브 또는 기존이지만 스트리핑 된 .ELF 파일)에서 복구 된 기능과 가변 기호로 완전히 분석 가능한 .ELF 파일을 얻을 수 있습니다.
이를 위해 거의 모든 커널에 존재하는 압축 기호 테이블 인 커널 기호 테이블 (Kallsyms)에 대한 커널을 스캔합니다.
관련 기호 테이블은 원래 압축되어 있으므로 원래 바이너리에서 보이지 않는 문자열을 복구해야합니다.
Ida Pro 및 Ghidra를 사용하여 분석 할 수있는 .ELF 파일을 생성합니다. 따라서이 도구는 임베디드 시스템 리버스 엔지니어링에 유용합니다.
용법:
./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 magic [ok]"Kallsyms"기호 테이블의 간단한 기록은 "Kallsyms_finder.py"파일의 상단에서 찾을 수 있습니다. 간단히 말해서, 이것은 2004 년경 Linux 커널에서 현재 형식의 형식으로 소개되었으며 무엇보다도 "커널 oops"메시지를 인쇄하는 데 사용됩니다.
여기에는 "Symbol Name", "Symbol Adress", "Symbol Type"( 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 | 커널 기호 이름에 포함될 수있는 Null-Terminated String 조각 또는 문자. 여기에는 최대 256 개의 문자열 조각 또는 문자가 포함될 수 있습니다. 실제로 모든 커널 기호에서 사용되는 ASCII 코드 포인트에 해당하는 인덱스는 관련 ASCII 문자에 해당하며, 다른 위치에는 통계적으로 선택된 문자열 조각이 포함됩니다. 이 도구는 kallsyms Symbols 테이블을 찾기 위해 전달 된 파일을 가로 질러이 배열을 먼저 찾으려고합니다. | 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 다양한 경우에 걸쳐 테스트되었습니다.
OpenWrt는 2013 년부터 기본적으로 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_indexLinux 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 ) (뒤로 다시) 현재 6.4 (2023 년 8 월 현재)까지 버전 2.6.10 (2004 년 12 월)의 커널을 지원해야합니다. CONFIG_KALLSYMS 없이 명시 적으로 구성된 커널 만 지원해서는 안됩니다. 이 커널 구성 변수가 빌드에서 설정되지 않은 경우 다음을 얻을 수 있습니다. KallsymsNotFoundException: No embedded symbol table found in this kernel .
원시 커널의 경우 Mipsel, Mipseb, Armel, Armeb, PowerPC, Sparc, X86, X86-64, ARM64, MIPS64, Super, 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)
개선 제안에 대한 문제를 열어주지 마십시오.