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

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

2024-10-12 17:16
2791

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

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

进入正题

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

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

这里我们站在前人的肩膀上学习, 再结合自身实践。
https://www.cnblogs.com/jianhua1992/p/16852796.html

什么是内核符号表?

内核符号表(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会遍历搜索并生成对应的汇编文件.

具体细节自己探索探索.
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#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的代码一定要理解内核符号表的原理, 不必急于求成,理解了就看懂了。最后欢迎充电,分享技术:
图片描述


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

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