-
-
[原创]逆向进入内核时代之APatch源码学习(04.内核符号表)
-
发表于:
2024-10-12 17:16
2658
-
[原创]逆向进入内核时代之APatch源码学习(04.内核符号表)
题外话:学了有什么屁用?啥也不是
答复: KROOT,KernelSu,APatch打造最强瑞士军刀
进入正题
话不多说,且听这回分解,通过前一章节, 我们了解到Kptools的核心功能是嵌入和提供一些必要的运行时参数, 而这些参数:
- 要么从外部获取
- 要么运行时拦截查找
这是我们必须要解答的问题, 这里面牵扯的知识点比较复杂, 其中核心知识点是KAllSyms, 也就是内核符号表.
这里我们站在前人的肩膀上学习, 再结合自身实践。
https://www.cnblogs.com/jianhua1992/p/16852796.html
什么是内核符号表?
内核符号表(Kernel Symbol Table)是操作系统内核维护的一张表格,包含了内核中所有符号(如函数名、变量名及其地址)的映射关系。符号表的主要用途包括调试、诊断、以及在运行时进行符号解析。以下是一些关于内核符号表的详细信息:
内核符号表主要功能
调试:
- 在调试内核代码时,调试工具(如gdb)需要知道内核函数和变量的地址,以便设置断点、查看变量值等。符号表提供了这些信息。
诊断和性能分析:
- 工具如perf、ftrace等依赖内核符号表来解析性能数据,帮助开发者找出性能瓶颈或错误代码位置。
加载和卸载内核模块:
- 内核模块在加载时需要解析符号表,以找到所需的函数和变量。
内核崩溃分析:
- 内核崩溃(Kernel Panic)时,符号表帮助生成更有意义的崩溃日志,指出确切的崩溃位置。
核心关键概念
- 符号:表示内核中函数或变量的名称。
- 地址:符号在内存中的位置。
- 映射关系:符号和地址之间的对应关系。
简单总结
- 内核符号表是操作系统内核中的重要数据结构,广泛用于内核调试、诊断、性能分析以及模块管理。了解并使用内核符号表对于内核开发者和系统管理员来说,是非常重要的技能。
真机如何查看内核符号表?
1 2 3 4 | thyme: / $ su
thyme: /
thyme: /
thyme: /
|
这里贴一下其他学员的经验, 传播鼓励。
自己编译内核如何查看内核符号表?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | / / KernelPatchQEMU / .tmp_kallsyms1.S
.section .rodata, "a"
.globl kallsyms_offsets
ALGN
kallsyms_offsets:
. long 0
. long 0
. long 0x800
. long 0x800
. long 0x800
. long 0x848
. long 0x898
. long 0x950
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | / / KernelPatchQEMU / System. map
0000000000000000 A __rela_size
0000000000000000 A _kernel_flags_le_hi32
0000000000000000 A _kernel_offset_le_hi32
0000000000000000 A _kernel_size_le_hi32
000000000000000a A _kernel_flags_le_lo32
0000000000000200 A PECOFF_FILE_ALIGNMENT
0000000000080000 A _kernel_offset_le_lo32
00000000001ad808 A __pecoff_data_rawsize
0000000000215000 A __pecoff_data_size
00000000011d0518 A __rela_offset
00000000012e6000 A _kernel_size_le_lo32
ffff000008080000 t _head
ffff000008080000 T _text
ffff000008080800 T __exception_text_start
|
kallsyms是如何生成的?
详细阅读下这里的代码即可 //KernelPatchQEMU/scripts/kallsyms.c,
在内核编译之前kallsyms会遍历搜索并生成对应的汇编文件.
具体细节自己探索探索.
https://vscode.dev/github/nzcv/KernelPatchQEMU/blob/master/scripts/kallsyms.c#L347
深入理解kptools里面analyze_kallsym_info
在我们掌握必备的基础知识之后, 我们来感受下作者是如何通过特征, 一步步找到自己想要的运行时参数的. 先简单画个图, 领会下意图.
https://vscode.dev/github/nzcv/KernelPatchQEMU/blob/master/.tmp_kallsyms1.S#L215122
可以查看kallsym对应的源码.
https://vscode.dev/github/nzcv/KernelPatchQEMU/blob/master/init/version.c#L44
1 2 3 4 5 6 7 8 9 | / * FIXED STRINGS! Don't touch! * /
const char linux_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n" ;
const char linux_proc_banner[] =
"%s version %s"
" (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ")"
" (" LINUX_COMPILER ") %s\n" ;
|
linux_banner有明显的特征.
https://vscode.dev/github/nzcv/KernelPatchQEMU/blob/master/scripts/kallsyms.c#L460
1 2 3 4 5 6 7 8 9 10 11 | output_label( "kallsyms_token_table" );
off = 0 ;
/ / https: / / vscode.dev / github / nzcv / KernelPatch / blob / old / tools / kallsym.h
/ / 对应KSYM_TOKEN_NUMS为什么是 256
for (i = 0 ; i < 256 ; i + + ) {
best_idx[i] = off;
expand_symbol(best_table[i], best_table_len[i], buf);
printf( "\t.asciz\t\"%s\"\n" , buf);
off + = strlen(buf) + 1 ;
}
printf( "\n" );
|
kallsyms_token_table代码生成实现, 可以辅助阅读kptools对应代码.
最后
个人觉得读懂kptools的代码一定要理解内核符号表的原理, 不必急于求成,理解了就看懂了。最后欢迎充电,分享技术:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2024-10-12 17:50
被周晓梦Chew编辑
,原因: