【linux内核-获取hook系统调用表】

本文的目标是学习如何使用获取系统调用表,通过替换系统调用,可以做很多事情;想要替换系统函数首要的问题就是获取系统调用表 system call table。

演示环境:

uname -ra
Linux localhost.localdomain 3.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core)

系统调用表,根据名字就可以猜到是一个表(实现是数组)里面放了很多的系统调用函数。
获取之后,就可以通过数组下标来寻找对用的系统函数。
下标可以通过查看内核源码得知:arch/x86/include/generated/uapi/asm/unistd_32.h
在这里插入图片描述

第一种:通过内核导出函数kallsyms_lookup_name获取:

  • 条件:需要内核开启CONFIG_KALLSYMS配置
cat /boot/config-3.10.0-693.el7.x86_64 | grep CONFIG_KALLSYMS
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y

核心代码:

 //kallsyms_lookup_name need be export, need CONFIG_KALLSYMS when compile kernel
  void* sys_table_addr = (void*) kallsyms_lookup_name("sys_call_table"); 

完整代码:

#include <linux/init.h> // 模块初始化和退出
#include <linux/module.h>
#include <linux/kallsyms.h>
 // 内核的一些基本信息,主要是modinfo显示
MODULE_AUTHOR("andy");
MODULE_DESCRIPTION("test");
MODULE_LICENSE("GPL");
MODULE_VERSION("v1.1.0");
 
void getsystab()
{
   
        void *sys_table_addr = (void *) kallsyms_lookup_name("sys_call_table");
        if (sys_table_addr) 
        {
   
                printk("addr:%p \n", sys_table_addr);
        }
}
 
static int patch_init(void)
{
   
        printk("[testkern]init\n");
        getsystab();
        return 0;
}
 
static void patch_exit(void){
   
        printk("[testkern]exit\n");
        return ;
}
 
// 入口 
module_init(patch_init);
// 退出
module_exit(patch_exit);

dmesg查看执行结果:
[535528.128860] [testkern]init
[535528.131788] addr:ffffffff816beee0

第二种:通过读取system.map文件获取

本质是通过下面的命令获取
cat /boot/System.map-3.10.0-693.el7.x86_64 | grep sys_call_table
完整代码:

#include <linux/init.h> // 模块初始化和退出
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include<linux/slab.h> //kfree

#define PROC_V    "/proc/version"
#define BOOT_PATH "/boot/System.map-"
#define MAX_VERSION_LEN   256

 // 内核的一些基本信息,主要是modinfo显示
MODULE_AUTHOR("andy");
MODULE_DESCRIPTION("test");
MODULE_LICENSE("GPL");
MODULE_VERSION("v1.1.0");
 
// 主要是通过读取文件 获取内核的版本信息
char *acquire_kernel_version (char *buf) {
   
    struct file *proc_version;
    char *kernel_version;
  
    mm_segment_t oldfs;
    oldfs = get_fs();
    set_fs (KERNEL_DS);
 	
    // 打开版本信息 
    proc_version = filp_open(PROC_V, O_RDONLY, 0);
    if (IS_ERR(proc_version) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值