使用 kprobe 修改(窃取)Linux 系统调用

问题描述 投票:0回答:1

我试图窃取 Linux 6.8 上的

statx
系统调用并修改返回参数。

但是,当尝试加载模块时,我在第 行遇到了关于 NULL 指针引用的 BUG

r = strncpy_from_user(path, (char __user *)user_regs->si, 128);

这是我的代码:

我使用这个问题(无法从 kprobe 处理程序读取系统调用参数)。 但我确实设法处理了这个争论。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kprobes.h> 

MODULE_VERSION("v.0");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Flavien <flav> ASTRAUD <[email protected]>");
MODULE_DESCRIPTION("ex. pour interception d'un syscall");

static int m_statx(struct kretprobe_instance *ri, struct pt_regs *regs)
{
    long r = 0;
    char path[128];
    struct pt_regs *user_regs = (struct pt_regs *)regs->di;
    struct statx statxbuf; // (struct statx *) regs->r8;

    r = strncpy_from_user(path, (char __user *)user_regs->si, 128);
    
    r = copy_from_user(&statxbuf, (struct statx *)user_regs->r8,
               sizeof (struct statx));

    pr_info("STATX_V3 %s size=%lld\n", path, statxbuf.stx_size);

    statxbuf.stx_size = 42;

    r = copy_to_user((struct statx *)user_regs->r8,
             &statxbuf, sizeof(statxbuf));

    return 0;
}

static struct kretprobe kret = { 
    //  .symbol_name = "__x64_sys_statx", 
    .handler = m_statx,
};

static int override_statx(void)
{
    kret.kp.symbol_name = "__x64_sys_statx";
    if (register_kretprobe(&kret) < 0) 
        return 0; 
    return 0;
}

static void pullback_syscall(void)
{
    unregister_kretprobe(&kret);
    
    return;
}

static int __init kstatx_init(void)
{
    pr_info("kstatx INIT\n=============\n");

    override_statx();

    return 0;
}

static void __exit kstatx_exit(void)
{
        pr_info("kstatx END\n=============\n"); 
    
    pullback_syscall();
}

module_init(kstatx_init);
module_exit(kstatx_exit);

c linux linux-kernel system-calls
1个回答
0
投票

这是@tsyvarev 帮助下的解决方案

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kprobes.h> 

MODULE_VERSION("v.0");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("flav <[email protected]>");
MODULE_DESCRIPTION("ex. pour interception d'un syscall");

struct my_data {
    char *ppath;
    struct statx *s_statx;
};

static int m_statx_pre(struct kretprobe_instance *ri, struct pt_regs *regs)
{
    struct my_data *data;
    char *ppath;

    pr_info("STATX entry\n");
    ppath = (char *)((struct pt_regs *)regs->di)->si;
    struct statx *statx = (struct statx *)((struct pt_regs *)regs->di)->r8;

    data = (struct my_data *)ri->data;
    data->s_statx = statx;
    data->ppath = ppath;

    return 0;
}

static int m_statx(struct kretprobe_instance *ri, struct pt_regs *regs)
{
    
    struct my_data *data;
    
    
    
    long r = 0;
    char path[128];

    struct statx statxbuf;

    data = (struct my_data *)ri->data;
    r = strncpy_from_user(path, data->ppath, 128);
    
    r = copy_from_user(&statxbuf, data->s_statx, sizeof (struct statx));

    pr_info("STATX_V3 %s size=%lld\n", path, statxbuf.stx_size);
    pr_info("STATX_ret: [%s]\n", path);


    statxbuf.stx_size = 42;
    statxbuf.stx_uid = 42;
    statxbuf.stx_gid = 42;

    r = copy_to_user(data->ppath, path, strlen(path)+1);
    r = copy_to_user(data->s_statx, &statxbuf, sizeof(statxbuf));

    return 0;
}

static struct kretprobe kret = { 
    .handler = m_statx,
    .entry_handler = m_statx_pre,
    .data_size = sizeof (struct my_data),
};

static int override_statx(void)
{
    kret.kp.symbol_name = "__x64_sys_statx";
    if (register_kretprobe(&kret) < 0) 
        return 0; 
    return 0;
}

static void pullback_syscall(void)
{
    unregister_kretprobe(&kret);
    
    return;
}

static int __init kstatx_init(void)
{
    pr_info("kstatx INIT\n=============\n");

    override_statx();

    return 0;
}

static void __exit kstatx_exit(void)
{
        pr_info("kstatx END\n=============\n"); 
    
    pullback_syscall();
}

module_init(kstatx_init);
module_exit(kstatx_exit);

没有模块:

# stat kparm.ko 
  File: kparm.ko
  Size: 302816          Blocks: 592        IO Block: 4096   regular file
Device: 252,0   Inode: 393542      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)

# ls -ln kparm.ko 
-rw-r--r-- 1 0 0 302816 Oct  7 10:23 kparm.ko

使用模块:

# stat kparm.ko 
  File: kparm.ko
  Size: 42              Blocks: 592        IO Block: 4096   regular file
Device: 252,0   Inode: 393542      Links: 1
Access: (0644/-rw-r--r--)  Uid: (   42/    _apt)   Gid: (   42/  shadow)

# ls -ln kparm.ko 
-rw-r--r-- 1 42 42 42 Oct  7 10:23 kparm.ko
© www.soinside.com 2019 - 2024. All rights reserved.