hook
技术就是针对函数的操纵,那么指定函数的获取则必然是需要的,除了operations
这种内核函数指针获取函数的方式,2.6版本后引入了导出符号
的机制。而内核函数也分为导出和非导出,也就是只有在内核中使用了EXPORT_SYMBOL
或者EXPORT_SYMBOL_GPL
导出的符号才能在内核模块中直接使用。
不管是导出的还是未导出的,可以通过这些方法来获取到指定函数的地址或者指定地址的函数
kallsyms_lookup_name
,这本身也是一个内核符号因此只有在导出后才能被使用,只有在编译内核时启用CONFIG_KALLSYMS
编译内核才行,而且获取到的是内核中的虚拟地址。
sprint_symbol
根据内存地址获取到内核符号存入buffer
,本身呢返回是一个int
,所查找的内核符号可以是本就存在于内核中的符号,也可以是位于动态插入的模块中的符号。
- 从
System.map
中直接获取到对应信息
$ cat /usr/src/linux-4.18.16.arch1/System.map | grep proc_pid_readdir
ffffffff812e3c50 T proc_pid_readdir
这是在编译内核时产生的文件,记录了编译时候内核符号的地址,但是问题就是这种方法对于运行时动态插入的内核模块并不支持,而且文件本身必须与当前内核对应。
-
/proc/kallsyms
文件中获取信息 这也是一个虚拟文件,在读取时由内核动态生成内容,因此地址一定是正确的,但是2.6.37
以后普通用户无法读到符号地址,但是据说内核符号数量上少于System.map
-
vmlinuz
$ nnm vmlinux|grep proc_root_readdir
不过这个我在我的发行版系统上使用并没有输出内核符号,应该还是内核编译的问题,而且是静态的地址,所以不推荐此方式