zergRush (CVE-2011-3874) 安卓内核漏洞成因分析

部分内容参考自http://www.cnblogs.com/daishuo/p/4002963.html

zergRush是我接触的第一个CVE漏洞,该漏洞影响安卓2.2-2.3.6版本系统。CVE-2011-3874描述得很明白,这个漏洞的本质是"use after free"。

漏洞存在于/system/bin/vold这个root身份的系统程序。具体地,vold调用了libsysutils.so,真正有问题的是这个 so。对应源码在/system/core/libsysutils/src/FrameworkListener.cpp的 FrameworkListener::dispatchCommand方法。

FrameworkListener.cpp源码

  1 bool FrameworkListener::onDataAvailable(SocketClient *c) {
  2     char buffer[255];
  3     int len;
  4
  5     if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
  6         SLOGE("read() failed (%s)", strerror(errno));
  7         return errno;
  8     } else if (!len)
  9         return false;
 10
 11     int offset = 0;
 12     int i;
 13
 14     for (i = 0; i < len; i++) {
 15         if (buffer[i] == ‘\0‘) {
 16             dispatchCommand(c, buffer + offset);
 17             offset = i + 1;
 18         }
 19     }
 20     return true;
 21 }

 27 void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
 28     FrameworkCommandCollection::iterator i;
 29     int argc = 0;
 30     char *argv[FrameworkListener::CMD_ARGS_MAX];    //数组长度固定
 31     char tmp[255];
 32     char *p = data;
 33     char *q = tmp;
 34     bool esc = false;
 35     bool quote = false;
 36     int k;
 37
 38     memset(argv, 0, sizeof(argv));
 39     memset(tmp, 0, sizeof(tmp));
 40     while(*p) {
 41         if (*p == ‘\\‘) {
 42             if (esc) {
 43                 *q++ = ‘\\‘;
 44                 esc = false;
 45             } else
 46                 esc = true;
 47             p++;
 48             continue;
 49         } else if (esc) {
 50             if (*p == ‘"‘)
 51                 *q++ = ‘"‘;
 52             else if (*p == ‘\\‘)
 53                 *q++ = ‘\\‘;
 54             else {
 55                 cli->sendMsg(500, "Unsupported escape sequence", false);
 56                 goto out;
 57             }
 58             p++;
 59             esc = false;
 60             continue;
 61         }
 62
 63         if (*p == ‘"‘) {
 64             if (quote)
 65                 quote = false;
 66             else
 67                 quote = true;
 68             p++;
 69             continue;
 70         }
 71
 72         *q = *p++;
 73         if (!quote && *q == ‘ ‘) {
 74             *q = ‘\0‘;
 75             argv[argc++] = strdup(tmp);      //没有检查长度
 76             memset(tmp, 0, sizeof(tmp));
 77             q = tmp;
 78             continue;
 79         }
 80         q++;
 81     }
 82
 83     argv[argc++] = strdup(tmp);
 84 #if 0
 85     for (k = 0; k < argc; k++) {
 86         SLOGD("arg[%d] = ‘%s‘", k, argv[k]);
 87     }
 88 #endif
 89
 90     if (quote) {
 91         cli->sendMsg(500, "Unclosed quotes error", false);
 92         goto out;
 93     }
 94
 95     for (i = mCommands->begin(); i != mCommands->end(); ++i) {
 96         FrameworkCommand *c = *i;
 97
 98         if (!strcmp(argv[0], c->getCommand())) {
 99             if (c->runCommand(cli, argc, argv)) {
100                 SLOGW("Handler ‘%s‘ error (%s)", c->getCommand(), strerror(errno));
101             }
102             goto out;
103         }
104     }
105
106     cli->sendMsg(500, "Command not recognized", false);
107 out:
108     int j;
109     for (j = 0; j < argc; j++)
110         free(argv[j]);
111     return;
112 }

1.程序流程逻辑

1-1.onDataAvailable方法监听socket输入,接收数据包后以‘\0‘为分隔符,将buffer内容分段传给dispatchCommand函数做进一步处理。

比如收到"aaa bbb ccc\0ddd eeee ff\0"
第一次传递"aaa bbb ccc\0" 第一个a的pos给dispatchCommand
第二次传递"ddd eeee ff\0" 第一个d的pos给dispatchCommand

1-2.dispatchCommand将接受的字符串以空格分割,调用strdup函数在堆中生成复制,把堆中地址保存到argv数组

"aaa bbb ccc\0"被保存成
argv[0]=&"aaa"
argv[1]=&"bbb"
argv[2]=&"ccc"

1-3.95行开始,将argv[0]与FrameworkCommand内置命令比对,若匹配执行命令,因此argv[0]是命令,argv[1]开始是对应的参数

1-4.执行完命令后free argv数组(因为strdup是在堆中生成复制,所以free理所当然)

107 out:
108     int j;
109     for (j = 0; j < argc; j++)
110         free(argv[j]);
111     return;
112 }

2.漏洞代码

 30     char *argv[FrameworkListener::CMD_ARGS_MAX];    //数组长度固定
 31     char tmp[255];
 72         *q = *p++;
 73         if (!quote && *q == ‘ ‘) {
 74             *q = ‘\0‘;
 75             argv[argc++] = strdup(tmp);      //没有检查长度
 76             memset(tmp, 0, sizeof(tmp));
 77             q = tmp;
 78             continue;
 79         }
 80         q++;
 81     }
 82
 83     argv[argc++] = strdup(tmp);

30行定义的定长数组,但75行向数组加元素时没检查边界,导致数组越界,CMD_ARGS_MAX=16,因此操作argv[16]实际覆盖了tmp的前4个字节

3.利用思路

108     int j;
109     for (j = 0; j < argc; j++)
110         free(argv[j]);
111     return;

109行有个free,在越界后可以free掉tmp中的内容。现在的思路是控制argv数组的内容,但argv本身不可控(因为都是strdup返回地址),若tmp内容可控,则实现了free(任意地址),恰好可以这么做。

最后一次数组元素时(83行)保证了tmp的前几个字节是攻击者构造的命令的参数,也就是argv[16]开始可以被攻击者控制

攻击字符串
"00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee xx \x78\x56\x34\x12 \xdd\xcc\xbb\xaa"

整理argv数组的操作后
argv[0] = &"00"
argv[1] = &"11"
.
.
argv[15] = &"ee"
argv[16] = 0xaabbccdd
argv[17] = &"\x78\x56\x34\x12"
argv[18] = &"\xdd\xcc\xbb\xaa"

这时在110行free(argv[16])可以free(任意地址)

107 out:
108     int j;
109     for (j = 0; j < argc; j++)
110         free(argv[j]);
111     return;
112 }

可以利用free来攻击虚函数。

zergRush攻击的思路先free对象c,这时这片堆空间恢复成空闲态,当有新的申请时这个空间很可能再次被分配,若能控制新申请时堆中的内容,则相当于控制了虚表内容。

幸运的是程序允许我们这么干。

 95     for (i = mCommands->begin(); i != mCommands->end(); ++i) {
 96         FrameworkCommand *c = *i;
 97
 98         if (!strcmp(argv[0], c->getCommand())) {
 99             if (c->runCommand(cli, argc, argv)) {
100                 SLOGW("Handler ‘%s‘ error (%s)", c->getCommand(), strerror(errno));
101             }
102             goto out;
103         }

具体的,99行的runCommand函数是虚函数,先想办法得到c的地址填入argv[17],在free时free掉c

之后的思路是想办法在调用c->runCommand前将c的堆空间内容控制住,若这时向dispatchCommand传入新的命令片段,则在第一次strdup时有可能申请的堆空间就是刚刚c的空间,恰好strdup的堆块内容是传入的参数的复制品,若构造好参数则控制了堆中内容,也就控制了虚表。这时程序执行到c->runCommand时就劫持了控制流。

时间: 2024-10-10 00:45:19

zergRush (CVE-2011-3874) 安卓内核漏洞成因分析的相关文章

CVE-2014-0321漏洞成因分析

1. 简介 最近在补之前落下的想学的东西,古河之前已经在微薄里面公布了此漏洞的poc及利用思路,不过在看古河的文章前我先独立分析一下其漏洞成因,记录下自己的分析流程. 2. 实验环境 操作系统:Win8.1 x86 RTM 浏览器:Internet Explorer 11 32bits (补丁打到KB2909921) 漏洞编号:CVE-2014-0321 微软补丁:MS14-012 3. 漏洞分析 3.1. 分析Crash 3.1.1. 运行poc,查看crash 直接运行poc,崩溃后查看状态

Android内核漏洞利用技术实战:环境搭建&amp;栈溢出实战

前言 Android的内核采用的是 Linux 内核,所以在Android内核中进行漏洞利用其实和在 一般的 x86平台下的 linux 内核中进行利用差不多.主要区别在于 Android 下使用的是arm汇编以及环境的搭建方面.本文对我最近的实践做一个分享,其实很简单. 内核调试环境搭建 搭建平台: ubuntu 16.04 这里使用 android 模拟器来进行内核调试.首先下载内核代码 git clone https://aosp.tuna.tsinghua.edu.cn/kernel/g

通付盾安全加固——拓展安卓内核安全边界

2014年对于移动支付来说,是充满分水岭意义和充满挑战的一年.随着智能终端的不断发展,尤其是苹果公司的iPad.iPhone等产品的普及以及Android开放系统的崛起,颠覆了传统的移动终端市场格局.手机从一个只能打电话.发短信的板砖,华丽变身成为我们赖以生存的"护身符",我们用它来购物.导航.交友.转账.订餐.订票等等,使我们终于告别了收银台.告别了排长队.告别了奔走相见的时代,这对于速食社会下的我们无疑是最大的福音. 我们似乎可以在这样一个时代下安然无恙地享受移动金融带来的种种美好

阿里安全称发现安卓WiFi漏洞:黑客可远程攻击

近日,阿里安全研究实验室发现了安卓系统的一个重大漏洞,主要影响安卓WiFi功能组件wpa_supplicant.通过该漏洞,黑客可对开启了WiFi的安卓手机发动远程攻击,甚至可窃取手机内的照片.通讯录等重要信息,因此该漏洞被称为 “WiFi杀手”.据悉,谷歌在接到阿里安全提交的漏洞细节后,及时告知了安卓系统wpa_supplicant组件的开发厂商.今日凌晨,该组件开发者公告称漏洞已修复.阿里安全研究实验室建议受影响的安卓用户尽快安装更新补丁. 阿里安全发现安卓WiFi漏洞 黑客可远程攻击 安卓

基于自适应热补丁的Android内核漏洞生态修复方案

1. 背景 Android内核漏洞严重影响了Android平台的安全.一旦内核被攻破,所有依赖内核完整性的安全机制都岌岌可危(比如加密.进程隔离.支付.指纹验证等).作为Android平台最后的防线,TrustZone也会受到威胁,因为内核可以从很多被信任的接口向TrustZone发起攻击.因此,理想情况下Android生态圈应该及时消灭内核漏洞.然而从Google的Android Security Bulletin上看,Android内核漏洞的数量呈飞快上涨的趋势(Figure 1所示).虽然

内核漏洞学习—熟悉HEVD

一直以来内核漏洞安全给很多人的印象就是:难,枯燥.但是内核安全是否掌握是衡量一个系统安全工程师水平的标准之一,也是安全从业人员都应该掌握的基本功.本文通过详细的实例带领读者走进内核安全的大门.难度系数:四颗星 原文地址:https://hshrzd.wordpress.com/2017/06/05/starting-with-windows-kernel-exploitation-part-2/ 由prison翻译整理,首发i春秋. 本文默认读者已经配置好了基本实验环境,因为环境配置网络上有大量

CVE-2014-0322漏洞成因与利用分析

CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了对漏洞的利用,第一次分析这种IE+Flash组合的漏洞利用因此写下此文档作为记录. 2. 实验环境 操作系统:Win7 SP1 浏览器:IE 10.0.9200.16798(补丁打到MS14-010(KB2909921)) 漏洞编号:CVE-2014-0322 微软补丁:MS14-012 3. 漏洞

CVE-2013-3897漏洞成因与利用分析(UAF类漏洞分析流程)

CVE-2013-3897漏洞成因与利用分析(UAF类漏洞分析流程) 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存.攻击者可以利用此类漏洞实现远程代码执行.UAF漏洞的根源源于对对象引用计数的处理不当,比如在编写程序时忘记AddRef或者多加了Release,最终导致对象的释放.对于IE的大部分对象(COM编程实现)来说,+4偏移处的含义是该对象的引用计数,可以通过跟踪它来定位补丁前后的位置及被释放的位置.+0偏移处的含义是该对象的虚函数表指针,可以通

安卓APP漏洞有哪些?在线免费App漏洞检测!

       针对智能手机的恶意软件早在几年前就已经出现了,不过直到2012年,手机安全问题才忽然成为了大众谈论的焦点.作为专业的移动互联网APP安全服务提供商爱加密来说,很早就开始着手于APP安全领域,为开发者们提供安全检测.应用保护.渠道检测等专业服务,全方位的保护APP安全,防止盗版.山寨.二次打包.注入恶意代码等现象的出现. 据了解,打包党通过APP应用存在的漏洞进行破解打包,形成山寨产品,流入市场给用户和开发者造成利益损害.我们所了解的Android应用程序存在的漏洞主要有:源代码存在