浅析CVE-2011-3874(zergRush)

本文详细分析了CVE-2011-3874漏洞,该漏洞是由于Linux内核中的use after free问题导致的安全风险。通过栈溢出,攻击者可以控制具有root权限的vold进程执行system(),从而实现提权。文章介绍了漏洞的描述、代码分析、利用方法和修复措施。
摘要由CSDN通过智能技术生成

 

 

 

0x0 漏洞信息

 

 

 

https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2011-3874

 

 

 

0x1 漏洞描述

 

 

漏洞的本质是"use after free".具有root权限的vold进程使用了libsysutils.so,其中某个函数存在栈溢出的问题,因此可以控制root身份的vold执行system(),借以提权.

 

 

0x2 代码分析

漏洞存在于/system/core/libsysutils/src/FrameworkListener.cpp的FrameworkListener::dispatchCommand方法

 

#define CMD_ARGS_MAX 16
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) 
{
    FrameworkCommandCollection::iterator i;
    int argc = 0;
    //在栈上分配了一个固定大小的数组argv
    char *argv[FrameworkListener::CMD_ARGS_MAX];
    char tmp[255];
    char *p = data;
    char *q = tmp;
    bool esc = false;
    bool quote = false;
    int k;

    //省略无关代码
    .....

    if (!quote && *q == ' ') 
    {
            *q = '\0';
            //填充数组的时候没有检测是否越界
            argv[argc++] = strdup(tmp);
            memset(tmp, 0, sizeof(tmp));
            q = tmp;
            continue;
        }
}


onDataAvailable方法监听socket输入,接收数据包后以'\0'为分隔符,将buffer内容分段传给dispatchCommand函数做进一步处理.dispatchCommand将接受的字符串以空格分割,调用strdup函数在堆中生成复制,把堆中地址保存到argv数组.但在argv数组越界,与tmp发生重叠的情况下,假设有一条命令带有17个参数,
"cmd x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 \x78\x56\x34\x12"

 

argv[0] == "cmd";
argv[1] == "x1";
argv[2] == "x2";
argv[3] == "x3";
argv[4] == "x4";
argv[5] == "x5";
argv[6] == "x6";
argv[7] == "x7";
argv[8] == "x8";
argv[9] == "x9";
argv[10] == "x10";
argv[11] == "x11";
argv[12] == "x12";
argv[13] == "x13";
argv[14] == "x14";
argv[15] == "x15";
argv[16] == 0x12345678;
argv[17] == "\x78\x56\x34\x12";


argv数组大小只有16项,argv[16]实际上是tmp数组的前4个字节,而最后一个参数是"\x78\x56\x34\x12",它被解析出来后缓存到tmp里,这样tmp的前4字节就成了0x78,0x56, 0x34,0x12 ,因此argv[16]==0x12345678.之后,argv[16]被free,即执行了free(0x12345678).我们可以任意控制参数内容,即可实现:free(任意地址).

 

 

 

0x3 如何利用

 

可以通过free来攻击虚函数.zergRush攻击的思路是先free对象C,这片堆空间恢复成空闲状态,再重新占用对象地址,进而覆盖vtable实现控制.

 

 

 

for (i = mCommands->begin(); i != mCommands->end(); ++i) 
{
    FrameworkCommand *c = *i;
  
    if (!strcmp(argv[0], c->getCommand())) 
    {
    	//runCommand函数是虚函数,先想办法得到c的地址填入argv[17],在free时free掉c
        if (c->runCommand(cli, argc, argv)) 
        {
            SLOGW("Handler ‘%s‘ error (%s)", c->getCommand(), strerror(errno));
        }
            goto out;
    }
}

 

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

 

 

0x4 Poc

 

/* android 2.2/2.3 libsysutils root exploit use-after-free
 *
 * Exploited by rewriting a FrameworkCommand object making the runCommand
 * point to our first ROP gadget.
 *
 * Copyright (c) 2011, The Revolutionary development team.
 *
 * Before using, insert empty formatted sdcard. USE IT AT YOUR OWN RISK,
 * THIS PROGRAM MIGHT NOT WORK OR MAKES YOUR DEVICE USELESS/BRICKED.  SO BE
 * WARNED!  I AM NOT RESPONSIBLE FOR ANY DAMAGE IT MIGHT CAUSE!
 *
 * It only works if called from adb shell since we need group log.
 *
 * Compile:
 * agcc zergRush.c -o zergRush -ldiskconfig -lcutils
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值