本文主要介绍三种方法抓取sys_call_table的地址
方法一:以sys_close为参考,遍历内存
方法二:直接抓/proc/kallsyms
方法三:调用函数syscall_table = (unsigned long*)kallsyms_lookup_name(“sys_call_table”);
方法四:sudo cat /boot/System.mapxxxxx | grep sys_call_table
test.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/syscalls.h>
#include <linux/kallsyms.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("curits li");
MODULE_DESCRIPTION("HELLO");
MODULE_VERSION("1.0");
unsigned long *syscall_table;
struct module *mod;
/*
* run over the memory till find the sys call talbe
* doing so, by searching the sys call close.
* kernel version over 5.3 using ksys_close.
*/
//方式一,遍历内存查找
unsigned long * obtain_syscall_table_bf(void)
{
unsigned long *syscall_table;
unsigned long int i;
for (i = (unsigned long int)sys_close; i < ULONG_MAX;
i += sizeof(void *)) {
syscall_table = (unsigned long *)i;
if (syscall_table[__NR_close] == (unsigned long)sys_close)
return syscall_table;
}
return NULL;
}
unsigned long *
get_sct(void)
{
return obtain_syscall_table_bf();
}
static int hello_init(void)
{
printk("%s\n", "Greetings the World!");
// struct module *mod;
syscall_table = get_sct();
printk("PAGE_OFFSET = %lx\n", PAGE_OFFSET);
printk("syscall_table = %p\n", syscall_table);
//方式二,直接使用shell命令
//system("cat /proc/kallsyms | grep -w sys_call_table | awk '{print $1}'");
//方式三,需要添加头文件
printk("sys_call_table address is: %lx\n",kallsyms_lookup_name("sys_call_table"));
printk(KERN_ALERT "this module: %p==%p\n", &__this_module, THIS_MODULE );
printk(KERN_ALERT "module state: %d\n", THIS_MODULE->state );
printk(KERN_ALERT "module name: %s\n", THIS_MODULE->name );
printk(KERN_ALERT"module version:%s\n",THIS_MODULE->version);
list_for_each_entry(mod, *(&THIS_MODULE->list.prev), list )
printk(KERN_ALERT "module name: %s\n", mod->name );
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "module state: %d\n", THIS_MODULE->state );
printk("find_module bye...\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile:
CONFIG_MODULE_SIG=n
ifeq ($(KERNELRELEASE),)
ROOTS_DIR = /root/
#内核源码路径,不同环境可能会不一样,内核源码一定要先编译
KERNEL_DIR = /lib/modules/$(shell uname -r)/build
CUR_DIR = $(shell pwd)
all:
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
clean :
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
install:
insmod test.ko
uninstall:
rmmod test
else
#用于指定到底编译的是哪个代码--hello.c
obj-m += test.o
#obj-m += math.o
endif
在编译驱动代码的时候报错
warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
从报错的信息很直观的可以看出是因为“ISO C90 禁止将声明和代码混合”,也就是说结构体 struct module *mod 因该在函数外进行声明,把结构体声明放在开头,编译不再由warming。
结尾粘上效果:
[22919.816516] PAGE_OFFSET = ffff880000000000
[22919.816517] syscall_table = ffffffff816beee0
[22919.819755] sys_call_table address is: ffffffff816beee0
[22919.819757] this module: ffffffffc06da000==ffffffffc06da000