subprocess_info 结构体


背景分析

下面分析 以下modeprobe_path的作用:

执行一个错误文件头的时候,调用链如下:

直接看exec_binprm函数,在一个depth的循环中迭代,调用到search_binary_handler:

进入到searchPbinary_handler函数,可以看到首先进行安全性检查,然后会通过一个叫做“list_for_head“的宏来遍历formats这个全局变量:

formats全局变量定义在这里,是一个双链表结构:

调试format如下,

具体的一个elf_format如下:

具体的汇编如下,就是直接和format的地址作比较,应该是预先通过文件名字找了一个format?:

总之如果找不到一个format,且need_retry == true的情况下,就会进入到如下代码中调用request_module:

最终调用到call_usermodehelper(从全局变量modeprobe_path中获取路径),这就是一个内核调用用户层程序的例子,这个程序是以特权运行的。

源码分析

回到subprocess_info:

其触发分配的代码如下:

#include <sys/socket.h>

int main(){

​ socket(22, AF_INET, 0);

}

函数调用栈帧如下:

可以看到是走了call_usermodehelper_set,这个函数的作用是创建一个subprocess_info:https://elixir.bootlin.com/linux/v5.19/source/kernel/umh.c#L358

调试一下看看在本环境下该结构体的大小:

然后到https://elixir.bootlin.com/linux/v5.19/source/kernel/kmod.c中看一下 __request_module函数:

其会通过call_modprobe函数来调用call_usermodehelper_setup,但是我们的栈帧中没有,且这个函数也不是内联的:

setup之后就会exec:

如果此时info的path是NULL,就会free info,就会调用导subprocess_info的cleanup函数指针:

利用方法

因此,当我们有能力篡改一个subprocess_info结构体的时候,就可以将其path设置为0,将其cleanup指针设置为目标函数,即可实现控制流的劫持;

参考

https://www.anquanke.com/post/id/236126#h2-0

https://x3h1n.github.io/2019/10/10/ret2dir%E5%88%A9%E7%94%A8%E5%AD%A6%E4%B9%A0/


文章作者: q1ming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1ming !
  目录