-
-
[原创]逆向进入内核时代之APatch源码学习(04.内核符号表)
-
发表于:
2024-10-12 17:16
3852
-
[原创]逆向进入内核时代之APatch源码学习(04.内核符号表)
题外话:学了有什么屁用?啥也不是
答复: KROOT,KernelSu,APatch打造最强瑞士军刀
进入正题
话不多说,且听这回分解,通过前一章节, 我们了解到Kptools的核心功能是嵌入和提供一些必要的运行时参数, 而这些参数:
- 要么从外部获取
- 要么运行时拦截查找
这是我们必须要解答的问题, 这里面牵扯的知识点比较复杂, 其中核心知识点是KAllSyms, 也就是内核符号表.
这里我们站在前人的肩膀上学习, 再结合自身实践。
41bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0L8X3u0D9L8$3N6K6i4K6u0W2j5$3!0E0i4K6u0r3K9X3W2S2L8X3S2#2j5e0p5&6z5e0u0Q4x3V1k6H3i4K6u0r3x3e0j5^5y4e0t1%4z5e0k6Q4x3X3g2Z5N6r3#2D9
什么是内核符号表?
内核符号表(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会遍历搜索并生成对应的汇编文件.
具体细节自己探索探索.
c28K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6$3M7$3y4G2k6r3g2Q4x3X3g2V1k6i4k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3V1k6F1P5X3y4$3i4K6u0r3d9$3g2J5L8X3g2D9f1r3q4@1j5$3S2c8c8f1#2g2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8Y4y4U0M7X3W2H3N6s2y4Q4x3V1k6C8j5h3I4D9M7%4W2E0M7#2)9J5k6h3y4Q4x3U0y4x3x3K6b7%4
深入理解kptools里面analyze_kallsym_info
在我们掌握必备的基础知识之后, 我们来感受下作者是如何通过特征, 一步步找到自己想要的运行时参数的. 先简单画个图, 领会下意图.

11cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6$3M7$3y4G2k6r3g2Q4x3X3g2V1k6i4k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3V1k6F1P5X3y4$3i4K6u0r3d9$3g2J5L8X3g2D9f1r3q4@1j5$3S2c8c8f1#2g2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8W2)9J5k6i4c8E0M7q4)9#2k6X3E0S2L8r3I4K6P5h3#2K6x3g2)9J5k6g2y4Q4x3U0y4x3x3U0p5#2x3e0t1J5
可以查看kallsym对应的源码.
26fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6$3M7$3y4G2k6r3g2Q4x3X3g2V1k6i4k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3V1k6F1P5X3y4$3i4K6u0r3d9$3g2J5L8X3g2D9f1r3q4@1j5$3S2c8c8f1#2g2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8X3W2F1K9i4c8Q4x3V1k6$3k6i4u0K6K9h3!0F1i4K6u0W2j5#2)9J5x3@1H3@1y4l9`.`.
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有明显的特征.
551K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6$3M7$3y4G2k6r3g2Q4x3X3g2V1k6i4k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3V1k6F1P5X3y4$3i4K6u0r3d9$3g2J5L8X3g2D9f1r3q4@1j5$3S2c8c8f1#2g2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8Y4y4U0M7X3W2H3N6s2y4Q4x3V1k6C8j5h3I4D9M7%4W2E0M7#2)9J5k6h3y4Q4x3U0y4x3y4o6j5H3
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的代码一定要理解内核符号表的原理, 不必急于求成,理解了就看懂了。最后欢迎充电,分享技术:

[培训]科锐逆向工程师培训第53期2025年7月8日开班!
最后于 2024-10-12 17:50
被周晓梦Chew编辑
,原因: