首页
社区
课程
招聘
[原创]逆向进入内核时代之APatch源码学习(04.内核符号表)
发表于: 2024-10-12 17:16 3853

[原创]逆向进入内核时代之APatch源码学习(04.内核符号表)

2024-10-12 17:16
3853

题外话:学了有什么屁用?啥也不是

答复: KROOT,KernelSu,APatch打造最强瑞士军刀

进入正题

话不多说,且听这回分解,通过前一章节, 我们了解到Kptools的核心功能是嵌入和提供一些必要的运行时参数, 而这些参数:

  1. 要么从外部获取
  2. 要么运行时拦截查找
    这是我们必须要解答的问题, 这里面牵扯的知识点比较复杂, 其中核心知识点是KAllSyms, 也就是内核符号表.

这里我们站在前人的肩膀上学习, 再结合自身实践。
89dK9s2c8@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:/ # echo 0 > /proc/sys/kernel/kptr_restrict
thyme:/ # cat /proc/kallsyms > /sdcard/syms.txt
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
#include <asm/types.h>
#if BITS_PER_LONG == 64
#define PTR .quad
#define ALGN .align 8
#else
#define PTR .long
#define ALGN .align 4
#endif
    .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会遍历搜索并生成对应的汇编文件.

具体细节自己探索探索.
8acK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6$3M7$3y4G2k6r3g2Q4x3X3g2V1k6i4k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3V1k6F1P5X3y4$3i4K6u0r3d9$3g2J5L8X3g2D9f1r3q4@1j5$3S2c8c8f1#2g2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2M7%4c8W2M7W2)9J5c8Y4y4U0M7X3W2H3N6s2y4Q4x3V1k6C8j5h3I4D9M7%4W2E0M7#2)9J5k6h3y4Q4x3U0y4x3x3K6b7%4

深入理解kptools里面analyze_kallsym_info

在我们掌握必备的基础知识之后, 我们来感受下作者是如何通过特征, 一步步找到自己想要的运行时参数的. 先简单画个图, 领会下意图.

图片描述

cd2K9s2c8@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有明显的特征.
46bK9s2c8@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#L14
//对应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的代码一定要理解内核符号表的原理, 不必急于求成,理解了就看懂了。最后欢迎充电,分享技术:
图片描述


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-10-12 17:50 被周晓梦Chew编辑 ,原因:
收藏
免费 6
支持
分享
最新回复 (1)
雪    币: 1503
活跃值: (3694)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2024-10-14 13:19
0
游客
登录 | 注册 方可回帖
返回