iOS 逆向工程 app安全 网络安全

神来之笔,2021CTF内核漏洞精选解析

2021-07-13  本文已影响0人  顶峰相见8号

0x0 保护

#!/bin/sh

qemu-system-x86_64 \
    -m 512M \
    -kernel bzImage \
    -nographic \
    -smp 1 \
    -cpu kvm64,+smep,+smap \
    -append "console=ttyS0 quiet kaslr" \
    -initrd rootfs.cpio \
    -monitor /dev/null \
    --no-reboot \
    -s

开启的保护:

SMEP SMAP KPTI

0x1 源码分析

file_operations可以看出这是一个内核下的菜单题目,提供add、delete、show、append功能。

static const struct file_operations file_ops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = handle_ioctl,
};

static long handle_ioctl(struct file *f, unsigned int cmd, unsigned long arg){
    long ret;

    req* args = kmalloc(sizeof(req), GFP_KERNEL);
    copy_from_user(args, arg, sizeof(req));

    if (cmd == 0x13371){
        ret = create(args);
    }
    else if (cmd == 0x13372){
        ret = delete(args);
    }
    else if (cmd == 0x13373){
        ret = show(args);
    }
    else if (cmd == 0x13374){
        ret = append(args);
    }
    else{
        ret = -EINVAL;
    }
    return ret;
}

关于create函数:限制申请0 - 1024大小的堆块,会先通过read_contents申请一个大小content_length临时堆块,用来存放用户输入的内容,然后再申请size大小的堆块来存入临时堆块的内容,并把地址放到nuts数组里。但是如果content_length设置为为0,就会只申请size的堆块,不会申请临时堆块,这一点可以用于泄漏信息。

static int create(req* arg){
    int size = read_size(arg);
    char* contents = read_contents(arg);
    int i;

    for (i = 0; i < 10; i++){
        if (nuts[i].contents == NULL){
            break;
        }
    }

    if (i == 10){
        printk(KERN_INFO "creation error");
        return -EINVAL;
    }

    if (size < 0 || size >= 1024){
        printk(KERN_INFO "bad size");
        return -EINVAL;
    }
    nuts[i].size = size;
    nuts[i].contents = kmalloc(size, GFP_KERNEL);
    if (contents != 0){
        memcpy_safe(nuts[i].contents, contents, size);  //size > length , read heap overflow.
        kfree(contents);
    }
    else {
        printk("bad content length!");
        return -EINVAL;
    }

    return 0;
}

// Return a content ptr which will be alloced in kernel.
static char* read_contents(req* arg){
    char* to_read = (char*) arg->contents;
    int content_length = arg->content_length;
    if (content_length <= 0){
        printk(KERN_INFO "bad content length");
        return 0;
    }
    char* res = kmalloc(content_length, GFP_KERNEL);
    copy_from_user(res, to_read, content_length);
    return res;
}

关于delete函数:没啥可说的。只是kfree指定堆块,并清空nuts数组在此处的信息。

static int delete(req* arg){
    int idx = read_idx(arg);
    if (idx < 0 || idx >= 10){
        return -EINVAL;
    }
    if (nuts[idx].contents == NULL){
        return -EINVAL;
    }
    printk(KERN_INFO "deleting at 0x%px", nuts[idx].contents);
    kfree(nuts[idx].contents);
    nuts[idx].contents = NULL;
    nuts[idx].size = 0;

    return 0;
}

关于show函数:输出nuts数组内指定堆块的信息。

static int show(req* arg){
    int idx = read_idx(arg);
    if (idx < 0 || idx >= 10){
        return -EINVAL;
    }
    if (nuts[idx].contents == NULL){
        return -EINVAL;
    }
    copy_to_user(arg->show_buffer, nuts[idx].contents, nuts[idx].size);

    return 0;
}

关于append函数:用户提供的size加上nuts数组上指定堆块的size成为新的size,申请新的堆块先存放旧堆块的内容,然后再在之后填入新的内容。kfree掉旧的堆块,更新nuts数组。

static int append(req* arg){
    int idx = read_idx(arg);
    if (idx < 0 || idx >= 10){
        return -EINVAL;
    }
    if (nuts[idx].contents == NULL){
        return -EINVAL;
    }

    int new_size = read_size(arg) + nuts[idx].size;
    if (new_size < 0 || new_size >= 1024){
        printk(KERN_INFO "bad new size!\n");
        return -EINVAL;
    }
    char* tmp = kmalloc(new_size, GFP_KERNEL);
    memcpy_safe(tmp, nuts[idx].contents, nuts[idx].size);
    kfree(nuts[idx].contents);
    char* appended = read_contents(arg);
    if (appended != 0){
        memcpy_safe(tmp+nuts[idx].size, appended, new_size - nuts[idx].size);
        kfree(appended);
    }
    nuts[idx].contents = tmp;
    nuts[idx].size = new_size;

    return 0;
}

0x2 漏洞点

漏洞点有两个地方:

0x3 利用思路

0x4 Exploit

Mech0n/UnionCTF-nutty.c

image.png

我是一名安全渗透工程师,希望本文对CTF感兴趣的伙伴们有所帮助,还有更多网络安全学习视频、工具包、逆向、应急响应等架构技术需要的戳我

在这里插入图片描述

在这里插入图片描述

最后,感谢大家阅读,喜欢的记得一键三连~

上一篇下一篇

猜你喜欢

热点阅读