最近(终于)转Android了,2011年著名的zergrush是接触的第一个ROOT漏洞。虽然它已经过气了,只影响Android 2.2 - 2.3.6,但觉得还是有必要记录一下分析所得。
市面上各种ROOT工具基本都包含zergrush,大多是开源的zergRush.c直接编译而来。已有的分析文章:
tomken_zhang,漏洞 — zergRush,漏洞 — zergRush (补充)
Claud, Android提权代码zergRush分析
分析内容集中在zergRush.c的代码结构上,对漏洞原理没有解析,或者错误地认为是栈溢出。其实CVE-2011-3874已经描述得很明白,这个漏洞的本质是"use after free"。
1. 栈溢出?No.
漏洞存在于/system/bin/vold这个root身份的系统程序。具体地,vold调用了libsysutils.so,真正有问题的是这个so。再具体地,问题出在/system/core/libsysutils/src/FrameworkListener.cpp的FrameworkListener::dispatchCommand方法。
它在栈上分配了一个固定大小的数组argv,
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { FrameworkCommandCollection::iterator i; int argc = 0; char *argv[FrameworkListener::CMD_ARGS_MAX]; char tmp[255]; char *p = data; char *q = tmp; bool esc = false; bool quote = false; int k;
FrameworkListener::CMD_ARGS_MAX = 16。但后面填充argv数组时,代码并没有检查是否发生了越界。
if (!quote && *q == ' ') { *q = '