linux 内核基础 八 modprobe提权

2022-11-07

什么是modprobe

modprobe是一个内置的linux系统命令,用于安装/卸载 LKM(loadable kernel module),它是一个内核全局变量,可以通过以下的命令进行查看:

modprobe和 insmod/rmmod的区别

众所周知,linux中还内置了另一组用于安装/卸载 LKM的命令 insmod/rmmod,modprobe和这组命令相比起来是有区别的。

  1. modprobe可以解决 加载模块 的依赖关系,比如加载module a前必须加载module b,modprobe可以通过 /lib/modules/uname -r/modules.dep 查找依赖关系
  2. modprobe 需要在/lib/modules/uname -r/ 下查找module,而insmod可以在当前目录下直接装载

如何利用modprobe进行内核提权

modprobe之所以可以进行内核提权,一个很重要的原因是, modprobe的路径(默认情况下是/sbin/modprobe)存储在内核本身的modprobe_path符号中,并且该页面是可写的
另一个原因是
在我们执行(exec)一个未知类型的文件时(magic number,魔数)(文件抬头没有被识别),系统会调用,会产生以下调用,最终调用到modprobe

entry_SYSCALL_64()
    sys_execve()
        do_execve()
            do_execveat_common()
                bprm_execve()
                    exec_binprm()
                        search_binary_handler()
                            __request_module() // wrapped as request_module
                                call_modprobe()

其中 call_modprobe的源码如下(5.14)kernel/kmod.c

static int call_modprobe(char *module_name, int wait)
{
    //...

    argv[0] = modprobe_path;
    argv[1] = "-q";
    argv[2] = "--";
    argv[3] = module_name;    /* check free_modprobe_argv() */
    argv[4] = NULL;

    info = call_usermodehelper_setup(modprobe_path, argv, envp, GFP_KERNEL,
                     NULL, free_modprobe_argv, NULL);

    if (!info)
        goto free_module_name;

    return call_usermodehelper_exec(info, wait | UMH_KILLABLE);
    //...

内核会以 root 权限来执行modprobe,如果我们能够劫持modprobe_path并将其指向我们自己的程序,那么就能成功完成利用

modprobe提权的利用条件

(1)知道modprobe_path的地址;
(2)知道kpti_trampoline(即swapgs_restore_regs_and_return_to_usermode函数)的地址,以便在覆写modprobe_path之后干净地返回到用户空间;
(3)有任意写入原语。

references

https://blog.csdn.net/vevenlcf/article/details/78884672
https://blog.csdn.net/weixin_45619852/article/details/121102283
https://www.anquanke.com/post/id/232545